<commit_before>use async_std::net::*;
use futures::channel::mpsc;
use futures::prelude::*;
use futures::stream::FusedStream;
use nhanh::*;
use std::collections::HashMap;
use std::ffi::c_void;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::thread::{self, JoinHandle};
use std::sync::Arc;

pub const MAX_CHANNELS: u64 = 256;

#[allow(warnings)]
mod enet {
    include!(concat!(env!("OUT_DIR"), "/enet.rs"));
}

#[derive(Debug)]
struct NewPeer {
    peer: u64,
    peer_event_stream: mpsc::UnboundedReceiver<Datagram>,
}

struct EnetCmd {
    peer: u64,
    channel: u8,
    data: Vec<u8>,
}

pub struct EnetServer {
    marker: Arc<()>,
    new_peer_stream: mpsc::UnboundedReceiver<NewPeer>,
    command_sink: mpsc::Sender<EnetCmd>,
}

async fn socket_addr_to_enet_addr(
    addr: impl ToSocketAddrs,
) -> enet::ENetAddress {
    let socket_address = addr
        .to_socket_addrs()
        .await
        .expect("addresses")
        .next()
        .expect("address");

    unsafe {
        let mut address: enet::ENetAddress = std::mem::uninitialized();
        address.host = match socket_address.ip() {
            IpAddr::V4(v4) => u32::from_le_bytes(v4.octets()),
            _ => panic!("Enet does not support ipv6"),
        };
        address.port = socket_address.port();
        address
    }
}

impl EnetServer {
    pub async fn bind(address: impl ToSocketAddrs) -> Self {
        let address = socket_addr_to_enet_addr(address).await;

        let (command_sink, command_stream) = mpsc::channel(0);
        let (new_peer_sink, new_peer_stream) = mpsc::unbounded();

        let marker = Arc::new(());

        std::thread::spawn(enet_service_loop(
                marker.clone(),
            command_stream,
            new_peer_sink,
            HostType::Server,
            address,
        ));

        Self {
            marker,
            new_peer_stream,
            command_sink,
        }
    }
}

impl Server<EnetConnection> for EnetServer {}

impl FusedStream for EnetServer {
    fn is_terminated(&self) -> bool {
        self.new_peer_stream.is_terminated()
    }
}

impl Stream for EnetServer {
    type Item = Result<EnetConnection>;
    fn poll_next(
        mut self: Pin<&mut Self>,
        ctx: &mut Context,
    ) -> Poll<Option<Self::Item>> {
        let new_peer = match Pin::new(&mut self.new_peer_stream).poll_next(ctx)
        {
            Poll::Pending => return Poll::Pending,
            Poll::Ready(Some(event)) => event,
            Poll::Ready(None) => return Poll::Ready(None),
        };

        Poll::Ready(Some(Ok(EnetConnection {
            marker: self.marker.clone(),
            peer: new_peer.peer,
            command_sink: self.command_sink.clone(),
            peer_event_stream: new_peer.peer_event_stream,
        })))
    }
}

pub struct EnetConnection {
    marker: Arc<()>,
    peer: u64,
    command_sink: mpsc::Sender<EnetCmd>,
    peer_event_stream: mpsc::UnboundedReceiver<Datagram>,
}

impl EnetConnection {
    pub async fn connect(server_addr: impl ToSocketAddrs) -> Self {
        let address = socket_addr_to_enet_addr(server_addr).await;

        let (command_sink, command_stream) = mpsc::channel(0);
        let (new_peer_sink, mut new_peer_stream) = mpsc::unbounded();

        let marker = Arc::new(());

        std::thread::spawn(enet_service_loop(
                marker.clone(),
            command_stream,
            new_peer_sink,
            HostType::Client,
            address,
        ));

        let peer = new_peer_stream.next().await.expect("connection to server");
        Self {
            marker,
            peer: peer.peer,
            command_sink,
            peer_event_stream: peer.peer_event_stream,
        }
    }
}

impl Connection for EnetConnection {}

impl FusedStream for EnetConnection {
    fn is_terminated(&self) -> bool {
        self.peer_event_stream.is_terminated()
    }
}

impl Stream for EnetConnection {
    type Item = Result<Datagram>;
    fn poll_next(
        mut self: Pin<&mut Self>,
        ctx: &mut Context,
    ) -> Poll<Option<Self::Item>> {
        Pin::new(&mut self.peer_event_stream)
            .poll_next(ctx)
            .map(|d| d.map(Ok))
    }
}

impl Sink<SendCmd> for EnetConnection {
    type Error = Box<dyn std::error::Error>;
    fn poll_ready(
        mut self: Pin<&mut Self>,
        ctx: &mut Context,
    ) -> Poll<Result<()>> {
        Pin::new(&mut self.command_sink)
            .poll_ready(ctx)
            .map_err(Into::into)
    }
    fn start_send(mut self: Pin<&mut Self>, item: SendCmd) -> Result<()> {
        let channel = match item.delivery_mode {
            DeliveryMode::ReliableOrdered(StreamId(channel)) => channel as u8,
            _ => panic!("benchmark only supports reliable ordered datagrams"),
        };

        let peer = self.peer;
        Pin::new(&mut self.command_sink)
            .start_send(EnetCmd {
                peer,
                channel,
                data: item.data,
            })
            .map_err(Into::into)
    }
    fn poll_flush(
        mut self: Pin<&mut Self>,
        ctx: &mut Context,
    ) -> Poll<Result<()>> {
        Pin::new(&mut self.command_sink)
            .poll_flush(ctx)
            .map_err(Into::into)
    }
    fn poll_close(
        mut self: Pin<&mut Self>,
        ctx: &mut Context,
    ) -> Poll<Result<()>> {
        Pin::new(&mut self.command_sink)
            .poll_close(ctx)
            .map_err(Into::into)
    }
}

enum HostType {
    Server,
    Client,
}

impl HostType {
    fn create(&self, server_addr: enet::ENetAddress) -> *mut enet::ENetHost {
        unsafe {
            let host = match self {
                HostType::Server => {
                    enet::enet_host_create(&server_addr, 32, MAX_CHANNELS, 0, 0)
                }
                HostType::Client => {
                    let client = enet::enet_host_create(
                        0 as *const enet::ENetAddress,
                        32,
                        2,
                        0,
                        0,
                    );
                    assert!(
                        enet::enet_host_connect(
                            client,
                            &server_addr,
                            MAX_CHANNELS,
                            0,
                        ) != 0 as *mut enet::ENetPeer
                    );
                    client
                }
            };
            assert!(host != 0 as *mut enet::ENetHost);
            host
        }
    }
}

fn enet_service_command(command: EnetCmd) {
    let packet = unsafe {
        enet::enet_packet_create(
            command.data.as_ptr() as *const c_void,
            command.data.len() as u64,
            enet::_ENetPacketFlag_ENET_PACKET_FLAG_RELIABLE,
        )
    };

    unsafe {
        let peer = command.peer as *mut enet::ENetPeer;
        enet::enet_peer_send(peer, command.channel, packet)
    };
}

fn enet_service_loop(
    marker: Arc<()>,
    mut command_stream: mpsc::Receiver<EnetCmd>,
    mut new_peer_sink: mpsc::UnboundedSender<NewPeer>,
    host_type: HostType,
    server_addr: enet::ENetAddress,
) -> impl FnOnce() {
    move || {
        assert_eq!(unsafe { enet::enet_initialize() }, 0);

        let host = host_type.create(server_addr);
        let mut total_sent = 0;
        let mut peers = HashMap::new();
        loop {
            if Arc::strong_count(&marker) == 1 {
                return;
            }

            match command_stream.try_next().transpose() {
                Some(command) => command,
                None => return,
            }
            .ok()
            .into_iter()
            .for_each(enet_service_command);

            let mut event: enet::ENetEvent =
                unsafe { std::mem::uninitialized() };
            while unsafe {
                enet::enet_host_service(
                    host,
                    { &mut event as *mut enet::ENetEvent },
                    /*ms=*/ 1,
                )
            } > 0
            {
                match event.type_ {
                    enet::_ENetEventType_ENET_EVENT_TYPE_CONNECT => {
                        let (peer_event_sink, peer_event_stream) =
                            mpsc::unbounded();
                        assert!(
                            peers.insert(event.peer, peer_event_sink).is_none(),
                            "Peer already connected."
                        );
                        new_peer_sink
                            .unbounded_send(NewPeer {
                                peer: event.peer as u64,
                                peer_event_stream,
                            })
                            .expect("sending new peer event");
                    }
                    enet::_ENetEventType_ENET_EVENT_TYPE_DISCONNECT => {
                        peers.remove(&event.peer);
                    }
                    enet::_ENetEventType_ENET_EVENT_TYPE_RECEIVE => {
                        let sink =
                            peers.get_mut(&event.peer).expect("peer sink");
                        let data: &'static [u8] = unsafe {
                            let packet = &mut *event.packet;
                            std::slice::from_raw_parts(
                                packet.data,
                                packet.dataLength as usize,
                            )
                        };
                        sink.unbounded_send(Datagram {
                            data: data.to_vec(),
                            stream_position: Some(StreamPosition {
                                stream_id: StreamId(event.channelID),
                                index: StreamIndex::Ordinal(total_sent),
                            }),
                        })
                        .expect("sending peer the event");

                        total_sent += 1;
                    }
                    e => println!("other event type: {:?}", e),
                }
            }
        }
    }
}
<commit_msg>Dequeue all available commands<commit_after>use async_std::net::*;
use futures::channel::mpsc;
use futures::prelude::*;
use futures::stream::FusedStream;
use nhanh::*;
use std::collections::HashMap;
use std::ffi::c_void;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::thread::{self, JoinHandle};

pub const MAX_CHANNELS: u64 = 256;

#[allow(warnings)]
mod enet {
    include!(concat!(env!("OUT_DIR"), "/enet.rs"));
}

#[derive(Debug)]
struct NewPeer {
    peer: u64,
    peer_event_stream: mpsc::UnboundedReceiver<Datagram>,
}

struct EnetCmd {
    peer: u64,
    channel: u8,
    data: Vec<u8>,
}

pub struct EnetServer {
    marker: Arc<()>,
    new_peer_stream: mpsc::UnboundedReceiver<NewPeer>,
    command_sink: mpsc::Sender<EnetCmd>,
}

async fn socket_addr_to_enet_addr(
    addr: impl ToSocketAddrs,
) -> enet::ENetAddress {
    let socket_address = addr
        .to_socket_addrs()
        .await
        .expect("addresses")
        .next()
        .expect("address");

    unsafe {
        let mut address: enet::ENetAddress = std::mem::uninitialized();
        address.host = match socket_address.ip() {
            IpAddr::V4(v4) => u32::from_le_bytes(v4.octets()),
            _ => panic!("Enet does not support ipv6"),
        };
        address.port = socket_address.port();
        address
    }
}

impl EnetServer {
    pub async fn bind(address: impl ToSocketAddrs) -> Self {
        let address = socket_addr_to_enet_addr(address).await;

        let (command_sink, command_stream) = mpsc::channel(0);
        let (new_peer_sink, new_peer_stream) = mpsc::unbounded();

        let marker = Arc::new(());

        std::thread::spawn(enet_service_loop(
            marker.clone(),
            command_stream,
            new_peer_sink,
            HostType::Server,
            address,
        ));

        Self {
            marker,
            new_peer_stream,
            command_sink,
        }
    }
}

impl Server<EnetConnection> for EnetServer {}

impl FusedStream for EnetServer {
    fn is_terminated(&self) -> bool {
        self.new_peer_stream.is_terminated()
    }
}

impl Stream for EnetServer {
    type Item = Result<EnetConnection>;
    fn poll_next(
        mut self: Pin<&mut Self>,
        ctx: &mut Context,
    ) -> Poll<Option<Self::Item>> {
        let new_peer = match Pin::new(&mut self.new_peer_stream).poll_next(ctx)
        {
            Poll::Pending => return Poll::Pending,
            Poll::Ready(Some(event)) => event,
            Poll::Ready(None) => return Poll::Ready(None),
        };

        Poll::Ready(Some(Ok(EnetConnection {
            marker: self.marker.clone(),
            peer: new_peer.peer,
            command_sink: self.command_sink.clone(),
            peer_event_stream: new_peer.peer_event_stream,
        })))
    }
}

pub struct EnetConnection {
    marker: Arc<()>,
    peer: u64,
    command_sink: mpsc::Sender<EnetCmd>,
    peer_event_stream: mpsc::UnboundedReceiver<Datagram>,
}

impl EnetConnection {
    pub async fn connect(server_addr: impl ToSocketAddrs) -> Self {
        let address = socket_addr_to_enet_addr(server_addr).await;

        let (command_sink, command_stream) = mpsc::channel(0);
        let (new_peer_sink, mut new_peer_stream) = mpsc::unbounded();

        let marker = Arc::new(());

        std::thread::spawn(enet_service_loop(
            marker.clone(),
            command_stream,
            new_peer_sink,
            HostType::Client,
            address,
        ));

        let peer = new_peer_stream.next().await.expect("connection to server");
        Self {
            marker,
            peer: peer.peer,
            command_sink,
            peer_event_stream: peer.peer_event_stream,
        }
    }
}

impl Connection for EnetConnection {}

impl FusedStream for EnetConnection {
    fn is_terminated(&self) -> bool {
        self.peer_event_stream.is_terminated()
    }
}

impl Stream for EnetConnection {
    type Item = Result<Datagram>;
    fn poll_next(
        mut self: Pin<&mut Self>,
        ctx: &mut Context,
    ) -> Poll<Option<Self::Item>> {
        Pin::new(&mut self.peer_event_stream)
            .poll_next(ctx)
            .map(|d| d.map(Ok))
    }
}

impl Sink<SendCmd> for EnetConnection {
    type Error = Box<dyn std::error::Error>;
    fn poll_ready(
        mut self: Pin<&mut Self>,
        ctx: &mut Context,
    ) -> Poll<Result<()>> {
        Pin::new(&mut self.command_sink)
            .poll_ready(ctx)
            .map_err(Into::into)
    }
    fn start_send(mut self: Pin<&mut Self>, item: SendCmd) -> Result<()> {
        let channel = match item.delivery_mode {
            DeliveryMode::ReliableOrdered(StreamId(channel)) => channel as u8,
            _ => panic!("benchmark only supports reliable ordered datagrams"),
        };

        let peer = self.peer;
        Pin::new(&mut self.command_sink)
            .start_send(EnetCmd {
                peer,
                channel,
                data: item.data,
            })
            .map_err(Into::into)
    }
    fn poll_flush(
        mut self: Pin<&mut Self>,
        ctx: &mut Context,
    ) -> Poll<Result<()>> {
        Pin::new(&mut self.command_sink)
            .poll_flush(ctx)
            .map_err(Into::into)
    }
    fn poll_close(
        mut self: Pin<&mut Self>,
        ctx: &mut Context,
    ) -> Poll<Result<()>> {
        Pin::new(&mut self.command_sink)
            .poll_close(ctx)
            .map_err(Into::into)
    }
}

enum HostType {
    Server,
    Client,
}

impl HostType {
    fn create(&self, server_addr: enet::ENetAddress) -> *mut enet::ENetHost {
        unsafe {
            let host = match self {
                HostType::Server => {
                    enet::enet_host_create(&server_addr, 32, MAX_CHANNELS, 0, 0)
                }
                HostType::Client => {
                    let client = enet::enet_host_create(
                        0 as *const enet::ENetAddress,
                        32,
                        2,
                        0,
                        0,
                    );
                    assert!(
                        enet::enet_host_connect(
                            client,
                            &server_addr,
                            MAX_CHANNELS,
                            0,
                        ) != 0 as *mut enet::ENetPeer
                    );
                    client
                }
            };
            assert!(host != 0 as *mut enet::ENetHost);
            host
        }
    }
}

fn enet_service_command(command: EnetCmd) {
    let packet = unsafe {
        enet::enet_packet_create(
            command.data.as_ptr() as *const c_void,
            command.data.len() as u64,
            enet::_ENetPacketFlag_ENET_PACKET_FLAG_RELIABLE,
        )
    };

    unsafe {
        let peer = command.peer as *mut enet::ENetPeer;
        enet::enet_peer_send(peer, command.channel, packet)
    };
}

fn enet_service_loop(
    marker: Arc<()>,
    mut command_stream: mpsc::Receiver<EnetCmd>,
    mut new_peer_sink: mpsc::UnboundedSender<NewPeer>,
    host_type: HostType,
    server_addr: enet::ENetAddress,
) -> impl FnOnce() {
    move || {
        assert_eq!(unsafe { enet::enet_initialize() }, 0);

        let host = host_type.create(server_addr);
        let mut total_sent = 0;
        let mut peers = HashMap::new();
        loop {
            if Arc::strong_count(&marker) == 1 {
                return;
            }

            while let Ok(command) = match command_stream.try_next().transpose()
            {
                Some(command) => command,
                None => return,
            } {
                enet_service_command(command);
            }

            let mut event: enet::ENetEvent =
                unsafe { std::mem::uninitialized() };
            while unsafe {
                enet::enet_host_service(
                    host,
                    { &mut event as *mut enet::ENetEvent },
                    /*ms=*/ 1,
                )
            } > 0
            {
                match event.type_ {
                    enet::_ENetEventType_ENET_EVENT_TYPE_CONNECT => {
                        let (peer_event_sink, peer_event_stream) =
                            mpsc::unbounded();
                        assert!(
                            peers.insert(event.peer, peer_event_sink).is_none(),
                            "Peer already connected."
                        );
                        new_peer_sink
                            .unbounded_send(NewPeer {
                                peer: event.peer as u64,
                                peer_event_stream,
                            })
                            .expect("sending new peer event");
                    }
                    enet::_ENetEventType_ENET_EVENT_TYPE_DISCONNECT => {
                        peers.remove(&event.peer);
                    }
                    enet::_ENetEventType_ENET_EVENT_TYPE_RECEIVE => {
                        let sink =
                            peers.get_mut(&event.peer).expect("peer sink");
                        let data: &'static [u8] = unsafe {
                            let packet = &mut *event.packet;
                            std::slice::from_raw_parts(
                                packet.data,
                                packet.dataLength as usize,
                            )
                        };
                        sink.unbounded_send(Datagram {
                            data: data.to_vec(),
                            stream_position: Some(StreamPosition {
                                stream_id: StreamId(event.channelID),
                                index: StreamIndex::Ordinal(total_sent),
                            }),
                        })
                        .expect("sending peer the event");

                        total_sent += 1;
                    }
                    e => println!("other event type: {:?}", e),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate rle_vec;

use std::iter::FromIterator;
use std::iter::repeat;
use test::Bencher;
use rle_vec::RleVec;

#[bench]
fn rle_iterate_1_000_unique_values(b: &mut Bencher) {
    let rle = RleVec::from_iter(0..10_000);
    b.iter(|| {
        for (i, v) in rle.iter().enumerate() {
            assert_eq!(i, *v);
        }
    })
}

#[bench]
fn vec_iterate_1_000_unique_values(b: &mut Bencher) {
    let vec = Vec::from_iter(0..10_000);
    b.iter(|| {
        for (i, v) in vec.iter().enumerate() {
            assert_eq!(i, *v);
        }
    })
}

#[bench]
fn rle_iterate_1_000_equal_values(b: &mut Bencher) {
    let rle = RleVec::from_iter(repeat(0).take(10_000));
    b.iter(|| {
        for v in rle.iter() {
            assert_eq!(*v, 0);
        }
    })
}

#[bench]
fn vec_iterate_1_000_equal_values(b: &mut Bencher) {
    let vec = Vec::from_iter(repeat(0).take(10_000));
    b.iter(|| {
        for v in vec.iter() {
            assert_eq!(*v, 0);
        }
    })
}

#[bench]
fn rle_iterate_1_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let rle = RleVec::from_iter(iter);
    b.iter(|| {
        for v in rle.iter() {
            assert!(*v == 0 || *v == 1); // ugly
        }
    })
}

#[bench]
fn vec_iterate_1_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let vec = Vec::from_iter(iter);
    b.iter(|| {
        for v in vec.iter() {
            assert!(*v == 0 || *v == 1); // ugly
        }
    })
}

#[bench]
fn rle_random_access_all_from_1_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let rle = RleVec::from_iter(iter);
    let len = rle.len();
    b.iter(|| {
        for i in 0..len {
            let _ = rle[i];
        }
    })
}

#[bench]
fn vec_random_access_all_from_1_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let vec = Vec::from_iter(iter);
    let len = vec.len();
    b.iter(|| {
        for i in 0..len {
            let _ = vec[i];
        }
    })
}
<commit_msg>Fix names and reduce test length<commit_after>#![feature(test)]

extern crate test;
extern crate rle_vec;

use std::iter::FromIterator;
use std::iter::repeat;
use test::Bencher;
use rle_vec::RleVec;

#[bench]
fn rle_iterate_10_000_unique_values(b: &mut Bencher) {
    let rle = RleVec::from_iter(0..10_000);
    b.iter(|| {
        for (i, v) in rle.iter().enumerate() {
            assert_eq!(i, *v);
        }
    })
}

#[bench]
fn vec_iterate_10_000_unique_values(b: &mut Bencher) {
    let vec = Vec::from_iter(0..10_000);
    b.iter(|| {
        for (i, v) in vec.iter().enumerate() {
            assert_eq!(i, *v);
        }
    })
}

#[bench]
fn rle_iterate_10_000_equal_values(b: &mut Bencher) {
    let rle = RleVec::from_iter(repeat(0).take(10_000));
    b.iter(|| {
        for v in rle.iter() {
            assert_eq!(*v, 0);
        }
    })
}

#[bench]
fn vec_iterate_10_000_equal_values(b: &mut Bencher) {
    let vec = Vec::from_iter(repeat(0).take(10_000));
    b.iter(|| {
        for v in vec.iter() {
            assert_eq!(*v, 0);
        }
    })
}

#[bench]
fn rle_iterate_1_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let rle = RleVec::from_iter(iter);
    b.iter(|| {
        for v in rle.iter() {
            assert!(*v == 0 || *v == 1); // ugly
        }
    })
}

#[bench]
fn vec_iterate_1_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let vec = Vec::from_iter(iter);
    b.iter(|| {
        for v in vec.iter() {
            assert!(*v == 0 || *v == 1); // ugly
        }
    })
}

#[bench]
fn rle_random_access_1_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let rle = RleVec::from_iter(iter);
    let len = rle.len();
    b.iter(|| {
        let mut i = 5;
        while i < len {
            let _ = rle[i];
            i += 10;
        }
    })
}

#[bench]
fn vec_random_access_1_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let vec = Vec::from_iter(iter);
    let len = vec.len();
    b.iter(|| {
        let mut i = 5;
        while i < len {
            let _ = vec[i];
            i += 10;
        }
    })
}
<|endoftext|>


<commit_before>extern crate permutohedron;
use permutohedron::Heap;

pub fn chain(input: &[(usize, usize)]) -> Option<Vec<(usize, usize)>> {
    if input.is_empty() {
        return Some(vec![]);
    }

    let mut input_as_vec = input.iter().cloned().collect::<Vec<_>>();
    let input_permutations = Heap::new(&mut input_as_vec);
    let mut solution = Vec::new();
    for permutation in input_permutations {
        let mut cur_cell = permutation[0];
        let first_cell = cur_cell;
        solution.push(cur_cell);
        for &(x, y) in permutation.iter().skip(1) {
            if cur_cell.1 == x {
                cur_cell = (x, y);
                solution.push(cur_cell);
            } else if cur_cell.1 == y {
                cur_cell = (y, x);
                solution.push(cur_cell);
            }
        }
        // if len of solution is the same as the len of input we need to check if
        // the first digit is the same as the last one
        if solution.len() == input.len() {
            if first_cell.0 == cur_cell.1 {
                // found the solution, just return and ignore the other solutions
                return Some(solution);
            }
        }
        solution.clear();
    }
    None
}
<commit_msg>More changes to Dominoes exercise<commit_after>extern crate permutohedron;
use permutohedron::Heap;

pub fn chain(input: &[(usize, usize)]) -> Option<Vec<(usize, usize)>> {
    if input.is_empty() {
        return Some(vec![]);
    }

    let mut input_as_vec = input.iter().cloned().collect::<Vec<_>>();
    let input_permutations = Heap::new(&mut input_as_vec);
    let mut solution = Vec::new();
    for permutation in input_permutations {
        let mut cur_cell = permutation[0];
        solution.push(cur_cell);
        for &(x, y) in permutation.iter().skip(1) {
            if cur_cell.1 == x {
                cur_cell = (x, y);
                solution.push(cur_cell);
            } else if cur_cell.1 == y {
                cur_cell = (y, x);
                solution.push(cur_cell);
            }
        }
        // if len of solution is the same as the len of input we need to check if
        // the first digit is the same as the last one
        if solution.len() == input.len() {
            if solution[0].0 == cur_cell.1 {
                // found the solution, just return and ignore the other solutions
                return Some(solution);
            }
        }
        solution.clear();
    }
    None
}
<|endoftext|>


<commit_before>extern crate boxcars;
extern crate failure;
extern crate rayon;
extern crate serde_json;
extern crate structopt;
extern crate globset;
#[macro_use]
extern crate structopt_derive;

use failure::{err_msg, Error, ResultExt};
use structopt::StructOpt;
use std::fs::{File, OpenOptions};
use std::io::{self, BufWriter};
use std::io::prelude::*;
use rayon::prelude::*;
use boxcars::{CrcCheck, NetworkParse, ParserBuilder, Replay};
use std::path::Path;
use globset::Glob;

#[derive(StructOpt, Debug, Clone, PartialEq)]
#[structopt(name = "rrrocket",
            about = "Parses Rocket League replay files and outputs JSON with decoded information")]
struct Opt {
    #[structopt(short = "c", long = "crc-check", help = "forces a crc check for corruption even when replay was successfully parsed")]
    crc: bool,

    #[structopt(short = "n", long = "network-parse", help = "parses the network data of a replay instead of skipping it")]
    body: bool,

    #[structopt(short = "m", long = "multiple", help = "parse multiple replays, instead of writing JSON to stdout, write to a sibling JSON file")]
    multiple: bool,

    #[structopt(help = "Rocket League replay files")] input: Vec<String>,
}

fn read_file(input: &str) -> Result<Vec<u8>, Error> {
    let mut f = File::open(input)
        .with_context(|e| format!("Could not open rocket league file: {} -- {}", input, e))?;
    let mut buffer = vec![];
    f.read_to_end(&mut buffer)
        .with_context(|e| format!("Could not read rocket league file: {} -- {}", input, e))?;
    Ok(buffer)
}

fn parse_replay<'a>(opt: &Opt, data: &'a [u8]) -> Result<Replay<'a>, Error> {
    ParserBuilder::new(&data[..])
        .with_crc_check(if opt.crc {
            CrcCheck::Always
        } else {
            CrcCheck::OnError
        })
        .with_network_parse(if opt.body {
            NetworkParse::Always
        } else {
            NetworkParse::Never
        })
        .parse()
}

fn parse_multiple_replays(opt: &Opt) -> Result<(), Error> {
    let glob = Glob::new("*.replay")?.compile_matcher();
    let v: Result<Vec<Vec<String>>, Error> = opt.input
        .iter()
        .map(|x| {
            let p = Path::new(x);
            if p.is_dir() {
                // If the commandline argument is a directory we look for all files that match
                // *.replay. A file that does not match the pattern because of an error reading the
                // directory / file will not be filtered and will cause the error to bubble up. In
                // the future, we could get smart and ignore directories / files we don't have
                // permission that wouldn't match the pattern anyways
                let files: Result<Vec<_>, _> = p.read_dir()?
                    .filter_map(|entry| {
                        match entry {
                            Ok(y) => {
                                if glob.is_match(y.path()) {
                                    // Force UTF-8. There is a special place in the fourth circle
                                    // of inferno for people who rename their rocket league replays
                                    // to not contain UTF-8. We won't panic, but will cause an
                                    // error when the file is attempted to be read.
                                    Some(Ok(y.path().to_string_lossy().into_owned()))
                                } else {
                                    None
                                }
                            }
                            Err(e) => Some(Err(e)),
                        }
                    })
                    .collect();
                Ok(files?)
            } else {
                Ok(vec![x.clone()])
            }
        })
        .collect();

     let res: Result<Vec<()>, Error> =  v?
        .into_iter()
        .flat_map(|x| x)
        .collect::<Vec<_>>()
        .par_iter()
        .map(|file| {
            let outfile = format!("{}.json", file);
            let fout = OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(true)
                .open(&outfile)
                .with_context(|e| {
                    format!(
                        "Could not open json output file: {} with error: {}",
                        outfile, e
                    )
                })?;
            let mut writer = BufWriter::new(fout);
            let data = read_file(file)?;
            let replay = parse_replay(opt, &data[..])
                .with_context(|e| format!("Could not parse: {} with error: {}", file, e))?;
            serde_json::to_writer(&mut writer, &replay).with_context(|e| {
                format!("Could not serialize replay {} to {}: {}", file, outfile, e)
            })?;
            Ok(())
        })
        .collect();
    res?;
    Ok(())
}

fn run() -> Result<(), Error> {
    let opt = Opt::from_args();
    if opt.multiple {
        parse_multiple_replays(&opt)
    } else if opt.input.len() != 1 {
        Err(err_msg(
            "Expected one input file if --multiple is not specified",
        ))
    } else {
        let file = &opt.input[0];
        let data = read_file(file)?;
        let replay = parse_replay(&opt, &data[..]).context("Could not parse replay")?;
        serde_json::to_writer(&mut io::stdout(), &replay).context("Could not serialize replay")?;
        Ok(())
    }
}

fn main() {
    if let Err(ref e) = run() {
        let mut stderr = io::stderr();
        for fail in e.causes() {
            let _ = writeln!(stderr, "{}", fail);
        }

        ::std::process::exit(1);
    }
}
<commit_msg>Extract expand paths to separate function<commit_after>extern crate boxcars;
extern crate failure;
extern crate rayon;
extern crate serde_json;
extern crate structopt;
extern crate globset;
#[macro_use]
extern crate structopt_derive;

use failure::{err_msg, Error, ResultExt};
use structopt::StructOpt;
use std::fs::{File, OpenOptions};
use std::io::{self, BufWriter};
use std::io::prelude::*;
use rayon::prelude::*;
use boxcars::{CrcCheck, NetworkParse, ParserBuilder, Replay};
use std::path::Path;
use globset::Glob;

#[derive(StructOpt, Debug, Clone, PartialEq)]
#[structopt(name = "rrrocket",
            about = "Parses Rocket League replay files and outputs JSON with decoded information")]
struct Opt {
    #[structopt(short = "c", long = "crc-check", help = "forces a crc check for corruption even when replay was successfully parsed")]
    crc: bool,

    #[structopt(short = "n", long = "network-parse", help = "parses the network data of a replay instead of skipping it")]
    body: bool,

    #[structopt(short = "m", long = "multiple", help = "parse multiple replays, instead of writing JSON to stdout, write to a sibling JSON file")]
    multiple: bool,

    #[structopt(help = "Rocket League replay files")] input: Vec<String>,
}

fn read_file(input: &str) -> Result<Vec<u8>, Error> {
    let mut f = File::open(input)
        .with_context(|e| format!("Could not open rocket league file: {} -- {}", input, e))?;
    let mut buffer = vec![];
    f.read_to_end(&mut buffer)
        .with_context(|e| format!("Could not read rocket league file: {} -- {}", input, e))?;
    Ok(buffer)
}

fn parse_replay<'a>(opt: &Opt, data: &'a [u8]) -> Result<Replay<'a>, Error> {
    ParserBuilder::new(&data[..])
        .with_crc_check(if opt.crc {
            CrcCheck::Always
        } else {
            CrcCheck::OnError
        })
        .with_network_parse(if opt.body {
            NetworkParse::Always
        } else {
            NetworkParse::Never
        })
        .parse()
}

/// Each file argument that we get could be a directory so we need to expand that directory and
/// find all the *.replay files. File arguments turn into single element vectors.
fn expand_paths(files: &[String]) -> Result<Vec<Vec<String>>, Error> {
    let glob = Glob::new("*.replay")?.compile_matcher();

    files
    .iter()
    .map(|x| {
        let p = Path::new(x);
        if p.is_dir() {
            // If the commandline argument is a directory we look for all files that match
            // *.replay. A file that does not match the pattern because of an error reading the
            // directory / file will not be filtered and will cause the error to bubble up. In
            // the future, we could get smart and ignore directories / files we don't have
            // permission that wouldn't match the pattern anyways
            let files: Result<Vec<_>, _> = p.read_dir()?
                .filter_map(|entry| {
                    match entry {
                        Ok(y) => {
                            if glob.is_match(y.path()) {
                                // Force UTF-8. There is a special place in the fourth circle
                                // of inferno for people who rename their rocket league replays
                                // to not contain UTF-8. We won't panic, but will cause an
                                // error when the file is attempted to be read.
                                Some(Ok(y.path().to_string_lossy().into_owned()))
                            } else {
                                None
                            }
                        }
                        Err(e) => Some(Err(e)),
                    }
                })
                .collect();
            Ok(files?)
        } else {
            Ok(vec![x.clone()])
        }
    })
    .collect()
}

fn parse_multiple_replays(opt: &Opt) -> Result<(), Error> {
    let res: Result<Vec<()>, Error> =
        expand_paths(&opt.input)?
        .into_iter()
        .flat_map(|x| x)
        .collect::<Vec<_>>()
        .par_iter()
        .map(|file| {
            let outfile = format!("{}.json", file);
            let fout = OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(true)
                .open(&outfile)
                .with_context(|e| {
                    format!(
                        "Could not open json output file: {} with error: {}",
                        outfile, e
                    )
                })?;
            let mut writer = BufWriter::new(fout);
            let data = read_file(file)?;
            let replay = parse_replay(opt, &data[..])
                .with_context(|e| format!("Could not parse: {} with error: {}", file, e))?;
            serde_json::to_writer(&mut writer, &replay).with_context(|e| {
                format!("Could not serialize replay {} to {}: {}", file, outfile, e)
            })?;
            Ok(())
        })
        .collect();
    res?;
    Ok(())
}

fn run() -> Result<(), Error> {
    let opt = Opt::from_args();
    if opt.multiple {
        parse_multiple_replays(&opt)
    } else if opt.input.len() != 1 {
        Err(err_msg(
            "Expected one input file if --multiple is not specified",
        ))
    } else {
        let file = &opt.input[0];
        let data = read_file(file)?;
        let replay = parse_replay(&opt, &data[..]).context("Could not parse replay")?;
        serde_json::to_writer(&mut io::stdout(), &replay).context("Could not serialize replay")?;
        Ok(())
    }
}

fn main() {
    if let Err(ref e) = run() {
        let mut stderr = io::stderr();
        for fail in e.causes() {
            let _ = writeln!(stderr, "{}", fail);
        }

        ::std::process::exit(1);
    }
}
<|endoftext|>


<commit_before>use ::cairo;
use ::glib::translate::*;
use ::glib_sys;
use ::libc;

use std::f64::consts::*;

use cairo::MatrixTrait;
use cssparser::{Parser, ParserInput, Token, ParseError as CssParseError};

use error::*;
use parsers::{Parse, ParseError, optional_comma};

impl Parse for cairo::Matrix {
    type Data = ();
    type Err = AttributeError;

    fn parse (s: &str, _: ()) -> Result<cairo::Matrix, AttributeError> {
        parse_transform (s)
    }
}

pub fn parse_transform(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let matrix = parse_transform_list(s)?;

    matrix.try_invert ().map (|_| matrix)
        .map_err (|_| AttributeError::Value ("invalid transformation matrix".to_string ()))
}

fn parse_transform_list(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let mut matrix = cairo::Matrix::identity();

    loop {
        let m = parse_transform_command(&mut parser)?;
        matrix = cairo::Matrix::multiply(&m, &matrix);

        if parser.is_exhausted() {
            break;
        }

        optional_comma(&mut parser);
    }

    Ok(matrix)
}

fn make_expected_function_error() -> AttributeError {
    AttributeError::from(ParseError::new("expected matrix|translate|scale|rotate|skewX|skewY"))
}

fn parse_transform_command(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    match parser.next()?.clone() {
        Token::Function(ref name) => parse_transform_function(name, parser),

        Token::Ident(ref name) => {
            parser.expect_parenthesis_block()?;
            parse_transform_function(name, parser)
        },

        _ => Err(make_expected_function_error()),
    }
}

fn parse_transform_function(name: &str, parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    match name {
        "matrix"    => parse_matrix_args(parser),
        "translate" => parse_translate_args(parser),
        "scale"     => parse_scale_args(parser),
        "rotate"    => parse_rotate_args(parser),
        "skewX"     => parse_skewX_args(parser),
        "skewY"     => parse_skewY_args(parser),
        _           => Err(make_expected_function_error()),
    }
}

fn parse_matrix_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let xx = p.expect_number()? as f64;
        optional_comma(p);

        let yx = p.expect_number()? as f64;
        optional_comma(p);

        let xy = p.expect_number()? as f64;
        optional_comma(p);

        let yy = p.expect_number()? as f64;
        optional_comma(p);

        let x0 = p.expect_number()? as f64;
        optional_comma(p);

        let y0 = p.expect_number()? as f64;

        Ok(cairo::Matrix::new(xx, yx, xy, yy, x0, y0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_translate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let tx = p.expect_number()?;

        optional_comma(p);

        let ty = p.expect_number()?;

        Ok(cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx as f64, ty as f64))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_scale_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let x = p.expect_number()?;

        let y = p.try(|p| -> Result<f32, CssParseError<()>> {
            optional_comma(p);
            Ok(p.expect_number()?)
        }).unwrap_or(x);

        Ok(cairo::Matrix::new(x as f64, 0.0, 0.0, y as f64, 0.0, 0.0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_rotate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let angle = p.expect_number()? as f64 * PI / 180.0;
        let (s, c) = angle.sin_cos();

        let (tx, ty) = p.try(|p| -> Result<_, CssParseError<()>> {
            optional_comma(p);
            let tx = p.expect_number()? as f64;

            optional_comma(p);
            let ty = p.expect_number()? as f64;

            Ok((tx, ty))
        }).unwrap_or((0.0, 0.0));

        let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

        m = cairo::Matrix::multiply (&cairo::Matrix::new (c, s, -s, c, 0.0, 0.0), &m);
        m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
        Ok(m)
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_skewX_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    unimplemented!();
}

fn parse_skewY_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    unimplemented!();
}

/*
pub fn parse_transform (s: &str) -> Result <cairo::Matrix, AttributeError> {
    let r = parse_TransformList (s);

    match r {
        Ok (m) => {
            m.try_invert ().map (|_| m)
                .map_err (|_| AttributeError::Value ("invalid transformation matrix".to_string ()))
        },

        Err (e) => {
            Err (AttributeError::Parse (ParseError::new (format! ("{:?}", e))))
        }
    }
}
*/

#[cfg(test)]
fn make_rotation_matrix (angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
    let angle = angle_degrees * PI / 180.0;

    let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

    let mut r = cairo::Matrix::identity ();
    r.rotate (angle);
    m = cairo::Matrix::multiply (&r, &m);

    m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
    m
}

#[no_mangle]
pub extern fn rsvg_parse_transform (out_matrix: *mut cairo::Matrix, s: *const libc::c_char) -> glib_sys::gboolean {
    assert! (!out_matrix.is_null ());
    assert! (!s.is_null ());

    let string = unsafe { String::from_glib_none (s) };
    let matrix: &mut cairo::Matrix = unsafe { &mut *out_matrix };

    match parse_transform (&string) {
        Ok (m) => {
            *matrix = m;
            true.to_glib ()
        },

        Err (_) => {
            *matrix = cairo::Matrix::identity ();
            false.to_glib ()
        }
    }
}

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

    #[test]
    #[ignore]
    fn parses_valid_transform () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }

    fn assert_parse_error(s: &str) {
        match parse_transform(s) {
            Err(AttributeError::Parse(_)) => {},
            _ => { panic!(); }
        }
    }

    #[test]
    #[ignore]
    fn syntax_error_yields_parse_error () {
        assert_parse_error("foo");
        assert_parse_error("matrix (1 2 3 4 5)");
        assert_parse_error("translate(1 2 3 4 5)");
        assert_parse_error("translate (1,)");
    }

    #[test]
    #[ignore]
    fn invalid_transform_yields_value_error () {
        match parse_transform ("matrix (0 0 0 0 0 0)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), translate (10, 10)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), skewX (90)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }
    }
}

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

    #[test]
    fn parses_matrix () {
        assert_eq! (parse_transform ("matrix (1 2 3 4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_transform ("matrix(1,2,3,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_transform ("matrix (1,2.25,-3.25e2,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.25, -325.0, 4.0, 5.0, 6.0));
    }

    #[test]
    fn parses_translate () {
        assert_eq! (parse_transform ("translate(-1 -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        // assert_eq! (parse_transform ("translate(-1, -2)").unwrap (),
        //             cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        // assert_eq! (parse_transform ("translate(-1)").unwrap (),
        //             cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, 0.0));
    }

    #[test]
    fn parses_scale() {
        assert_eq! (parse_transform ("scale (-1)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -1.0, 0.0, 0.0));

        assert_eq! (parse_transform ("scale(-1 -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_transform ("scale(-1, -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));
    }

    #[test]
    fn parses_rotate () {
        assert_eq! (parse_transform ("rotate (30)").unwrap (), make_rotation_matrix (30.0, 0.0, 0.0));
        assert_eq! (parse_transform ("rotate (30,-1,-2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
        assert_eq! (parse_transform ("rotate(30, -1, -2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
    }

    fn make_skew_x_matrix (angle_degrees: f64) -> cairo::Matrix {
        let a = angle_degrees * PI / 180.0;
        cairo::Matrix::new (1.0,      0.0,
                            a.tan (), 1.0,
                            0.0, 0.0)
    }

    fn make_skew_y_matrix (angle_degrees: f64) -> cairo::Matrix {
        let mut m = make_skew_x_matrix (angle_degrees);
        m.yx = m.xy;
        m.xy = 0.0;
        m
    }

    #[test]
    #[ignore]
    fn parses_skew_x () {
        assert_eq! (parse_transform ("skewX (30)").unwrap (), make_skew_x_matrix (30.0));
    }

    #[test]
    #[ignore]
    fn parses_skew_y () {
        assert_eq! (parse_transform ("skewY (30)").unwrap (), make_skew_y_matrix (30.0));
    }

    #[test]
    #[ignore]
    fn parses_transform_list () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        assert_eq! (parse_transform ("scale(10)rotate(30, 10, 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &s));

        assert_eq! (parse_transform ("translate(20, 30), scale (10)").unwrap (),
                    cairo::Matrix::multiply (&s, &t));

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }
}
<commit_msg>Parse the skewX / skewY transforms<commit_after>use ::cairo;
use ::glib::translate::*;
use ::glib_sys;
use ::libc;

use std::f64::consts::*;

use cairo::MatrixTrait;
use cssparser::{Parser, ParserInput, Token, ParseError as CssParseError};

use error::*;
use parsers::{Parse, ParseError, optional_comma};

impl Parse for cairo::Matrix {
    type Data = ();
    type Err = AttributeError;

    fn parse (s: &str, _: ()) -> Result<cairo::Matrix, AttributeError> {
        parse_transform (s)
    }
}

pub fn parse_transform(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let matrix = parse_transform_list(s)?;

    matrix.try_invert ().map (|_| matrix)
        .map_err (|_| AttributeError::Value ("invalid transformation matrix".to_string ()))
}

fn parse_transform_list(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let mut matrix = cairo::Matrix::identity();

    loop {
        let m = parse_transform_command(&mut parser)?;
        matrix = cairo::Matrix::multiply(&m, &matrix);

        if parser.is_exhausted() {
            break;
        }

        optional_comma(&mut parser);
    }

    Ok(matrix)
}

fn make_expected_function_error() -> AttributeError {
    AttributeError::from(ParseError::new("expected matrix|translate|scale|rotate|skewX|skewY"))
}

fn parse_transform_command(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    match parser.next()?.clone() {
        Token::Function(ref name) => parse_transform_function(name, parser),

        Token::Ident(ref name) => {
            parser.expect_parenthesis_block()?;
            parse_transform_function(name, parser)
        },

        _ => Err(make_expected_function_error()),
    }
}

fn parse_transform_function(name: &str, parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    match name {
        "matrix"    => parse_matrix_args(parser),
        "translate" => parse_translate_args(parser),
        "scale"     => parse_scale_args(parser),
        "rotate"    => parse_rotate_args(parser),
        "skewX"     => parse_skewx_args(parser),
        "skewY"     => parse_skewy_args(parser),
        _           => Err(make_expected_function_error()),
    }
}

fn parse_matrix_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let xx = p.expect_number()? as f64;
        optional_comma(p);

        let yx = p.expect_number()? as f64;
        optional_comma(p);

        let xy = p.expect_number()? as f64;
        optional_comma(p);

        let yy = p.expect_number()? as f64;
        optional_comma(p);

        let x0 = p.expect_number()? as f64;
        optional_comma(p);

        let y0 = p.expect_number()? as f64;

        Ok(cairo::Matrix::new(xx, yx, xy, yy, x0, y0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_translate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let tx = p.expect_number()?;

        optional_comma(p);

        let ty = p.expect_number()?;

        Ok(cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx as f64, ty as f64))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_scale_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let x = p.expect_number()?;

        let y = p.try(|p| -> Result<f32, CssParseError<()>> {
            optional_comma(p);
            Ok(p.expect_number()?)
        }).unwrap_or(x);

        Ok(cairo::Matrix::new(x as f64, 0.0, 0.0, y as f64, 0.0, 0.0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_rotate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let angle = p.expect_number()? as f64 * PI / 180.0;
        let (s, c) = angle.sin_cos();

        let (tx, ty) = p.try(|p| -> Result<_, CssParseError<()>> {
            optional_comma(p);
            let tx = p.expect_number()? as f64;

            optional_comma(p);
            let ty = p.expect_number()? as f64;

            Ok((tx, ty))
        }).unwrap_or((0.0, 0.0));

        let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

        m = cairo::Matrix::multiply (&cairo::Matrix::new (c, s, -s, c, 0.0, 0.0), &m);
        m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
        Ok(m)
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_skewx_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let a = p.expect_number()? as f64 * PI / 180.0;
        Ok(cairo::Matrix::new (1.0,      0.0,
                               a.tan (), 1.0,
                               0.0, 0.0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_skewy_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let a = p.expect_number()? as f64 * PI / 180.0;
        Ok(cairo::Matrix::new (1.0,  a.tan (),
                               0.0,  1.0,
                               0.0, 0.0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

/*
pub fn parse_transform (s: &str) -> Result <cairo::Matrix, AttributeError> {
    let r = parse_TransformList (s);

    match r {
        Ok (m) => {
            m.try_invert ().map (|_| m)
                .map_err (|_| AttributeError::Value ("invalid transformation matrix".to_string ()))
        },

        Err (e) => {
            Err (AttributeError::Parse (ParseError::new (format! ("{:?}", e))))
        }
    }
}
*/

#[cfg(test)]
fn make_rotation_matrix (angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
    let angle = angle_degrees * PI / 180.0;

    let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

    let mut r = cairo::Matrix::identity ();
    r.rotate (angle);
    m = cairo::Matrix::multiply (&r, &m);

    m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
    m
}

#[no_mangle]
pub extern fn rsvg_parse_transform (out_matrix: *mut cairo::Matrix, s: *const libc::c_char) -> glib_sys::gboolean {
    assert! (!out_matrix.is_null ());
    assert! (!s.is_null ());

    let string = unsafe { String::from_glib_none (s) };
    let matrix: &mut cairo::Matrix = unsafe { &mut *out_matrix };

    match parse_transform (&string) {
        Ok (m) => {
            *matrix = m;
            true.to_glib ()
        },

        Err (_) => {
            *matrix = cairo::Matrix::identity ();
            false.to_glib ()
        }
    }
}

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

    #[test]
    #[ignore]
    fn parses_valid_transform () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }

    fn assert_parse_error(s: &str) {
        match parse_transform(s) {
            Err(AttributeError::Parse(_)) => {},
            _ => { panic!(); }
        }
    }

    #[test]
    #[ignore]
    fn syntax_error_yields_parse_error () {
        assert_parse_error("foo");
        assert_parse_error("matrix (1 2 3 4 5)");
        assert_parse_error("translate(1 2 3 4 5)");
        assert_parse_error("translate (1,)");
    }

    #[test]
    #[ignore]
    fn invalid_transform_yields_value_error () {
        match parse_transform ("matrix (0 0 0 0 0 0)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), translate (10, 10)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), skewX (90)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }
    }
}

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

    #[test]
    fn parses_matrix () {
        assert_eq! (parse_transform ("matrix (1 2 3 4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_transform ("matrix(1,2,3,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_transform ("matrix (1,2.25,-3.25e2,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.25, -325.0, 4.0, 5.0, 6.0));
    }

    #[test]
    fn parses_translate () {
        assert_eq! (parse_transform ("translate(-1 -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        // assert_eq! (parse_transform ("translate(-1, -2)").unwrap (),
        //             cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        // assert_eq! (parse_transform ("translate(-1)").unwrap (),
        //             cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, 0.0));
    }

    #[test]
    fn parses_scale() {
        assert_eq! (parse_transform ("scale (-1)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -1.0, 0.0, 0.0));

        assert_eq! (parse_transform ("scale(-1 -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_transform ("scale(-1, -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));
    }

    #[test]
    fn parses_rotate () {
        assert_eq! (parse_transform ("rotate (30)").unwrap (), make_rotation_matrix (30.0, 0.0, 0.0));
        assert_eq! (parse_transform ("rotate (30,-1,-2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
        assert_eq! (parse_transform ("rotate(30, -1, -2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
    }

    fn make_skew_x_matrix (angle_degrees: f64) -> cairo::Matrix {
        let a = angle_degrees * PI / 180.0;
        cairo::Matrix::new (1.0,      0.0,
                            a.tan (), 1.0,
                            0.0, 0.0)
    }

    fn make_skew_y_matrix (angle_degrees: f64) -> cairo::Matrix {
        let mut m = make_skew_x_matrix (angle_degrees);
        m.yx = m.xy;
        m.xy = 0.0;
        m
    }

    #[test]
    fn parses_skew_x () {
        assert_eq! (parse_transform ("skewX (30)").unwrap (), make_skew_x_matrix (30.0));
    }

    #[test]
    fn parses_skew_y () {
        assert_eq! (parse_transform ("skewY (30)").unwrap (), make_skew_y_matrix (30.0));
    }

    #[test]
    #[ignore]
    fn parses_transform_list () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        assert_eq! (parse_transform ("scale(10)rotate(30, 10, 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &s));

        assert_eq! (parse_transform ("translate(20, 30), scale (10)").unwrap (),
                    cairo::Matrix::multiply (&s, &t));

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }
}
<|endoftext|>


<commit_before><commit_msg>mutability<commit_after>
// however
use std::cell::Cell;

// mutability of struct is in its binding
struct Color {
    r: i32,
    g: i32,
    b: i32,
    // mut a: i32, // not possible
    // how ever
    a: Cell<f32>,
}

fn main() {
    let mut x = 5;
    let mut xx = 55;
    let mut z = 9;
    let mut zz = 99;

    // immutable binding to mutable reference
    // can change value of x but
    // y cannot bind to another reference
    let y = &mut x;

    // mutable binding to mutable reference
    let mut yy = &mut xx;

    // cannot do this
    // y = &mut z;

    // can do this
    yy = &mut zz;

    let c = Color {r: 32, g: 56, b: 89, a: Cell::new(1.0)};

    // cannot do
    // c.r = 23;
    // however
    c.a.set(0.5);
}
<|endoftext|>


<commit_before>//! Support for JPG image decoding.

use super::{CustomMessageSnafu, CustomSnafu, MissingAttributeSnafu};
use crate::adapters::{DecodeResult, PixelDataObject, PixelRWAdapter};
use jpeg_decoder::Decoder;
use snafu::{OptionExt, ResultExt};
use std::io::Cursor;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct JPEGAdapter;

impl PixelRWAdapter for JPEGAdapter {
    /// Decode DICOM image data with jpeg encoding.

    fn decode(&self, src: &dyn PixelDataObject, dst: &mut Vec<u8>) -> DecodeResult<()> {
        let cols = src
            .cols()
            .context(MissingAttributeSnafu { name: "Columns" })?;
        let rows = src.rows().context(MissingAttributeSnafu { name: "Rows" })?;
        let samples_per_pixel = src.samples_per_pixel().context(MissingAttributeSnafu {
            name: "SamplesPerPixel",
        })?;
        let bits_allocated = src.bits_allocated().context(MissingAttributeSnafu {
            name: "BitsAllocated",
        })?;

        if bits_allocated != 8 && bits_allocated != 16 {
            return CustomMessageSnafu {
                message: "BitsAllocated other than 8 or 16 is not supported",
            }
            .fail();
        }

        let nr_frames = src.number_of_frames().unwrap_or(1) as usize;
        let bytes_per_sample = bits_allocated / 8;

        // `stride` it the total number of bytes for each sample plane
        let stride: usize = bytes_per_sample as usize * cols as usize * rows as usize;
        dst.resize((samples_per_pixel as usize * stride) * nr_frames, 0);

        // Embedded jpegs can span multiple fragments
        // Hence we collect all fragments into single vector
        // and then just iterate a cursor for each frame
        let fragments: Vec<u8> = src
            .raw_pixel_data()
            .context(CustomMessageSnafu {
                message: "Expected to have raw pixel data available",
            })?
            .fragments
            .into_iter()
            .flatten()
            .collect();

        let fragments_len = fragments.len() as u64;
        let mut cursor = Cursor::new(fragments);

        let mut dst_offset = 0;

        loop {
            // dicom fields always have to have an even length and fill this space with padding
            // if uneven we have to move one position further to consume this padding
            if cursor.position() % 2 > 0 {
                cursor.set_position(cursor.position() + 1);
            }

            if cursor.position() >= fragments_len {
                break;
            }
            let mut decoder = Decoder::new(&mut cursor);
            let decoded = decoder
                .decode()
                .map_err(|e| Box::new(e) as Box<_>)
                .context(CustomSnafu)?;

            let decoded_len = decoded.len();
            dst[dst_offset..(dst_offset + decoded_len)].copy_from_slice(&decoded);
            dst_offset += decoded_len
        }

        Ok(())
    }
}
<commit_msg>Move cursor manipulation to end of iteration<commit_after>//! Support for JPG image decoding.

use super::{CustomMessageSnafu, CustomSnafu, MissingAttributeSnafu};
use crate::adapters::{DecodeResult, PixelDataObject, PixelRWAdapter};
use jpeg_decoder::Decoder;
use snafu::{OptionExt, ResultExt};
use std::io::Cursor;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct JPEGAdapter;

impl PixelRWAdapter for JPEGAdapter {
    /// Decode DICOM image data with jpeg encoding.

    fn decode(&self, src: &dyn PixelDataObject, dst: &mut Vec<u8>) -> DecodeResult<()> {
        let cols = src
            .cols()
            .context(MissingAttributeSnafu { name: "Columns" })?;
        let rows = src.rows().context(MissingAttributeSnafu { name: "Rows" })?;
        let samples_per_pixel = src.samples_per_pixel().context(MissingAttributeSnafu {
            name: "SamplesPerPixel",
        })?;
        let bits_allocated = src.bits_allocated().context(MissingAttributeSnafu {
            name: "BitsAllocated",
        })?;

        if bits_allocated != 8 && bits_allocated != 16 {
            return CustomMessageSnafu {
                message: "BitsAllocated other than 8 or 16 is not supported",
            }
            .fail();
        }

        let nr_frames = src.number_of_frames().unwrap_or(1) as usize;
        let bytes_per_sample = bits_allocated / 8;

        // `stride` it the total number of bytes for each sample plane
        let stride: usize = bytes_per_sample as usize * cols as usize * rows as usize;
        dst.resize((samples_per_pixel as usize * stride) * nr_frames, 0);

        // Embedded jpegs can span multiple fragments
        // Hence we collect all fragments into single vector
        // and then just iterate a cursor for each frame
        let fragments: Vec<u8> = src
            .raw_pixel_data()
            .context(CustomMessageSnafu {
                message: "Expected to have raw pixel data available",
            })?
            .fragments
            .into_iter()
            .flatten()
            .collect();

        let fragments_len = fragments.len() as u64;
        let mut cursor = Cursor::new(fragments);
        let mut dst_offset = 0;

        loop {
            let mut decoder = Decoder::new(&mut cursor);
            let decoded = decoder
                .decode()
                .map_err(|e| Box::new(e) as Box<_>)
                .context(CustomSnafu)?;

            let decoded_len = decoded.len();
            dst[dst_offset..(dst_offset + decoded_len)].copy_from_slice(&decoded);
            dst_offset += decoded_len;

            // dicom fields always have to have an even length and fill this space with padding
            // if uneven we have to move one position further to consume this padding
            if cursor.position() % 2 > 0 {
                cursor.set_position(cursor.position() + 1);
            }

            if cursor.position() >= fragments_len {
                break;
            }
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate robots;

use robots::actors::{Actor,ActorCell};
use std::sync::Mutex;
use std::any::Any;
use std::thread;
use std::time;
use super::super::gpioaccess::{DirectionProxied,PinProxyContract,PwmProxyContract};
use super::super::gpioaccess::proxyimpl::{PinProxy,PwmProxy};

#[derive(Copy, Clone, PartialEq,Debug)]
pub enum PinCommands {
	Blink(u64),
	Switch,
}

pub struct PinActor {
	pinproxy :  Mutex<PinProxy>,
}

impl Actor for PinActor {
	fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<PinCommands>(_message){
			match *_message {
				PinCommands::Blink(times) => {
					let pin = self.pinproxy.lock().unwrap();
					match pin.export() {
						Ok(()) => {
							println!("Pin exported");
							for _ in 1..times {
								pin.set_direction(DirectionProxied::Out);
								pin.set_direction(DirectionProxied::High);
								thread::sleep(time::Duration::from_millis(400));
								pin.set_direction(DirectionProxied::Low);
								thread::sleep(time::Duration::from_millis(400));
								println!("Blink");
							}
							match pin.unexport() {
								Ok(()) => {
									println!("Pin unexported");
								}
								_ => {}
							}
						}
						_ => {}
					}
				},
				PinCommands::Switch => { }
			}
		}
	}
}

impl PinActor{
	pub fn new(pin_number: u64) -> PinActor {
		PinActor{ pinproxy : Mutex::new(PinProxy::new(pin_number)) }
	}
}

#[derive(Copy, Clone, PartialEq,Debug)]
pub enum PwmCommands {
	MoveToDegree(u16)
}

pub struct PwmActor {
	pwmproxy :  Result<Mutex<PwmProxy>,()>,
}

impl Actor for PwmActor {
	fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		println!("pwm received message");
		if let Ok(_message) = Box::<Any>::downcast::<PwmCommands>(_message){
			println!("pwm recognized command");
			match *_message {
				PwmCommands::MoveToDegree(degree) => {
					println!("pwm movetodegree");
					match self.pwmproxy {
						Ok(ref pwmproxyresult) =>
						{
							let pwm = pwmproxyresult.lock().unwrap();
							match pwm.export() {
								Ok(()) => {
									println!("Pwm exported");
									match pwm.set_period_ns(2_500_000)
									{
										Ok(()) => {
											println!("Pwm setting period");
											match pwm.enable(true)
											{
												Ok(()) => {
													println!("Pwm enable");
													for x in 1..10 {
														println!("Pwm {}",x);
														pwm.increase_to_max(0.1);
														pwm.decrease_to_minimum(0.1);
													}
													match pwm.enable(false)
													{
														Ok(()) => {
															println!("Pwm disable");
														}
														_ => println!("Pwm disabled failed")
													}
												}
												_ => println!("Pwm enabled failed")
											}
										}
										_ => println!("Pwm set period failed")
									}
									match pwm.unexport() {
										Ok(()) => {
											println!("Pwm unexported");
										}
										_ => println!("Pwm unexport failed")
									}
								}
								_ => println!("Pwm export failed")
							}
						}
						_ => println!("No Pwm")
					}

					println!("pwm done");
				}
			}
		}
	}
}

impl PwmActor{
	pub fn new(number: u32) -> PwmActor {
		match PwmProxy::new(0,number)
		{
			Ok(pwmproxy) =>  PwmActor{ pwmproxy : Ok(Mutex::new(pwmproxy)) },
			_ => PwmActor{ pwmproxy : Err(()) },
		}
	}
}<commit_msg>step by step<commit_after>extern crate robots;

use robots::actors::{Actor,ActorCell};
use std::sync::Mutex;
use std::any::Any;
use std::thread;
use std::time;
use super::super::gpioaccess::{DirectionProxied,PinProxyContract,PwmProxyContract};
use super::super::gpioaccess::proxyimpl::{PinProxy,PwmProxy};

#[derive(Copy, Clone, PartialEq,Debug)]
pub enum PinCommands {
	Blink(u64),
	Switch,
}

pub struct PinActor {
	pinproxy :  Mutex<PinProxy>,
}

impl Actor for PinActor {
	fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<PinCommands>(_message){
			match *_message {
				PinCommands::Blink(times) => {
					let pin = self.pinproxy.lock().unwrap();
					match pin.export() {
						Ok(()) => {
							println!("Pin exported");
							for _ in 1..times {
								pin.set_direction(DirectionProxied::Out);
								pin.set_direction(DirectionProxied::High);
								thread::sleep(time::Duration::from_millis(400));
								pin.set_direction(DirectionProxied::Low);
								thread::sleep(time::Duration::from_millis(400));
								println!("Blink");
							}
							match pin.unexport() {
								Ok(()) => {
									println!("Pin unexported");
								}
								_ => {}
							}
						}
						_ => {}
					}
				},
				PinCommands::Switch => { }
			}
		}
	}
}

impl PinActor{
	pub fn new(pin_number: u64) -> PinActor {
		PinActor{ pinproxy : Mutex::new(PinProxy::new(pin_number)) }
	}
}

#[derive(Copy, Clone, PartialEq,Debug)]
pub enum PwmCommands {
	MoveToDegree(u16)
}

pub struct PwmActor {
	pwmproxy :  Result<Mutex<PwmProxy>,()>,
}

impl Actor for PwmActor {
	fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		println!("pwm received message");
		if let Ok(_message) = Box::<Any>::downcast::<PwmCommands>(_message){
			println!("pwm recognized command");
			match *_message {
				PwmCommands::MoveToDegree(degree) => {
					println!("pwm movetodegree");
					match self.pwmproxy {
						Ok(ref pwmproxyresult) =>
						{
							let pwm = pwmproxyresult.lock().unwrap();
							match pwm.export() {
								Ok(()) => {
									println!("Pwm exported");
									match pwm.set_period_ns(2_500_000)
									{
										Ok(()) => {
											println!("Pwm setting period");
											match pwm.enable(true)
											{
												Ok(()) => {
													println!("Pwm enable");
													for x in 1..10 {
														println!("Pwm {}",x);
														pwm.increase_to_max(0.05);
														pwm.decrease_to_minimum(0.05);
													}
													match pwm.enable(false)
													{
														Ok(()) => {
															println!("Pwm disable");
														}
														_ => println!("Pwm disabled failed")
													}
												}
												_ => println!("Pwm enabled failed")
											}
										}
										_ => println!("Pwm set period failed")
									}
									match pwm.unexport() {
										Ok(()) => {
											println!("Pwm unexported");
										}
										_ => println!("Pwm unexport failed")
									}
								}
								_ => println!("Pwm export failed")
							}
						}
						_ => println!("No Pwm")
					}

					println!("pwm done");
				}
			}
		}
	}
}

impl PwmActor{
	pub fn new(number: u32) -> PwmActor {
		match PwmProxy::new(0,number)
		{
			Ok(pwmproxy) =>  PwmActor{ pwmproxy : Ok(Mutex::new(pwmproxy)) },
			_ => PwmActor{ pwmproxy : Err(()) },
		}
	}
}<|endoftext|>


<commit_before>
extern mod sax;

use extra::treemap::TreeSet;
use self::sax::*;

pub enum Ns { Gl, Glx, Wgl }

fn trim_str<'a>(s: &'a str, trim: &str) -> &'a str {
    if s.starts_with(trim) { s.slice_from(trim.len()) } else { s }
}

fn trim_enum_prefix<'a>(ident: &'a str, ns: Ns) -> &'a str {
    match ns {
        Gl => trim_str(ident, "GL_"),
        Glx => trim_str(ident, "GLX_"),
        Wgl =>  trim_str(ident, "WGL_"),
    }
}

fn trim_cmd_prefix<'a>(ident: &'a str, ns: Ns) -> &'a str {
    match ns {
        Gl => trim_str(ident, "gl"),
        Glx => trim_str(ident, "glx"),
        Wgl =>  trim_str(ident, "wgl"),
    }
}

pub struct Registry {
    groups: ~[Group],
    enums: ~[EnumNs],
    cmds: ~[CmdNs],
}

impl Registry {
    /// Generate a registry from the supplied XML string
    pub fn from_xml(data: &str, ns: Ns) -> Registry {
        RegistryBuilder::parse(data, ns)
    }

    /// Returns a set of all the types used in the supplied registry. This is useful
    /// for working out what conversions are needed for the specific registry.
    pub fn get_tys(&self) -> TreeSet<~str> {
        let mut tys = TreeSet::new();
        for cmds in self.cmds.iter() {
            for def in cmds.defs.iter() {
                tys.insert(def.proto.ty.clone());
                for param in def.params.iter() {
                    tys.insert(param.ty.clone());
                }
            }
        }
        tys
    }
}

pub struct Group {
    name: ~str,
    enums: ~[~str],
}

pub struct EnumNs {
    namespace: ~str,
    group: Option<~str>,
    ty: Option<~str>,
    start: Option<~str>,
    end: Option<~str>,
    vendor: Option<~str>,
    comment: Option<~str>,
    defs: ~[Enum],
}

pub struct Enum {
    ident: ~str,
    value: ~str,
    alias: Option<~str>,
}

pub struct CmdNs {
    namespace: ~str,
    defs: ~[Cmd],
}

pub struct Binding {
    ident: ~str,
    ty: ~str,
    group: Option<~str>,
}

pub struct Cmd {
    proto: Binding,
    params: ~[Binding],
    is_safe: bool,
    alias: Option<~str>,
    vecequiv: Option<~str>,
    glx: Option<GlxOpcode>,
}

pub struct GlxOpcode {
    ty: ~str,
    opcode: ~str,
    name: Option<~str>,
    comment: Option<~str>,
}

struct RegistryBuilder {
    ns: Ns,
    priv port: SaxPort,
}

/// A big, ugly, imperative impl with methods that accumulates a Registry struct
impl<'self> RegistryBuilder {
    fn parse(data: &str, ns: Ns) -> Registry {
        RegistryBuilder {
            ns: ns,
            port: parse_xml(data),
        }.consume_registry()
    }

    fn recv(&self) -> ParseEvent {
        loop {
            match self.port.recv() {
                Ok(StartDocument) => (),
                Ok(Comment(_)) => (),
                Ok(Characters(ref ch)) if ch.is_whitespace() => (),
                Ok(EndDocument) => fail!("The end of the document has been reached"),
                Ok(event) => return event,
                Err(err) => fail!("XML error: %s", err.to_str()),
            }
        }
    }

    fn expect_characters(&self) -> ~str {
        match self.recv() {
            Characters(ref ch) => ch.clone(),
            msg => fail!("Expected characters, found: %s", msg.to_str()),
        }
    }

    fn expect_start_element(&self, name: &str) -> Attributes {
        match self.recv() {
            StartElement(ref n, ref atts) if name == *n => atts.clone(),
            msg => fail!("Expected <%s>, found: %s", name, msg.to_str()),
        }
    }

    fn expect_end_element(&self, name: &str) {
        match self.recv() {
            EndElement(ref n) if name == *n => (),
            msg => fail!("Expected </%s>, found: %s", name, msg.to_str()),
        }
    }

    fn skip_until(&self, event: ParseEvent) {
        loop {
            let msg = self.recv();
            if msg == event || msg == EndDocument { break }
        }
    }

    fn consume_registry(&self) -> Registry {
        self.expect_start_element("registry");
        let mut registry = Registry {
            groups: ~[],
            enums: ~[],
            cmds: ~[]
        };
        loop {
            match self.recv() {
                // ignores
                Characters(_) | Comment(_) => (),
                StartElement(~"comment", _) => self.skip_until(EndElement(~"comment")),
                StartElement(~"types", _) => self.skip_until(EndElement(~"types")),
                StartElement(~"feature", _) => self.skip_until(EndElement(~"feature")),
                StartElement(~"extensions", _) => self.skip_until(EndElement(~"extensions")),

                // add groups
                StartElement(~"groups", _) => {
                    loop {
                        match self.recv() {
                            StartElement(~"group", ref atts) => {
                                registry.groups.push(
                                    self.consume_group(atts.get_clone("name"))
                                );
                            }
                            EndElement(~"groups") => break,
                            msg => fail!("Expected </groups>, found: %s", msg.to_str()),
                        }
                    }
                }

                // add enum namespace
                StartElement(~"enums", ref atts) => {
                    registry.enums.push(
                        EnumNs {
                            namespace:  atts.get_clone("namespace"),
                            group:      atts.find_clone("group"),
                            ty:         atts.find_clone("type"),
                            start:      atts.find_clone("start"),
                            end:        atts.find_clone("end"),
                            vendor:     atts.find_clone("vendor"),
                            comment:    atts.find_clone("comment"),
                            defs:       self.consume_enums(),
                        }
                    )
                }

                // add command namespace
                StartElement(~"commands", ref atts) => {
                    registry.cmds.push(
                        CmdNs {
                            namespace:  atts.get_clone("namespace"),
                            defs:       self.consume_cmds(),
                        }
                    );
                }

                // finished building the registry
                EndElement(~"registry") => break,

                // error handling
                msg => fail!("Expected </registry>, found: %s", msg.to_str()),
            }
        }
        registry
    }

    fn consume_group(&self, name: ~str) -> Group {
        let mut enms = ~[];
        loop {
            match self.recv() {
                StartElement(~"enum", ref atts) => {
                    enms.push(atts.get_clone("name"));
                    self.expect_end_element("enum");
                }
                EndElement(~"group") => break,
                msg => fail!("Expected </group>, found: %s", msg.to_str()),
            }
        }
        Group {
            name: name,
            enums: enms,
        }
    }

    fn consume_enums(&self) -> ~[Enum] {
        let mut enums = ~[];
        loop {
            match self.recv() {
                // ignores
                Characters(_) | Comment(_) => (),
                StartElement(~"unused", _) => self.skip_until(EndElement(~"unused")),

                // add enum definition
                StartElement(~"enum", ref atts) => {
                    enums.push(
                        Enum {
                            ident:  trim_enum_prefix(atts.get("name"), self.ns).to_owned(),
                            value:  atts.get_clone("value"),
                            alias:  atts.find_clone("alias"),
                        }
                    );
                    self.expect_end_element("enum");
                }

                // finished building the namespace
                EndElement(~"enums") => break,
                // error handling
                msg => fail!("Expected </enums>, found: %s", msg.to_str()),
            }
        }
        enums
    }

    fn consume_cmds(&self) -> ~[Cmd] {
        let mut cmds = ~[];
        loop {
            match self.recv() {
                // add command definition
                StartElement(~"command", _) => {
                    cmds.push(self.consume_cmd());
                }
                // finished building the namespace
                EndElement(~"commands") => break,
                // error handling
                msg => fail!("Expected </commands>, found: %s", msg.to_str()),
            }
        }
        cmds
    }

    fn consume_cmd(&self) -> Cmd {
        // consume command prototype
        let proto_atts = self.expect_start_element("proto");
        let mut proto = self.consume_binding(proto_atts.find_clone("group"));
        proto.ident = trim_cmd_prefix(proto.ident, self.ns).to_owned();
        self.expect_end_element("proto");

        let mut params = ~[];
        let mut alias = None;
        let mut vecequiv = None;
        let mut glx = None;
        loop {
            match self.recv() {
                StartElement(~"param", ref atts) => {
                    params.push(
                        self.consume_binding(atts.find_clone("group"))
                    );
                    self.expect_end_element("param");
                }
                StartElement(~"alias", ref atts) => {
                    alias = atts.find_clone("alias");
                    self.expect_end_element("alias");
                }
                StartElement(~"vecequiv", ref atts) => {
                    vecequiv = atts.find_clone("vecequiv");
                    self.expect_end_element("vecequiv");
                }
                StartElement(~"glx", ref atts) => {
                    glx = Some(GlxOpcode {
                        ty:      atts.get_clone("type"),
                        opcode:  atts.get_clone("opcode"),
                        name:    atts.find_clone("name"),
                        comment: atts.find_clone("comment"),
                    });
                    self.expect_end_element("glx");
                }
                EndElement(~"command") => break,
                msg => fail!("Expected </command>, found: %s", msg.to_str()),
            }
        }
        let is_safe = params.len() <= 0 || params.iter().any(|p| !p.ty.contains_char('*'));

        Cmd {
            proto: proto,
            params: params,
            is_safe: is_safe,
            alias: alias,
            vecequiv: vecequiv,
            glx: glx,
        }
    }

    fn consume_binding(&self, group: Option<~str>) -> Binding {
        // consume type
        let mut ty = ~"";
        loop {
            match self.recv() {
                Characters(ch) => ty.push_str(ch),
                StartElement(~"ptype", _) => (),
                EndElement(~"ptype") => (),
                StartElement(~"name", _) => break,
                msg => fail!("Expected binding, found: %s", msg.to_str()),
            }
        }
        // consume identifier
        let ident = self.expect_characters();
        self.expect_end_element("name");
        Binding {
            ident: ident,
            ty: ty,
            group: group,
        }
    }
}
<commit_msg>Fix potential bug in `skip_until`<commit_after>
extern mod sax;

use extra::treemap::TreeSet;
use self::sax::*;

pub enum Ns { Gl, Glx, Wgl }

fn trim_str<'a>(s: &'a str, trim: &str) -> &'a str {
    if s.starts_with(trim) { s.slice_from(trim.len()) } else { s }
}

fn trim_enum_prefix<'a>(ident: &'a str, ns: Ns) -> &'a str {
    match ns {
        Gl => trim_str(ident, "GL_"),
        Glx => trim_str(ident, "GLX_"),
        Wgl =>  trim_str(ident, "WGL_"),
    }
}

fn trim_cmd_prefix<'a>(ident: &'a str, ns: Ns) -> &'a str {
    match ns {
        Gl => trim_str(ident, "gl"),
        Glx => trim_str(ident, "glx"),
        Wgl =>  trim_str(ident, "wgl"),
    }
}

pub struct Registry {
    groups: ~[Group],
    enums: ~[EnumNs],
    cmds: ~[CmdNs],
}

impl Registry {
    /// Generate a registry from the supplied XML string
    pub fn from_xml(data: &str, ns: Ns) -> Registry {
        RegistryBuilder::parse(data, ns)
    }

    /// Returns a set of all the types used in the supplied registry. This is useful
    /// for working out what conversions are needed for the specific registry.
    pub fn get_tys(&self) -> TreeSet<~str> {
        let mut tys = TreeSet::new();
        for cmds in self.cmds.iter() {
            for def in cmds.defs.iter() {
                tys.insert(def.proto.ty.clone());
                for param in def.params.iter() {
                    tys.insert(param.ty.clone());
                }
            }
        }
        tys
    }
}

pub struct Group {
    name: ~str,
    enums: ~[~str],
}

pub struct EnumNs {
    namespace: ~str,
    group: Option<~str>,
    ty: Option<~str>,
    start: Option<~str>,
    end: Option<~str>,
    vendor: Option<~str>,
    comment: Option<~str>,
    defs: ~[Enum],
}

pub struct Enum {
    ident: ~str,
    value: ~str,
    alias: Option<~str>,
}

pub struct CmdNs {
    namespace: ~str,
    defs: ~[Cmd],
}

pub struct Binding {
    ident: ~str,
    ty: ~str,
    group: Option<~str>,
}

pub struct Cmd {
    proto: Binding,
    params: ~[Binding],
    is_safe: bool,
    alias: Option<~str>,
    vecequiv: Option<~str>,
    glx: Option<GlxOpcode>,
}

pub struct GlxOpcode {
    ty: ~str,
    opcode: ~str,
    name: Option<~str>,
    comment: Option<~str>,
}

struct RegistryBuilder {
    ns: Ns,
    priv port: SaxPort,
}

/// A big, ugly, imperative impl with methods that accumulates a Registry struct
impl<'self> RegistryBuilder {
    fn parse(data: &str, ns: Ns) -> Registry {
        RegistryBuilder {
            ns: ns,
            port: parse_xml(data),
        }.consume_registry()
    }

    fn recv(&self) -> ParseEvent {
        loop {
            match self.port.recv() {
                Ok(StartDocument) => (),
                Ok(Comment(_)) => (),
                Ok(Characters(ref ch)) if ch.is_whitespace() => (),
                Ok(EndDocument) => fail!("The end of the document has been reached"),
                Ok(event) => return event,
                Err(err) => fail!("XML error: %s", err.to_str()),
            }
        }
    }

    fn expect_characters(&self) -> ~str {
        match self.recv() {
            Characters(ref ch) => ch.clone(),
            msg => fail!("Expected characters, found: %s", msg.to_str()),
        }
    }

    fn expect_start_element(&self, name: &str) -> Attributes {
        match self.recv() {
            StartElement(ref n, ref atts) if name == *n => atts.clone(),
            msg => fail!("Expected <%s>, found: %s", name, msg.to_str()),
        }
    }

    fn expect_end_element(&self, name: &str) {
        match self.recv() {
            EndElement(ref n) if name == *n => (),
            msg => fail!("Expected </%s>, found: %s", name, msg.to_str()),
        }
    }

    fn skip_until(&self, event: ParseEvent) {
        loop {
            match self.recv() {
                EndDocument => fail!("Expected %s, but reached the end of the document.",
                                     event.to_str()),
                ref msg if *msg == event => break,
                _ => (),
            }
        }
    }

    fn consume_registry(&self) -> Registry {
        self.expect_start_element("registry");
        let mut registry = Registry {
            groups: ~[],
            enums: ~[],
            cmds: ~[]
        };
        loop {
            match self.recv() {
                // ignores
                Characters(_) | Comment(_) => (),
                StartElement(~"comment", _) => self.skip_until(EndElement(~"comment")),
                StartElement(~"types", _) => self.skip_until(EndElement(~"types")),
                StartElement(~"feature", _) => self.skip_until(EndElement(~"feature")),
                StartElement(~"extensions", _) => self.skip_until(EndElement(~"extensions")),

                // add groups
                StartElement(~"groups", _) => {
                    loop {
                        match self.recv() {
                            StartElement(~"group", ref atts) => {
                                registry.groups.push(
                                    self.consume_group(atts.get_clone("name"))
                                );
                            }
                            EndElement(~"groups") => break,
                            msg => fail!("Expected </groups>, found: %s", msg.to_str()),
                        }
                    }
                }

                // add enum namespace
                StartElement(~"enums", ref atts) => {
                    registry.enums.push(
                        EnumNs {
                            namespace:  atts.get_clone("namespace"),
                            group:      atts.find_clone("group"),
                            ty:         atts.find_clone("type"),
                            start:      atts.find_clone("start"),
                            end:        atts.find_clone("end"),
                            vendor:     atts.find_clone("vendor"),
                            comment:    atts.find_clone("comment"),
                            defs:       self.consume_enums(),
                        }
                    )
                }

                // add command namespace
                StartElement(~"commands", ref atts) => {
                    registry.cmds.push(
                        CmdNs {
                            namespace:  atts.get_clone("namespace"),
                            defs:       self.consume_cmds(),
                        }
                    );
                }

                // finished building the registry
                EndElement(~"registry") => break,

                // error handling
                msg => fail!("Expected </registry>, found: %s", msg.to_str()),
            }
        }
        registry
    }

    fn consume_group(&self, name: ~str) -> Group {
        let mut enms = ~[];
        loop {
            match self.recv() {
                StartElement(~"enum", ref atts) => {
                    enms.push(atts.get_clone("name"));
                    self.expect_end_element("enum");
                }
                EndElement(~"group") => break,
                msg => fail!("Expected </group>, found: %s", msg.to_str()),
            }
        }
        Group {
            name: name,
            enums: enms,
        }
    }

    fn consume_enums(&self) -> ~[Enum] {
        let mut enums = ~[];
        loop {
            match self.recv() {
                // ignores
                Characters(_) | Comment(_) => (),
                StartElement(~"unused", _) => self.skip_until(EndElement(~"unused")),

                // add enum definition
                StartElement(~"enum", ref atts) => {
                    enums.push(
                        Enum {
                            ident:  trim_enum_prefix(atts.get("name"), self.ns).to_owned(),
                            value:  atts.get_clone("value"),
                            alias:  atts.find_clone("alias"),
                        }
                    );
                    self.expect_end_element("enum");
                }

                // finished building the namespace
                EndElement(~"enums") => break,
                // error handling
                msg => fail!("Expected </enums>, found: %s", msg.to_str()),
            }
        }
        enums
    }

    fn consume_cmds(&self) -> ~[Cmd] {
        let mut cmds = ~[];
        loop {
            match self.recv() {
                // add command definition
                StartElement(~"command", _) => {
                    cmds.push(self.consume_cmd());
                }
                // finished building the namespace
                EndElement(~"commands") => break,
                // error handling
                msg => fail!("Expected </commands>, found: %s", msg.to_str()),
            }
        }
        cmds
    }

    fn consume_cmd(&self) -> Cmd {
        // consume command prototype
        let proto_atts = self.expect_start_element("proto");
        let mut proto = self.consume_binding(proto_atts.find_clone("group"));
        proto.ident = trim_cmd_prefix(proto.ident, self.ns).to_owned();
        self.expect_end_element("proto");

        let mut params = ~[];
        let mut alias = None;
        let mut vecequiv = None;
        let mut glx = None;
        loop {
            match self.recv() {
                StartElement(~"param", ref atts) => {
                    params.push(
                        self.consume_binding(atts.find_clone("group"))
                    );
                    self.expect_end_element("param");
                }
                StartElement(~"alias", ref atts) => {
                    alias = atts.find_clone("alias");
                    self.expect_end_element("alias");
                }
                StartElement(~"vecequiv", ref atts) => {
                    vecequiv = atts.find_clone("vecequiv");
                    self.expect_end_element("vecequiv");
                }
                StartElement(~"glx", ref atts) => {
                    glx = Some(GlxOpcode {
                        ty:      atts.get_clone("type"),
                        opcode:  atts.get_clone("opcode"),
                        name:    atts.find_clone("name"),
                        comment: atts.find_clone("comment"),
                    });
                    self.expect_end_element("glx");
                }
                EndElement(~"command") => break,
                msg => fail!("Expected </command>, found: %s", msg.to_str()),
            }
        }
        let is_safe = params.len() <= 0 || params.iter().any(|p| !p.ty.contains_char('*'));

        Cmd {
            proto: proto,
            params: params,
            is_safe: is_safe,
            alias: alias,
            vecequiv: vecequiv,
            glx: glx,
        }
    }

    fn consume_binding(&self, group: Option<~str>) -> Binding {
        // consume type
        let mut ty = ~"";
        loop {
            match self.recv() {
                Characters(ch) => ty.push_str(ch),
                StartElement(~"ptype", _) => (),
                EndElement(~"ptype") => (),
                StartElement(~"name", _) => break,
                msg => fail!("Expected binding, found: %s", msg.to_str()),
            }
        }
        // consume identifier
        let ident = self.expect_characters();
        self.expect_end_element("name");
        Binding {
            ident: ident,
            ty: ty,
            group: group,
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>initial nav interface<commit_after><|endoftext|>


<commit_before><commit_msg>Update to new api<commit_after><|endoftext|>