<commit_before>use super::{f32, Lab};

pub struct DE2000;

impl DE2000 {
    //! Returns the difference between two `Lab` colors as calculated by the
    //! [CIEDE2000 algorithm](http://en.wikipedia.org/wiki/Color_difference#CIEDE2000).

    pub fn new(x1: Lab, x2: Lab) -> f32 {
        let ksub_l = 1.0;
        let ksub_c = 1.0;
        let ksub_h = 1.0;

        let delta_l_prime = x2.l - x1.l;

        let l_bar = (x1.l + x2.l) / 2.0;

        let c1 = (x1.a.powi(2) + x1.b.powi(2)).sqrt();
        let c2 = (x2.a.powi(2) + x2.b.powi(2)).sqrt();

        let c_bar = (c1 + c2) / 2.0;

        let a_prime_1 =
            x1.a + (x1.a / 2.0) * (1.0 - (c_bar.powi(7) / (c_bar.powi(7) + 25f32.powi(7))).sqrt());
        let a_prime_2 =
            x2.a + (x2.a / 2.0) * (1.0 - (c_bar.powi(7) / (c_bar.powi(7) + 25f32.powi(7))).sqrt());

        let c_prime_1 = (a_prime_1.powi(2) + x1.b.powi(2)).sqrt();
        let c_prime_2 = (a_prime_2.powi(2) + x2.b.powi(2)).sqrt();

        let c_bar_prime = (c_prime_1 + c_prime_2) / 2.0;

        let delta_c_prime = c_prime_2 - c_prime_1;

        let s_sub_l = 1.0 +
                      ((0.015 * (l_bar - 50.0).powi(2)) / (20.0 + (l_bar - 50.0).powi(2)).sqrt());

        let s_sub_c = 1.0 + 0.045 * c_bar_prime;

        let h_prime_1 = get_h_prime_fn(x1.b, a_prime_1);
        let h_prime_2 = get_h_prime_fn(x2.b, a_prime_2);

        let delta_h_prime = get_delta_h_prime(c1, c2, h_prime_1, h_prime_2);

        let delta_upcase_h_prime = 2.0 * (c_prime_1 * c_prime_2).sqrt() *
                                   (degrees_to_radians(delta_h_prime) / 2.0).sin();

        let upcase_h_bar_prime = get_upcase_h_bar_prime(h_prime_1, h_prime_2);

        let upcase_t = get_upcase_t(upcase_h_bar_prime);

        let s_sub_upcase_h = 1.0 + 0.015 * c_bar_prime * upcase_t;

        let r_sub_t = get_r_sub_t(c_bar_prime, upcase_h_bar_prime);

        let lightness: f32 = delta_l_prime / (ksub_l * s_sub_l);

        let chroma: f32 = delta_c_prime / (ksub_c * s_sub_c);

        let hue: f32 = delta_upcase_h_prime / (ksub_h * s_sub_upcase_h);

        (lightness.powi(2) + chroma.powi(2) + hue.powi(2) + r_sub_t * chroma * hue).sqrt()
    }
}

fn get_h_prime_fn(x: f32, y: f32) -> f32 {
    let hue_angle;

    if x == 0.0 && y == 0.0 {
        return 0.0;
    }

    hue_angle = radians_to_degrees(x.atan2(y));

    if hue_angle < 0.0 {
        hue_angle + 360.0;
    }

    hue_angle
}

fn get_delta_h_prime(c1: f32, c2: f32, h_prime_1: f32, h_prime_2: f32) -> f32 {
    if 0.0 == c1 || 0.0 == c2 {
        return 0.0;
    }

    if (h_prime_1 - h_prime_2).abs() <= 180.0 {
        return h_prime_2 - h_prime_1;
    }

    if h_prime_2 <= h_prime_1 {
        return h_prime_2 - h_prime_1 + 360.0;
    } else {
        return h_prime_2 - h_prime_1 - 360.0;
    }
}

fn get_upcase_h_bar_prime(h_prime_1: f32, h_prime_2: f32) -> f32 {
    if (h_prime_1 - h_prime_2).abs() > 180.0 {
        return (h_prime_1 + h_prime_2 + 360.0) / 2.0;
    }

    (h_prime_1 + h_prime_2) / 2.0
}

fn get_upcase_t(upcase_h_bar_prime: f32) -> f32 {
    1.0 - 0.17 * (degrees_to_radians(upcase_h_bar_prime - 30.0)).cos() +
    0.24 * (degrees_to_radians(2.0 * upcase_h_bar_prime)).cos() +
    0.32 * (degrees_to_radians(3.0 * upcase_h_bar_prime + 6.0)).cos() -
    0.20 * (degrees_to_radians(4.0 * upcase_h_bar_prime - 63.0)).cos()
}

fn get_r_sub_t(c_bar_prime: f32, upcase_h_bar_prime: f32) -> f32 {
    -2.0 * (c_bar_prime.powi(7) / (c_bar_prime.powi(7) + 25f32.powi(7))).sqrt() *
    (degrees_to_radians(60.0 * (-(((upcase_h_bar_prime - 275.0) / 25.0).powi(2))).exp())).sin()
}

fn radians_to_degrees(radians: f32) -> f32 {
    radians * (180.0 / f32::consts::PI)
}

fn degrees_to_radians(degrees: f32) -> f32 {
    degrees * (f32::consts::PI / 180.0)
}

#[cfg(test)]
mod tests {
    use super::{DE2000, Lab};

    #[test]
    fn it_works() {
        let x1 = Lab {
            l: 36.0,
            a: 60.0,
            b: 41.0,
        };

        let x2 = Lab {
            l: 55.0,
            a: 66.0,
            b: 77.0,
        };

        assert_eq!(DE2000::new(x1, x2), 22.394508);
    }
}
<commit_msg>Add `from_rgb`<commit_after>use super::{f32, Lab};

pub struct DE2000;

impl DE2000 {
    /// Returns the difference between two `Lab` colors as calculated by the
    /// [CIEDE2000 algorithm](http://en.wikipedia.org/wiki/Color_difference#CIEDE2000).

    pub fn new(x1: Lab, x2: Lab) -> f32 {
        let ksub_l = 1.0;
        let ksub_c = 1.0;
        let ksub_h = 1.0;

        let delta_l_prime = x2.l - x1.l;

        let l_bar = (x1.l + x2.l) / 2.0;

        let c1 = (x1.a.powi(2) + x1.b.powi(2)).sqrt();
        let c2 = (x2.a.powi(2) + x2.b.powi(2)).sqrt();

        let c_bar = (c1 + c2) / 2.0;

        let a_prime_1 =
            x1.a + (x1.a / 2.0) * (1.0 - (c_bar.powi(7) / (c_bar.powi(7) + 25f32.powi(7))).sqrt());
        let a_prime_2 =
            x2.a + (x2.a / 2.0) * (1.0 - (c_bar.powi(7) / (c_bar.powi(7) + 25f32.powi(7))).sqrt());

        let c_prime_1 = (a_prime_1.powi(2) + x1.b.powi(2)).sqrt();
        let c_prime_2 = (a_prime_2.powi(2) + x2.b.powi(2)).sqrt();

        let c_bar_prime = (c_prime_1 + c_prime_2) / 2.0;

        let delta_c_prime = c_prime_2 - c_prime_1;

        let s_sub_l = 1.0 +
                      ((0.015 * (l_bar - 50.0).powi(2)) / (20.0 + (l_bar - 50.0).powi(2)).sqrt());

        let s_sub_c = 1.0 + 0.045 * c_bar_prime;

        let h_prime_1 = get_h_prime_fn(x1.b, a_prime_1);
        let h_prime_2 = get_h_prime_fn(x2.b, a_prime_2);

        let delta_h_prime = get_delta_h_prime(c1, c2, h_prime_1, h_prime_2);

        let delta_upcase_h_prime = 2.0 * (c_prime_1 * c_prime_2).sqrt() *
                                   (degrees_to_radians(delta_h_prime) / 2.0).sin();

        let upcase_h_bar_prime = get_upcase_h_bar_prime(h_prime_1, h_prime_2);

        let upcase_t = get_upcase_t(upcase_h_bar_prime);

        let s_sub_upcase_h = 1.0 + 0.015 * c_bar_prime * upcase_t;

        let r_sub_t = get_r_sub_t(c_bar_prime, upcase_h_bar_prime);

        let lightness: f32 = delta_l_prime / (ksub_l * s_sub_l);

        let chroma: f32 = delta_c_prime / (ksub_c * s_sub_c);

        let hue: f32 = delta_upcase_h_prime / (ksub_h * s_sub_upcase_h);

        (lightness.powi(2) + chroma.powi(2) + hue.powi(2) + r_sub_t * chroma * hue).sqrt()
    }

    /// Returns the difference between two RGB colors as calculated by the
    /// [CIEDE2000 algorithm](http://en.wikipedia.org/wiki/Color_difference#CIEDE2000).

    pub fn from_rgb(x1: &[u8; 3], x2: &[u8; 3]) -> f32 {
        let l1 = Lab::from_rgb(x1);
        let l2 = Lab::from_rgb(x2);

        DE2000::new(l1, l2)
    }
}

fn get_h_prime_fn(x: f32, y: f32) -> f32 {
    let hue_angle;

    if x == 0.0 && y == 0.0 {
        return 0.0;
    }

    hue_angle = radians_to_degrees(x.atan2(y));

    if hue_angle < 0.0 {
        hue_angle + 360.0;
    }

    hue_angle
}

fn get_delta_h_prime(c1: f32, c2: f32, h_prime_1: f32, h_prime_2: f32) -> f32 {
    if 0.0 == c1 || 0.0 == c2 {
        return 0.0;
    }

    if (h_prime_1 - h_prime_2).abs() <= 180.0 {
        return h_prime_2 - h_prime_1;
    }

    if h_prime_2 <= h_prime_1 {
        return h_prime_2 - h_prime_1 + 360.0;
    } else {
        return h_prime_2 - h_prime_1 - 360.0;
    }
}

fn get_upcase_h_bar_prime(h_prime_1: f32, h_prime_2: f32) -> f32 {
    if (h_prime_1 - h_prime_2).abs() > 180.0 {
        return (h_prime_1 + h_prime_2 + 360.0) / 2.0;
    }

    (h_prime_1 + h_prime_2) / 2.0
}

fn get_upcase_t(upcase_h_bar_prime: f32) -> f32 {
    1.0 - 0.17 * (degrees_to_radians(upcase_h_bar_prime - 30.0)).cos() +
    0.24 * (degrees_to_radians(2.0 * upcase_h_bar_prime)).cos() +
    0.32 * (degrees_to_radians(3.0 * upcase_h_bar_prime + 6.0)).cos() -
    0.20 * (degrees_to_radians(4.0 * upcase_h_bar_prime - 63.0)).cos()
}

fn get_r_sub_t(c_bar_prime: f32, upcase_h_bar_prime: f32) -> f32 {
    -2.0 * (c_bar_prime.powi(7) / (c_bar_prime.powi(7) + 25f32.powi(7))).sqrt() *
    (degrees_to_radians(60.0 * (-(((upcase_h_bar_prime - 275.0) / 25.0).powi(2))).exp())).sin()
}

fn radians_to_degrees(radians: f32) -> f32 {
    radians * (180.0 / f32::consts::PI)
}

fn degrees_to_radians(degrees: f32) -> f32 {
    degrees * (f32::consts::PI / 180.0)
}

#[cfg(test)]
mod tests {
    use super::{DE2000, Lab};

    #[test]
    fn it_works() {
        let x1 = Lab {
            l: 36.0,
            a: 60.0,
            b: 41.0,
        };

        let x2 = Lab {
            l: 55.0,
            a: 66.0,
            b: 77.0,
        };

        assert_eq!(DE2000::new(x1, x2), 22.394508);
    }
}
<|endoftext|>


<commit_before>use crate::codec::Message;
use crate::fair_queue::FairQueue;
use crate::transport::AcceptStopHandle;
use crate::util::{FairQueueProcessor, PeerIdentity};
use crate::{
    transport, util, Endpoint, MultiPeer, Socket, SocketBackend, SocketType, TryIntoEndpoint,
    ZmqError, ZmqMessage, ZmqResult,
};
use async_trait::async_trait;
use crossbeam::queue::SegQueue;
use dashmap::DashMap;
use futures::channel::{mpsc, oneshot};
use futures::{SinkExt, StreamExt};
use std::collections::hash_map::RandomState;
use std::collections::HashMap;
use std::sync::Arc;

struct DealerPeer {
    pub(crate) send_queue: mpsc::Sender<Message>,
    pub(crate) recv_queue_in: mpsc::Sender<Message>,
    pub(crate) _io_close_handle: futures::channel::oneshot::Sender<bool>,
}

struct DealerSocketBackend {
    pub(crate) peers: DashMap<PeerIdentity, DealerPeer>,
    pub(crate) peer_queue_in: mpsc::Sender<(PeerIdentity, mpsc::Receiver<Message>)>,
    pub(crate) round_robin: SegQueue<PeerIdentity>,
}

#[async_trait]
impl SocketBackend for DealerSocketBackend {
    async fn message_received(&self, peer_id: &PeerIdentity, message: Message) {
        self.peers
            .get_mut(peer_id)
            .expect("Not found peer by id")
            .recv_queue_in
            .send(message)
            .await
            .expect("Failed to send");
    }

    fn socket_type(&self) -> SocketType {
        SocketType::DEALER
    }

    fn shutdown(&self) {
        self.peers.clear();
    }
}

#[async_trait]
impl MultiPeer for DealerSocketBackend {
    async fn peer_connected(
        &self,
        peer_id: &PeerIdentity,
    ) -> (mpsc::Receiver<Message>, oneshot::Receiver<bool>) {
        let default_queue_size = 100;
        let (out_queue, out_queue_receiver) = mpsc::channel(default_queue_size);
        let (in_queue, in_queue_receiver) = mpsc::channel(default_queue_size);
        let (stop_handle, stop_callback) = oneshot::channel::<bool>();

        self.peers.insert(
            peer_id.clone(),
            DealerPeer {
                send_queue: out_queue,
                recv_queue_in: in_queue,
                _io_close_handle: stop_handle,
            },
        );
        self.round_robin.push(peer_id.clone());
        self.peer_queue_in
            .clone()
            .try_send((peer_id.clone(), in_queue_receiver))
            .unwrap();

        (out_queue_receiver, stop_callback)
    }

    async fn peer_disconnected(&self, peer_id: &PeerIdentity) {
        self.peers.remove(peer_id);
    }
}

pub struct DealerSocket {
    backend: Arc<DealerSocketBackend>,
    fair_queue: mpsc::Receiver<(PeerIdentity, Message)>,
    _fair_queue_close_handle: oneshot::Sender<bool>,
    binds: HashMap<Endpoint, AcceptStopHandle>,
}

impl Drop for DealerSocket {
    fn drop(&mut self) {
        self.backend.shutdown();
    }
}

#[async_trait]
impl Socket for DealerSocket {
    fn new() -> Self {
        // TODO define buffer size
        let default_queue_size = 100;
        let (queue_sender, fair_queue) = mpsc::channel(default_queue_size);
        let (peer_in, peer_out) = mpsc::channel(default_queue_size);
        let (fair_queue_close_handle, fqueue_close_recevier) = oneshot::channel();
        tokio::spawn(util::process_fair_queue_messages(FairQueueProcessor {
            fair_queue_stream: FairQueue::new(),
            socket_incoming_queue: queue_sender,
            peer_queue_in: peer_out,
            _io_close_handle: fqueue_close_recevier,
        }));
        Self {
            backend: Arc::new(DealerSocketBackend {
                peers: DashMap::new(),
                peer_queue_in: peer_in,
                round_robin: SegQueue::new(),
            }),
            _fair_queue_close_handle: fair_queue_close_handle,
            fair_queue,
            binds: HashMap::new(),
        }
    }

    async fn bind(&mut self, endpoint: impl TryIntoEndpoint + 'async_trait) -> ZmqResult<Endpoint> {
        let endpoint = endpoint.try_into()?;

        let cloned_backend = self.backend.clone();
        let cback = move |result| util::peer_connected(result, cloned_backend.clone());
        let (endpoint, stop_handle) = transport::begin_accept(endpoint, cback).await?;

        self.binds.insert(endpoint.clone(), stop_handle);
        Ok(endpoint)
    }

    fn binds(&self) -> &HashMap<Endpoint, AcceptStopHandle, RandomState> {
        &self.binds
    }

    async fn unbind(&mut self, endpoint: impl TryIntoEndpoint + 'async_trait) -> ZmqResult<()> {
        let endpoint = endpoint.try_into()?;

        let stop_handle = self.binds.remove(&endpoint);
        let stop_handle = stop_handle.ok_or(ZmqError::NoSuchBind(endpoint))?;
        stop_handle.0.shutdown().await
    }

    async fn connect(&mut self, endpoint: impl TryIntoEndpoint + 'async_trait) -> ZmqResult<()> {
        let endpoint = endpoint.try_into()?;

        let connect_result = transport::connect(endpoint).await;
        util::peer_connected(connect_result, self.backend.clone()).await;
        Ok(())
    }
}

impl DealerSocket {
    pub async fn recv_multipart(&mut self) -> ZmqResult<Vec<ZmqMessage>> {
        loop {
            match self.fair_queue.next().await {
                Some((_peer_id, Message::Multipart(messages))) => {
                    return Ok(messages);
                }
                Some((_peer_id, _)) => todo!(),
                None => todo!(),
            };
        }
    }

    pub async fn send_multipart(&mut self, messages: Vec<ZmqMessage>) -> ZmqResult<()> {
        // In normal scenario this will always be only 1 iteration
        // There can be special case when peer has disconnected and his id is still in
        // RR queue This happens because SegQueue don't have an api to delete
        // items from queue. So in such case we'll just pop item and skip it if
        // we don't have a matching peer in peers map
        let mut messages = Message::Multipart(messages);
        loop {
            let next_peer_id = match self.backend.round_robin.pop() {
                Ok(peer) => peer,
                Err(_) => {
                    if let Message::Multipart(messages) = messages {
                        return Err(ZmqError::ReturnToSenderMultipart {
                            reason: "Not connected to peers. Unable to send messages",
                            messages,
                        });
                    } else {
                        panic!("Not supposed to happen");
                    }
                }
            };
            match self.backend.peers.get_mut(&next_peer_id) {
                Some(mut peer) => {
                    let send_result = peer.send_queue.try_send(messages);
                    match send_result {
                        Ok(()) => {
                            self.backend.round_robin.push(next_peer_id.clone());
                            return Ok(());
                        }
                        Err(e) => {
                            if e.is_full() {
                                // Try again later
                                self.backend.round_robin.push(next_peer_id.clone());
                            }
                            messages = e.into_inner();
                            continue;
                        }
                    };
                }
                None => continue,
            }
        }
    }
}
<commit_msg>Move most of fair queue stuff to backend impl<commit_after>use crate::codec::Message;
use crate::fair_queue::FairQueue;
use crate::transport::AcceptStopHandle;
use crate::util::{FairQueueProcessor, PeerIdentity};
use crate::{
    transport, util, Endpoint, MultiPeer, Socket, SocketBackend, SocketType, TryIntoEndpoint,
    ZmqError, ZmqMessage, ZmqResult,
};
use async_trait::async_trait;
use crossbeam::queue::SegQueue;
use dashmap::DashMap;
use futures::channel::{mpsc, oneshot};
use futures::{SinkExt, StreamExt};
use std::collections::hash_map::RandomState;
use std::collections::HashMap;
use std::sync::Arc;

struct DealerPeer {
    pub(crate) send_queue: mpsc::Sender<Message>,
    pub(crate) recv_queue_in: mpsc::Sender<Message>,
    pub(crate) _io_close_handle: futures::channel::oneshot::Sender<bool>,
}

struct DealerSocketBackend {
    pub(crate) peers: DashMap<PeerIdentity, DealerPeer>,
    peer_queue_in: mpsc::Sender<(PeerIdentity, mpsc::Receiver<Message>)>,
    _fair_queue_close_handle: oneshot::Sender<bool>,
    pub(crate) round_robin: SegQueue<PeerIdentity>,
}

impl DealerSocketBackend {
    fn new(queue_sender: mpsc::Sender<(PeerIdentity, Message)>) -> Self {
        // TODO define buffer size
        let default_queue_size = 100;
        let (peer_in, peer_out) = mpsc::channel(default_queue_size);
        let (fair_queue_close_handle, fqueue_close_recevier) = oneshot::channel();
        tokio::spawn(util::process_fair_queue_messages(FairQueueProcessor {
            fair_queue_stream: FairQueue::new(),
            socket_incoming_queue: queue_sender,
            peer_queue_in: peer_out,
            _io_close_handle: fqueue_close_recevier,
        }));
        Self {
            peers: DashMap::new(),
            peer_queue_in: peer_in,
            round_robin: SegQueue::new(),
            _fair_queue_close_handle: fair_queue_close_handle,
        }
    }
}

#[async_trait]
impl SocketBackend for DealerSocketBackend {
    async fn message_received(&self, peer_id: &PeerIdentity, message: Message) {
        self.peers
            .get_mut(peer_id)
            .expect("Not found peer by id")
            .recv_queue_in
            .send(message)
            .await
            .expect("Failed to send");
    }

    fn socket_type(&self) -> SocketType {
        SocketType::DEALER
    }

    fn shutdown(&self) {
        self.peers.clear();
    }
}

#[async_trait]
impl MultiPeer for DealerSocketBackend {
    async fn peer_connected(
        &self,
        peer_id: &PeerIdentity,
    ) -> (mpsc::Receiver<Message>, oneshot::Receiver<bool>) {
        let default_queue_size = 100;
        let (out_queue, out_queue_receiver) = mpsc::channel(default_queue_size);
        let (in_queue, in_queue_receiver) = mpsc::channel(default_queue_size);
        let (stop_handle, stop_callback) = oneshot::channel::<bool>();

        self.peers.insert(
            peer_id.clone(),
            DealerPeer {
                send_queue: out_queue,
                recv_queue_in: in_queue,
                _io_close_handle: stop_handle,
            },
        );
        self.round_robin.push(peer_id.clone());
        self.peer_queue_in
            .clone()
            .try_send((peer_id.clone(), in_queue_receiver))
            .unwrap();

        (out_queue_receiver, stop_callback)
    }

    async fn peer_disconnected(&self, peer_id: &PeerIdentity) {
        self.peers.remove(peer_id);
    }
}

pub struct DealerSocket {
    backend: Arc<DealerSocketBackend>,
    fair_queue: mpsc::Receiver<(PeerIdentity, Message)>,
    binds: HashMap<Endpoint, AcceptStopHandle>,
}

impl Drop for DealerSocket {
    fn drop(&mut self) {
        self.backend.shutdown();
    }
}

#[async_trait]
impl Socket for DealerSocket {
    fn new() -> Self {
        // TODO define buffer size
        let default_queue_size = 100;
        let (queue_sender, fair_queue) = mpsc::channel(default_queue_size);
        Self {
            backend: Arc::new(DealerSocketBackend::new(queue_sender)),
            fair_queue,
            binds: HashMap::new(),
        }
    }

    async fn bind(&mut self, endpoint: impl TryIntoEndpoint + 'async_trait) -> ZmqResult<Endpoint> {
        let endpoint = endpoint.try_into()?;

        let cloned_backend = self.backend.clone();
        let cback = move |result| util::peer_connected(result, cloned_backend.clone());
        let (endpoint, stop_handle) = transport::begin_accept(endpoint, cback).await?;

        self.binds.insert(endpoint.clone(), stop_handle);
        Ok(endpoint)
    }

    fn binds(&self) -> &HashMap<Endpoint, AcceptStopHandle, RandomState> {
        &self.binds
    }

    async fn unbind(&mut self, endpoint: impl TryIntoEndpoint + 'async_trait) -> ZmqResult<()> {
        let endpoint = endpoint.try_into()?;

        let stop_handle = self.binds.remove(&endpoint);
        let stop_handle = stop_handle.ok_or(ZmqError::NoSuchBind(endpoint))?;
        stop_handle.0.shutdown().await
    }

    async fn connect(&mut self, endpoint: impl TryIntoEndpoint + 'async_trait) -> ZmqResult<()> {
        let endpoint = endpoint.try_into()?;

        let connect_result = transport::connect(endpoint).await;
        util::peer_connected(connect_result, self.backend.clone()).await;
        Ok(())
    }
}

impl DealerSocket {
    pub async fn recv_multipart(&mut self) -> ZmqResult<Vec<ZmqMessage>> {
        loop {
            match self.fair_queue.next().await {
                Some((_peer_id, Message::Multipart(messages))) => {
                    return Ok(messages);
                }
                Some((_peer_id, _)) => todo!(),
                None => todo!(),
            };
        }
    }

    pub async fn send_multipart(&mut self, messages: Vec<ZmqMessage>) -> ZmqResult<()> {
        // In normal scenario this will always be only 1 iteration
        // There can be special case when peer has disconnected and his id is still in
        // RR queue This happens because SegQueue don't have an api to delete
        // items from queue. So in such case we'll just pop item and skip it if
        // we don't have a matching peer in peers map
        let mut messages = Message::Multipart(messages);
        loop {
            let next_peer_id = match self.backend.round_robin.pop() {
                Ok(peer) => peer,
                Err(_) => {
                    if let Message::Multipart(messages) = messages {
                        return Err(ZmqError::ReturnToSenderMultipart {
                            reason: "Not connected to peers. Unable to send messages",
                            messages,
                        });
                    } else {
                        panic!("Not supposed to happen");
                    }
                }
            };
            match self.backend.peers.get_mut(&next_peer_id) {
                Some(mut peer) => {
                    let send_result = peer.send_queue.try_send(messages);
                    match send_result {
                        Ok(()) => {
                            self.backend.round_robin.push(next_peer_id.clone());
                            return Ok(());
                        }
                        Err(e) => {
                            if e.is_full() {
                                // Try again later
                                self.backend.round_robin.push(next_peer_id.clone());
                            }
                            messages = e.into_inner();
                            continue;
                        }
                    };
                }
                None => continue,
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
#![feature(globs)]

extern crate router = "route-recognizer";
extern crate conduit;

use std::collections::HashMap;
use std::any::{Any, AnyRefExt};
use std::fmt::Show;

use router::{Router, Match};
use conduit::{Method, Handler, Request, Response};

pub struct RouteBuilder {
    routers: HashMap<Method, Router<Box<Handler + Send + Share>>>
}

impl RouteBuilder {
    pub fn new() -> RouteBuilder {
        RouteBuilder { routers: HashMap::new() }
    }

    pub fn recognize<'a>(&'a self, method: &Method, path: &str)
                         -> Result<Match<&'a Box<Handler + Send + Share>>, String>
    {
        match self.routers.find(method) {
            None => Err(format!("No router found for {}", method)),
            Some(router) => router.recognize(path)
        }
    }

    pub fn map<'a, H: Handler>(&'a mut self, method: Method, pattern: &str,
                               handler: H) -> &'a mut RouteBuilder {
        {
            let router = self.routers.find_or_insert_with(method, |_| Router::new());
            router.add(pattern, box handler as Box<Handler + Send + Share>);
        }
        self
    }

    pub fn get<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(conduit::Get, pattern, handler)
    }

    pub fn post<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(conduit::Post, pattern, handler)
    }

    pub fn put<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(conduit::Put, pattern, handler)
    }

    pub fn delete<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                  -> &'a mut RouteBuilder {
        self.map(conduit::Delete, pattern, handler)
    }

    pub fn head<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(conduit::Head, pattern, handler)
    }
}

impl conduit::Handler for RouteBuilder {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show>> {
        let m = {
            let method = request.method();
            let path = request.path();

            match self.recognize(&method, path) {
                Ok(m) => m,
                Err(e) => return Err(box e as Box<Show>)
            }
        };

        {
            let extensions = request.mut_extensions();
            extensions.insert("router.params", box m.params.clone() as Box<Any>);
        }

        (*m.handler).call(request)
    }
}

pub trait RequestParams<'a> {
    fn params(self) -> &'a router::Params;
}

pub fn params<'a>(req: &'a Request) -> &'a router::Params {
    req.extensions().find(&"router.params")
        .and_then(|a| a.as_ref::<router::Params>())
        .expect("Missing params")
}

impl<'a> RequestParams<'a> for &'a Request {
    fn params(self) -> &'a router::Params {
        params(self)
    }
}

#[cfg(test)]
mod tests {
    extern crate semver;
    use std::io::net::ip::IpAddr;
    use std::collections::HashMap;
    use std::io::MemReader;
    use super::*;

    use conduit;
    use conduit::{Handler, Method, Scheme, Host, Headers, Extensions};

    struct RequestSentinel {
        method: Method,
        path: String,
        extensions: conduit::Extensions
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_string(),
                extensions: HashMap::new(),
                method: method
            }
        }
    }

    impl conduit::Request for RequestSentinel {
        fn http_version(&self) -> semver::Version { unimplemented!() }
        fn conduit_version(&self) -> semver::Version { unimplemented!() }
        fn method(&self) -> Method { self.method }
        fn scheme(&self) -> Scheme { unimplemented!() }
        fn host<'a>(&'a self) -> Host<'a> { unimplemented!() }
        fn virtual_root<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn path<'a>(&'a self) -> &'a str {
            self.path.as_slice()
        }
        fn query_string<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn remote_ip(&self) -> IpAddr { unimplemented!() }
        fn content_length(&self) -> Option<uint> { unimplemented!() }
        fn headers<'a>(&'a self) -> &'a Headers { unimplemented!() }
        fn body<'a>(&'a mut self) -> &'a mut Reader { unimplemented!() }
        fn extensions<'a>(&'a self) -> &'a Extensions {
            &self.extensions
        }
        fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
            &mut self.extensions
        }
    }

    #[test]
    fn basic_get() {
        let router = test_router();
        let mut req = RequestSentinel::new(conduit::Get, "/posts/1");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_string().unwrap(), "1, Get".to_string());
    }

    #[test]
    fn basic_post() {
        let router = test_router();
        let mut req = RequestSentinel::new(conduit::Post, "/posts/10");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_string().unwrap(), "10, Post".to_string());
    }

    #[test]
    fn nonexistent_route() {
        let router = test_router();
        let mut req = RequestSentinel::new(conduit::Post, "/nonexistent");
        router.call(&mut req).err().expect("No response");
    }

    fn test_router() -> RouteBuilder {
        let mut router = RouteBuilder::new();
        router.post("/posts/:id", test_handler);
        router.get("/posts/:id", test_handler);
        router
    }

    fn test_handler(req: &mut conduit::Request) -> Result<conduit::Response, ()> {
        let mut res = vec!();
        res.push(req.params()["id"]);
        res.push(format!("{}", req.method()));

        Ok(conduit::Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: box MemReader::new(res.connect(", ").into_bytes())
        })
    }
}
<commit_msg>Update to master<commit_after>#![feature(macro_rules)]
#![feature(globs)]

extern crate router = "route-recognizer";
extern crate conduit;

use std::collections::HashMap;
use std::any::{Any, AnyRefExt};
use std::fmt::Show;

use router::{Router, Match};
use conduit::{Method, Handler, Request, Response};

pub struct RouteBuilder {
    routers: HashMap<Method, Router<Box<Handler + Send + Share>>>
}

impl RouteBuilder {
    pub fn new() -> RouteBuilder {
        RouteBuilder { routers: HashMap::new() }
    }

    pub fn recognize<'a>(&'a self, method: &Method, path: &str)
                         -> Result<Match<&'a Box<Handler + Send + Share>>, String>
    {
        match self.routers.find(method) {
            None => Err(format!("No router found for {}", method)),
            Some(router) => router.recognize(path)
        }
    }

    pub fn map<'a, H: Handler>(&'a mut self, method: Method, pattern: &str,
                               handler: H) -> &'a mut RouteBuilder {
        {
            let router = self.routers.find_or_insert_with(method, |_| Router::new());
            router.add(pattern, box handler as Box<Handler + Send + Share>);
        }
        self
    }

    pub fn get<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(conduit::Get, pattern, handler)
    }

    pub fn post<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(conduit::Post, pattern, handler)
    }

    pub fn put<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                               -> &'a mut RouteBuilder {
        self.map(conduit::Put, pattern, handler)
    }

    pub fn delete<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                  -> &'a mut RouteBuilder {
        self.map(conduit::Delete, pattern, handler)
    }

    pub fn head<'a, H: Handler>(&'a mut self, pattern: &str, handler: H)
                                -> &'a mut RouteBuilder {
        self.map(conduit::Head, pattern, handler)
    }
}

impl conduit::Handler for RouteBuilder {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show>> {
        let m = {
            let method = request.method();
            let path = request.path();

            match self.recognize(&method, path) {
                Ok(m) => m,
                Err(e) => return Err(box e as Box<Show>)
            }
        };

        {
            let extensions = request.mut_extensions();
            extensions.insert("router.params", box m.params.clone() as Box<Any>);
        }

        (*m.handler).call(request)
    }
}

pub trait RequestParams<'a> {
    fn params(self) -> &'a router::Params;
}

pub fn params<'a>(req: &'a Request) -> &'a router::Params {
    req.extensions().find(&"router.params")
        .and_then(|a| a.as_ref::<router::Params>())
        .expect("Missing params")
}

impl<'a> RequestParams<'a> for &'a Request {
    fn params(self) -> &'a router::Params {
        params(self)
    }
}

#[cfg(test)]
mod tests {
    extern crate semver;
    use std::io::net::ip::IpAddr;
    use std::collections::HashMap;
    use std::io::MemReader;
    use super::*;

    use conduit;
    use conduit::{Handler, Method, Scheme, Host, Headers, Extensions};

    struct RequestSentinel {
        method: Method,
        path: String,
        extensions: conduit::Extensions
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_string(),
                extensions: HashMap::new(),
                method: method
            }
        }
    }

    impl conduit::Request for RequestSentinel {
        fn http_version(&self) -> semver::Version { unimplemented!() }
        fn conduit_version(&self) -> semver::Version { unimplemented!() }
        fn method(&self) -> Method { self.method }
        fn scheme(&self) -> Scheme { unimplemented!() }
        fn host<'a>(&'a self) -> Host<'a> { unimplemented!() }
        fn virtual_root<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn path<'a>(&'a self) -> &'a str {
            self.path.as_slice()
        }
        fn query_string<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn remote_ip(&self) -> IpAddr { unimplemented!() }
        fn content_length(&self) -> Option<uint> { unimplemented!() }
        fn headers<'a>(&'a self) -> &'a Headers { unimplemented!() }
        fn body<'a>(&'a mut self) -> &'a mut Reader { unimplemented!() }
        fn extensions<'a>(&'a self) -> &'a Extensions {
            &self.extensions
        }
        fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
            &mut self.extensions
        }
    }

    #[test]
    fn basic_get() {
        let router = test_router();
        let mut req = RequestSentinel::new(conduit::Get, "/posts/1");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_string().unwrap(), "1, Get".to_string());
    }

    #[test]
    fn basic_post() {
        let router = test_router();
        let mut req = RequestSentinel::new(conduit::Post, "/posts/10");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_string().unwrap(), "10, Post".to_string());
    }

    #[test]
    fn nonexistent_route() {
        let router = test_router();
        let mut req = RequestSentinel::new(conduit::Post, "/nonexistent");
        router.call(&mut req).err().expect("No response");
    }

    fn test_router() -> RouteBuilder {
        let mut router = RouteBuilder::new();
        router.post("/posts/:id", test_handler);
        router.get("/posts/:id", test_handler);
        router
    }

    fn test_handler(req: &mut conduit::Request) -> Result<conduit::Response, ()> {
        let mut res = vec!();
        res.push(req.params()["id"].clone());
        res.push(format!("{}", req.method()));

        Ok(conduit::Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: box MemReader::new(res.connect(", ").into_bytes())
        })
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::io;
use std::slice;
use std::default::Default;

use color;
use color:: {
    Pixel,
    ColorType
};

/// An enumeration of Image Errors
#[deriving(Show, PartialEq, Eq)]
pub enum ImageError {
    ///The Image is not formatted properly
    FormatError(String),

    ///The Image's dimensions are either too small or too large
    DimensionError,

    ///The Decoder does not support this image format
    UnsupportedError(String),

    ///The Decoder does not support this color type
    UnsupportedColor(ColorType),

    ///Not enough data was provided to the Decoder
    ///to decode the image
    NotEnoughData,

    ///An I/O Error occurred while decoding the image
    IoError(io::IoError),

    ///The end of the image has been reached
    ImageEnd
}

pub type ImageResult<T> = Result<T, ImageError>;

/// An enumeration of supported image formats.
/// Not all formats support both encoding and decoding.
#[deriving(PartialEq, Eq, Show)]
pub enum ImageFormat {
    /// An Image in PNG Format
    PNG,

    /// An Image in JPEG Format
    JPEG,

    /// An Image in GIF Format
    GIF,

    /// An Image in WEBP Format
    WEBP,

    /// An Image in PPM Format
    PPM
}

/// The trait that all decoders implement
pub trait ImageDecoder {
    ///Return a tuple containing the width and height of the image
    fn dimensions(&mut self) -> ImageResult<(u32, u32)>;

    ///Return the color type of the image e.g RGB(8) (8bit RGB)
    fn colortype(&mut self) -> ImageResult<ColorType>;

    ///Returns the length in bytes of one decoded row of the image
    fn row_len(&mut self) -> ImageResult<uint>;

    ///Read one row from the image into buf
    ///Returns the row index
    fn read_scanline(&mut self, buf: &mut [u8]) -> ImageResult<u32>;

    ///Decode the entire image and return it as a Vector
    fn read_image(&mut self) -> ImageResult<Vec<u8>>;

    ///Decode a specific region of the image, represented by the rectangle
    ///starting from ```x``` and ```y``` and having ```length``` and ```width```
    fn load_rect(&mut self, x: u32, y: u32, length: u32, width: u32) -> ImageResult<Vec<u8>> {
        let (w, h) = try!(self.dimensions());

        if length > h || width > w || x > w || y > h {
            return Err(DimensionError)
        }

        let c = try!(self.colortype());

        let bpp = color::bits_per_pixel(c) / 8;

        let rowlen  = try!(self.row_len());

        let mut buf = Vec::from_elem(length as uint * width as uint * bpp, 0u8);
        let mut tmp = Vec::from_elem(rowlen, 0u8);

        loop {
            let row = try!(self.read_scanline(tmp.as_mut_slice()));

            if row - 1 == y {
                break
            }
        }

        for i in range(0, length as uint) {
            {
                let from = tmp.slice_from(x as uint * bpp)
                              .slice_to(width as uint * bpp);

                let to   = buf.slice_from_mut(i * width as uint * bpp)
                              .slice_to_mut(width as uint * bpp);

                slice::bytes::copy_memory(to, from);
            }

            let _ = try!(self.read_scanline(tmp.as_mut_slice()));
        }

        Ok(buf)
    }
}

/// Immutable pixel iterator
pub struct Pixels<'a, I:'a> {
    image:  &'a I,
    x:      u32,
    y:      u32,
    width:  u32,
    height: u32
}

impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> Iterator<(u32, u32, P)> for Pixels<'a, I> {
    fn next(&mut self) -> Option<(u32, u32, P)> {
        if self.x >= self.width {
            self.x =  0;
            self.y += 1;
        }

        if self.y >= self.height {
            None
        } else {
            let pixel = self.image.get_pixel(self.x, self.y);
            let p = (self.x, self.y, pixel);

            self.x += 1;

            Some(p)
        }
    }
}

/// Mutable pixel iterator
pub struct MutPixels<'a, I:'a> {
    image:  &'a mut I,
    x:      u32,
    y:      u32,
    width:  u32,
    height: u32
}

impl<'a, T: Primitive, P: Pixel<T>, I: MutableRefImage<P>> Iterator<(u32, u32, &'a mut P)> for MutPixels<'a, I> {
    fn next(&mut self) -> Option<(u32, u32, &'a mut P)> {
        if self.x >= self.width {
            self.x =  0;
            self.y += 1;
        }

        if self.y >= self.height {
            None
        } else {
            let tmp = self.image.get_mut_pixel(self.x, self.y);

            //error: lifetime of `self` is too short to guarantee its contents
            //       can be safely reborrowed...
            let ptr = unsafe {
                mem::transmute(tmp)
            };

            let p = (self.x, self.y, ptr);

            self.x += 1;

            Some(p)
        }
    }
}

///A trait for manipulating images.
pub trait GenericImage<P> {
    ///The width and height of this image.
    fn dimensions(&self) -> (u32, u32);

    ///The bounding rectangle of this image.
    fn bounds(&self) -> (u32, u32, u32, u32);

    ///Return the pixel located at (x, y)
    fn get_pixel(&self, x: u32, y: u32) -> P;

    ///Put a pixel at location (x, y)
    fn put_pixel(&mut self, x: u32, y: u32, pixel: P);

    ///Return an Iterator over the pixels of this image.
    ///The iterator yields the coordinates of each pixel
    ///along with their value
    fn pixels(&self) -> Pixels<Self> {
        let (width, height) = self.dimensions();

        Pixels {
            image:  self,
            x:      0,
            y:      0,
            width:  width,
            height: height,
        }
    }
}

///A trait for images that allow providing mutable references to pixels.
pub trait MutableRefImage<P>: GenericImage<P> {
    ///Return a mutable reference to the pixel located at (x, y)
    fn get_mut_pixel(&mut self, x: u32, y: u32) -> &mut P;

    ///Return an Iterator over mutable pixels of this image.
    ///The iterator yields the coordinates of each pixel
    ///along with a mutable reference to them.
    fn mut_pixels(&mut self) -> MutPixels<Self> {
        let (width, height) = self.dimensions();

        MutPixels {
            image:  self,
            x:      0,
            y:      0,
            width:  width,
            height: height,
        }
    }
}

///An Image whose pixels are contained within a vector
#[deriving(Clone)]
pub struct ImageBuf<P> {
    pixels:  Vec<P>,
    width:   u32,
    height:  u32,
}

impl<T: Primitive, P: Pixel<T>> ImageBuf<P> {
    ///Construct a new ImageBuf with the specified width and height.
    pub fn new(width: u32, height: u32) -> ImageBuf<P> {
        let pixel: P = Default::default();
        let pixels = Vec::from_elem((width * height) as uint, pixel.clone());

        ImageBuf {
            pixels:  pixels,
            width:   width,
            height:  height,
        }
    }

    ///Construct a new ImageBuf by repeated application of the supplied function.
    ///The arguments to the function are the pixel's x and y coordinates.
    pub fn from_fn(width: u32, height: u32, f: | u32, u32 | -> P) -> ImageBuf<P> {
        let mut pixels: Vec<P> = Vec::with_capacity((width * height) as uint);

        for y in range(0, height) {
            for x in range(0, width) {
                pixels.insert((y * width + x) as uint, f(x, y));
            }
        }

        ImageBuf::from_pixels(pixels, width, height)
    }

    ///Construct a new ImageBuf from a vector of pixels.
    pub fn from_pixels(pixels: Vec<P>, width: u32, height: u32) -> ImageBuf<P> {
        ImageBuf {
            pixels: pixels,
            width:  width,
            height: height,
        }
    }

    ///Construct a new ImageBuf from a pixel.
    pub fn from_pixel(width: u32, height: u32, pixel: P) -> ImageBuf<P> {
        let buf = Vec::from_elem(width as uint * height as uint, pixel.clone());

        ImageBuf::from_pixels(buf, width, height)
    }

    ///Return an immutable reference to this image's pixel buffer
    pub fn pixelbuf(&self) -> & [P] {
        self.pixels.as_slice()
    }

    ///Return a mutable reference to this image's pixel buffer
    pub fn mut_pixelbuf(&mut self) -> &mut [P] {
        self.pixels.as_mut_slice()
    }

    ///Destroy this ImageBuf, returning the internal vector
    pub fn into_vec(self) -> Vec<P> {
        self.pixels
    }
}

impl<T: Primitive, P: Pixel<T> + Clone + Copy> GenericImage<P> for ImageBuf<P> {
    fn dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    fn bounds(&self) -> (u32, u32, u32, u32) {
        (0, 0, self.width, self.height)
    }

    fn get_pixel(&self, x: u32, y: u32) -> P {
        let index  = y * self.width + x;

        self.pixels[index as uint]
    }

    fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
        let index  = y * self.width + x;
        let buf    = self.pixels.as_mut_slice();

        buf[index as uint] = pixel;
    }
}

impl<T: Primitive, P: Pixel<T> + Clone + Copy> MutableRefImage<P> for ImageBuf<P> {
    fn get_mut_pixel(&mut self, x: u32, y: u32) -> &mut P {
        let index = y * self.width + x;

        self.pixels.get_mut(index as uint)
    }
}

impl<T: Primitive, P: Pixel<T>> Index<(u32, u32), P> for ImageBuf<P> {
    fn index(&self, coords: &(u32, u32)) -> &P {
        let &(x, y) = coords;
        let index  = y * self.width + x;

        &self.pixels[index as uint]
    }
}

/// A View into another image
pub struct SubImage <'a, I:'a> {
    image:   &'a mut I,
    xoffset: u32,
    yoffset: u32,
    xstride: u32,
    ystride: u32,
}

impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> SubImage<'a, I> {
    ///Construct a new subimage
    pub fn new(image: &mut I, x: u32, y: u32, width: u32, height: u32) -> SubImage<I> {
        SubImage {
            image:   image,
            xoffset: x,
            yoffset: y,
            xstride: width,
            ystride: height,
        }
    }

    ///Return a mutable reference to the wrapped image.
    pub fn mut_inner(&mut self) -> &mut I {
        &mut (*self.image)
    }

    ///Change the coordinates of this subimage.
    pub fn change_bounds(&mut self, x: u32, y: u32, width: u32, height: u32) {
        self.xoffset = x;
        self.yoffset = y;
        self.xstride = width;
        self.ystride = height;
    }

    ///Convert this subimage to an ImageBuf
    pub fn to_image(&self) -> ImageBuf<P> {
        let p: P = Default::default();
        let mut out = ImageBuf::from_pixel(self.xstride, self.ystride, p.clone());

        for y in range(0, self.ystride) {
            for x in range(0, self.xstride) {
                let p = self.get_pixel(x, y);
                out.put_pixel(x, y, p);
            }
        }

        out
    }
}

impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> GenericImage<P> for SubImage<'a, I> {
    fn dimensions(&self) -> (u32, u32) {
        (self.xstride, self.ystride)
    }

    fn bounds(&self) -> (u32, u32, u32, u32) {
        (self.xoffset, self.yoffset, self.xstride, self.ystride)
    }

    fn get_pixel(&self, x: u32, y: u32) -> P {
        self.image.get_pixel(x + self.xoffset, y + self.yoffset)
    }

    fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
        self.image.put_pixel(x + self.xoffset, y + self.yoffset, pixel)
    }
}

impl<'a, T: Primitive, P: Pixel<T>, I: MutableRefImage<P>> MutableRefImage<P> for SubImage<'a, I> {
    fn get_mut_pixel(&mut self, x: u32, y: u32) -> &mut P {
        self.image.get_mut_pixel(x + self.xoffset, y + self.yoffset)
    }
}
<commit_msg>Added `with_bytes` and `with_mut_bytes`<commit_after>use std::mem;
use std::io;
use std::slice;
use std::default::Default;

use color;
use color:: {
    Pixel,
    ColorType
};

/// An enumeration of Image Errors
#[deriving(Show, PartialEq, Eq)]
pub enum ImageError {
    ///The Image is not formatted properly
    FormatError(String),

    ///The Image's dimensions are either too small or too large
    DimensionError,

    ///The Decoder does not support this image format
    UnsupportedError(String),

    ///The Decoder does not support this color type
    UnsupportedColor(ColorType),

    ///Not enough data was provided to the Decoder
    ///to decode the image
    NotEnoughData,

    ///An I/O Error occurred while decoding the image
    IoError(io::IoError),

    ///The end of the image has been reached
    ImageEnd
}

pub type ImageResult<T> = Result<T, ImageError>;

/// An enumeration of supported image formats.
/// Not all formats support both encoding and decoding.
#[deriving(PartialEq, Eq, Show)]
pub enum ImageFormat {
    /// An Image in PNG Format
    PNG,

    /// An Image in JPEG Format
    JPEG,

    /// An Image in GIF Format
    GIF,

    /// An Image in WEBP Format
    WEBP,

    /// An Image in PPM Format
    PPM
}

/// The trait that all decoders implement
pub trait ImageDecoder {
    ///Return a tuple containing the width and height of the image
    fn dimensions(&mut self) -> ImageResult<(u32, u32)>;

    ///Return the color type of the image e.g RGB(8) (8bit RGB)
    fn colortype(&mut self) -> ImageResult<ColorType>;

    ///Returns the length in bytes of one decoded row of the image
    fn row_len(&mut self) -> ImageResult<uint>;

    ///Read one row from the image into buf
    ///Returns the row index
    fn read_scanline(&mut self, buf: &mut [u8]) -> ImageResult<u32>;

    ///Decode the entire image and return it as a Vector
    fn read_image(&mut self) -> ImageResult<Vec<u8>>;

    ///Decode a specific region of the image, represented by the rectangle
    ///starting from ```x``` and ```y``` and having ```length``` and ```width```
    fn load_rect(&mut self, x: u32, y: u32, length: u32, width: u32) -> ImageResult<Vec<u8>> {
        let (w, h) = try!(self.dimensions());

        if length > h || width > w || x > w || y > h {
            return Err(DimensionError)
        }

        let c = try!(self.colortype());

        let bpp = color::bits_per_pixel(c) / 8;

        let rowlen  = try!(self.row_len());

        let mut buf = Vec::from_elem(length as uint * width as uint * bpp, 0u8);
        let mut tmp = Vec::from_elem(rowlen, 0u8);

        loop {
            let row = try!(self.read_scanline(tmp.as_mut_slice()));

            if row - 1 == y {
                break
            }
        }

        for i in range(0, length as uint) {
            {
                let from = tmp.slice_from(x as uint * bpp)
                              .slice_to(width as uint * bpp);

                let to   = buf.slice_from_mut(i * width as uint * bpp)
                              .slice_to_mut(width as uint * bpp);

                slice::bytes::copy_memory(to, from);
            }

            let _ = try!(self.read_scanline(tmp.as_mut_slice()));
        }

        Ok(buf)
    }
}

/// Immutable pixel iterator
pub struct Pixels<'a, I:'a> {
    image:  &'a I,
    x:      u32,
    y:      u32,
    width:  u32,
    height: u32
}

impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> Iterator<(u32, u32, P)> for Pixels<'a, I> {
    fn next(&mut self) -> Option<(u32, u32, P)> {
        if self.x >= self.width {
            self.x =  0;
            self.y += 1;
        }

        if self.y >= self.height {
            None
        } else {
            let pixel = self.image.get_pixel(self.x, self.y);
            let p = (self.x, self.y, pixel);

            self.x += 1;

            Some(p)
        }
    }
}

/// Mutable pixel iterator
pub struct MutPixels<'a, I:'a> {
    image:  &'a mut I,
    x:      u32,
    y:      u32,
    width:  u32,
    height: u32
}

impl<'a, T: Primitive, P: Pixel<T>, I: MutableRefImage<P>> Iterator<(u32, u32, &'a mut P)> for MutPixels<'a, I> {
    fn next(&mut self) -> Option<(u32, u32, &'a mut P)> {
        if self.x >= self.width {
            self.x =  0;
            self.y += 1;
        }

        if self.y >= self.height {
            None
        } else {
            let tmp = self.image.get_mut_pixel(self.x, self.y);

            //error: lifetime of `self` is too short to guarantee its contents
            //       can be safely reborrowed...
            let ptr = unsafe {
                mem::transmute(tmp)
            };

            let p = (self.x, self.y, ptr);

            self.x += 1;

            Some(p)
        }
    }
}

///A trait for manipulating images.
pub trait GenericImage<P> {
    ///The width and height of this image.
    fn dimensions(&self) -> (u32, u32);

    ///The bounding rectangle of this image.
    fn bounds(&self) -> (u32, u32, u32, u32);

    ///Return the pixel located at (x, y)
    fn get_pixel(&self, x: u32, y: u32) -> P;

    ///Put a pixel at location (x, y)
    fn put_pixel(&mut self, x: u32, y: u32, pixel: P);

    ///Return an Iterator over the pixels of this image.
    ///The iterator yields the coordinates of each pixel
    ///along with their value
    fn pixels(&self) -> Pixels<Self> {
        let (width, height) = self.dimensions();

        Pixels {
            image:  self,
            x:      0,
            y:      0,
            width:  width,
            height: height,
        }
    }
}

///A trait for images that allow providing mutable references to pixels.
pub trait MutableRefImage<P>: GenericImage<P> {
    ///Return a mutable reference to the pixel located at (x, y)
    fn get_mut_pixel(&mut self, x: u32, y: u32) -> &mut P;

    ///Return an Iterator over mutable pixels of this image.
    ///The iterator yields the coordinates of each pixel
    ///along with a mutable reference to them.
    fn mut_pixels(&mut self) -> MutPixels<Self> {
        let (width, height) = self.dimensions();

        MutPixels {
            image:  self,
            x:      0,
            y:      0,
            width:  width,
            height: height,
        }
    }
}

///An Image whose pixels are contained within a vector
#[deriving(Clone)]
pub struct ImageBuf<P> {
    pixels:  Vec<P>,
    width:   u32,
    height:  u32,
}

impl<T: Primitive, P: Pixel<T>> ImageBuf<P> {
    ///Construct a new ImageBuf with the specified width and height.
    pub fn new(width: u32, height: u32) -> ImageBuf<P> {
        let pixel: P = Default::default();
        let pixels = Vec::from_elem((width * height) as uint, pixel.clone());

        ImageBuf {
            pixels:  pixels,
            width:   width,
            height:  height,
        }
    }

    ///Construct a new ImageBuf by repeated application of the supplied function.
    ///The arguments to the function are the pixel's x and y coordinates.
    pub fn from_fn(width: u32, height: u32, f: | u32, u32 | -> P) -> ImageBuf<P> {
        let mut pixels: Vec<P> = Vec::with_capacity((width * height) as uint);

        for y in range(0, height) {
            for x in range(0, width) {
                pixels.insert((y * width + x) as uint, f(x, y));
            }
        }

        ImageBuf::from_pixels(pixels, width, height)
    }

    ///Construct a new ImageBuf from a vector of pixels.
    pub fn from_pixels(pixels: Vec<P>, width: u32, height: u32) -> ImageBuf<P> {
        ImageBuf {
            pixels: pixels,
            width:  width,
            height: height,
        }
    }

    ///Construct a new ImageBuf from a pixel.
    pub fn from_pixel(width: u32, height: u32, pixel: P) -> ImageBuf<P> {
        let buf = Vec::from_elem(width as uint * height as uint, pixel.clone());

        ImageBuf::from_pixels(buf, width, height)
    }

    ///Return an immutable reference to this image's pixel buffer
    pub fn pixelbuf(&self) -> & [P] {
        self.pixels.as_slice()
    }

    ///Return a mutable reference to this image's pixel buffer
    pub fn mut_pixelbuf(&mut self) -> &mut [P] {
        self.pixels.as_mut_slice()
    }

    ///Destroy this ImageBuf, returning the internal vector
    pub fn into_vec(self) -> Vec<P> {
        self.pixels
    }

    ///Calls closure with immutable raw data of the image.
    ///Returns the result from the closure.
    pub fn with_bytes<U>(&self, f: | &[u8] | -> U) -> U {
        use std::mem::{ size_of, transmute };
        use std::raw::Slice;
        // Compute size of slice in bytes.
        let len = size_of::<P>() * self.pixels.len();
        let slice = Slice { data: self.pixels.as_ptr() as *const u8, len: len };
        f(unsafe { transmute(slice) })
    }

    ///Calls closure with mutable raw data of the image.
    ///Returns the result from the closure.
    pub fn with_mut_bytes<U>(&mut self, f: | &mut [u8] | -> U) -> U {
        use std::mem::{ size_of, transmute };
        use std::raw::Slice;
        // Compute size of slice in bytes.
        let len = size_of::<P>() * self.pixels.len();
        let slice = Slice { data: self.pixels.as_mut_ptr() as *const u8, len: len };
        f(unsafe { transmute(slice) })
    }
}

impl<T: Primitive, P: Pixel<T> + Clone + Copy> GenericImage<P> for ImageBuf<P> {
    fn dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    fn bounds(&self) -> (u32, u32, u32, u32) {
        (0, 0, self.width, self.height)
    }

    fn get_pixel(&self, x: u32, y: u32) -> P {
        let index  = y * self.width + x;

        self.pixels[index as uint]
    }

    fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
        let index  = y * self.width + x;
        let buf    = self.pixels.as_mut_slice();

        buf[index as uint] = pixel;
    }
}

impl<T: Primitive, P: Pixel<T> + Clone + Copy> MutableRefImage<P> for ImageBuf<P> {
    fn get_mut_pixel(&mut self, x: u32, y: u32) -> &mut P {
        let index = y * self.width + x;

        self.pixels.get_mut(index as uint)
    }
}

impl<T: Primitive, P: Pixel<T>> Index<(u32, u32), P> for ImageBuf<P> {
    fn index(&self, coords: &(u32, u32)) -> &P {
        let &(x, y) = coords;
        let index  = y * self.width + x;

        &self.pixels[index as uint]
    }
}

/// A View into another image
pub struct SubImage <'a, I:'a> {
    image:   &'a mut I,
    xoffset: u32,
    yoffset: u32,
    xstride: u32,
    ystride: u32,
}

impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> SubImage<'a, I> {
    ///Construct a new subimage
    pub fn new(image: &mut I, x: u32, y: u32, width: u32, height: u32) -> SubImage<I> {
        SubImage {
            image:   image,
            xoffset: x,
            yoffset: y,
            xstride: width,
            ystride: height,
        }
    }

    ///Return a mutable reference to the wrapped image.
    pub fn mut_inner(&mut self) -> &mut I {
        &mut (*self.image)
    }

    ///Change the coordinates of this subimage.
    pub fn change_bounds(&mut self, x: u32, y: u32, width: u32, height: u32) {
        self.xoffset = x;
        self.yoffset = y;
        self.xstride = width;
        self.ystride = height;
    }

    ///Convert this subimage to an ImageBuf
    pub fn to_image(&self) -> ImageBuf<P> {
        let p: P = Default::default();
        let mut out = ImageBuf::from_pixel(self.xstride, self.ystride, p.clone());

        for y in range(0, self.ystride) {
            for x in range(0, self.xstride) {
                let p = self.get_pixel(x, y);
                out.put_pixel(x, y, p);
            }
        }

        out
    }
}

impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> GenericImage<P> for SubImage<'a, I> {
    fn dimensions(&self) -> (u32, u32) {
        (self.xstride, self.ystride)
    }

    fn bounds(&self) -> (u32, u32, u32, u32) {
        (self.xoffset, self.yoffset, self.xstride, self.ystride)
    }

    fn get_pixel(&self, x: u32, y: u32) -> P {
        self.image.get_pixel(x + self.xoffset, y + self.yoffset)
    }

    fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
        self.image.put_pixel(x + self.xoffset, y + self.yoffset, pixel)
    }
}

impl<'a, T: Primitive, P: Pixel<T>, I: MutableRefImage<P>> MutableRefImage<P> for SubImage<'a, I> {
    fn get_mut_pixel(&mut self, x: u32, y: u32) -> &mut P {
        self.image.get_mut_pixel(x + self.xoffset, y + self.yoffset)
    }
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::collections::TreeMap;

use quire::validate as V;
use quire::ast as A;

pub use self::main::MainCommand;
pub use self::child::ChildCommand;

#[deriving(Decodable, Clone, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum Pid1Mode {
    exec = 0,
    wait = 1,
    wait_all_children = 2,
}

#[deriving(Decodable, Show, Clone, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum SuperviseMode {
    wait_all,
    stop_on_failure,
    restart,
}

#[deriving(Decodable, Show, Clone, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum WriteMode {
    read_only,
    transient_reflink_copy,
    transient_hard_link_copy,
}

#[deriving(Decodable, Clone, PartialEq, Eq)]
pub struct CommandInfo {
    // Common
    pub description: Option<String>,
    pub banner: Option<String>,
    pub banner_delay: i64,
    pub epilog: Option<String>,

    // Command
    pub pid1mode: Pid1Mode,
    pub work_dir: Option<String>,
    pub container: String,
    pub accepts_arguments: Option<bool>,
    pub environ: TreeMap<String, String>,
    pub inherit_environ: Vec<String>,
    pub write_mode: WriteMode,
    pub run: Vec<String>,
}

#[deriving(Decodable, Clone, PartialEq, Eq)]
pub struct ChildCommandInfo {
    // Command
    pub pid1mode: Pid1Mode,
    pub work_dir: Option<String>,
    pub container: String,
    pub accepts_arguments: Option<bool>,
    pub environ: TreeMap<String, String>,
    pub inherit_environ: Vec<String>,
    pub write_mode: WriteMode,
    pub run: Vec<String>,
}

#[deriving(Decodable, Clone, PartialEq, Eq)]
pub struct SuperviseInfo {
    // Common
    pub description: Option<String>,
    pub banner: Option<String>,
    pub banner_delay: i64,
    pub epilog: Option<String>,

    // Supervise
    pub mode: SuperviseMode,
    pub children: TreeMap<String, ChildCommand>,
}

pub mod main {
    use super::{CommandInfo, SuperviseInfo};

    #[deriving(Decodable, PartialEq, Eq, Clone)]
    pub enum MainCommand {
        Command(CommandInfo),
        Supervise(SuperviseInfo),
    }

    impl MainCommand {
        pub fn description<'x>(&'x self) -> Option<&'x String> {
            match *self {
                Command(ref cmd) => cmd.description.as_ref(),
                Supervise(ref cmd) => cmd.description.as_ref(),
            }
        }
    }
}

pub mod child {
    use super::{ChildCommandInfo};

    #[deriving(Decodable, PartialEq, Eq, Clone)]
    pub enum ChildCommand {
        Command(ChildCommandInfo),
    }

    impl ChildCommand {
        pub fn get_container<'x>(&'x self) -> &String {
            match *self {
                Command(ref info) => &info.container,
            }
        }
    }
}

fn shell_command(ast: A::Ast) -> Vec<A::Ast> {
    match ast {
        A::Scalar(pos, _, style, value) => {
            return vec!(
                A::Scalar(pos.clone(), A::NonSpecific, A::Plain,
                          "/bin/sh".to_string()),
                A::Scalar(pos.clone(), A::NonSpecific, A::Plain,
                          "-c".to_string()),
                A::Scalar(pos.clone(), A::NonSpecific, style,
                          value),
                );
        }
        _ => unreachable!(),
    }
}

fn run_fields<'a>() -> Vec<(String, Box<V::Validator + 'a>)> {
    return vec!(
        ("pid1mode".to_string(), box V::Scalar {
            default: Some("wait".to_string()),
            .. Default::default()} as Box<V::Validator>),
        ("work_dir".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        ("container".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        ("accepts_arguments".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        ("environ".to_string(), box V::Mapping {
            key_element: box V::Scalar {
                .. Default::default()} as Box<V::Validator>,
            value_element: box V::Scalar {
                .. Default::default()} as Box<V::Validator>,
            .. Default::default()} as Box<V::Validator>),
        ("inherit_environ".to_string(), box V::Sequence {
            element: box V::Scalar {
                .. Default::default()} as Box<V::Validator>,
            .. Default::default()} as Box<V::Validator>),
        ("write_mode".to_string(), box V::Scalar {
            default: Some("read-only".to_string()),
            .. Default::default()} as Box<V::Validator>),
        ("run".to_string(), box V::Sequence {
            from_scalar: Some(shell_command),
            element: box V::Scalar {
                .. Default::default()} as Box<V::Validator>,
            .. Default::default()} as Box<V::Validator>),
        );
}

fn command_fields<'a>() -> Vec<(String, Box<V::Validator + 'a>)> {
    return vec!(
        ("description".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        ("banner".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        ("banner_delay".to_string(), box V::Numeric {
            min: Some(0),
            default: Some(0i64),
            .. Default::default()} as Box<V::Validator>),
        ("epilog".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        );
}

fn subcommand_validator<'a>() -> Box<V::Validator + 'a> {
    return box V::Enum { options: vec!(
        ("Command".to_string(), box V::Structure {
            members: run_fields(),
            .. Default::default()} as Box<V::Validator>),
    ), .. Default::default()} as Box<V::Validator>;
}

pub fn command_validator<'a>() -> Box<V::Validator + 'a> {
    let mut command_members = vec!();
    command_members.extend(command_fields().into_iter());
    command_members.extend(run_fields().into_iter());

    let mut supervise_members = vec!(
        ("mode".to_string(), box V::Scalar {
            default: Some("stop-on-failure".to_string()),
            .. Default::default()} as Box<V::Validator>),
        ("children".to_string(), box V::Mapping {
            key_element: box V::Scalar {
                ..Default::default()} as Box<V::Validator>,
            value_element: subcommand_validator(),
            .. Default::default()} as Box<V::Validator>),
        );
    supervise_members.extend(command_fields().into_iter());

    return box V::Enum { options: vec!(
        ("Command".to_string(), box V::Structure {
            members: command_members,
            .. Default::default()} as Box<V::Validator>),
        ("Supervise".to_string(), box V::Structure {
            members: supervise_members,
            .. Default::default()} as Box<V::Validator>),
    ), .. Default::default()} as Box<V::Validator>;
}
<commit_msg>Fix typo<commit_after>use std::default::Default;
use std::collections::TreeMap;

use quire::validate as V;
use quire::ast as A;

pub use self::main::MainCommand;
pub use self::child::ChildCommand;

#[deriving(Decodable, Clone, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum Pid1Mode {
    exec = 0,
    wait = 1,
    wait_all_children = 2,
}

#[deriving(Decodable, Show, Clone, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum SuperviseMode {
    wait_all,
    stop_on_failure,
    restart,
}

#[deriving(Decodable, Show, Clone, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum WriteMode {
    read_only,
    transient_reflink_copy,
    transient_hardlink_copy,
}

#[deriving(Decodable, Clone, PartialEq, Eq)]
pub struct CommandInfo {
    // Common
    pub description: Option<String>,
    pub banner: Option<String>,
    pub banner_delay: i64,
    pub epilog: Option<String>,

    // Command
    pub pid1mode: Pid1Mode,
    pub work_dir: Option<String>,
    pub container: String,
    pub accepts_arguments: Option<bool>,
    pub environ: TreeMap<String, String>,
    pub inherit_environ: Vec<String>,
    pub write_mode: WriteMode,
    pub run: Vec<String>,
}

#[deriving(Decodable, Clone, PartialEq, Eq)]
pub struct ChildCommandInfo {
    // Command
    pub pid1mode: Pid1Mode,
    pub work_dir: Option<String>,
    pub container: String,
    pub accepts_arguments: Option<bool>,
    pub environ: TreeMap<String, String>,
    pub inherit_environ: Vec<String>,
    pub write_mode: WriteMode,
    pub run: Vec<String>,
}

#[deriving(Decodable, Clone, PartialEq, Eq)]
pub struct SuperviseInfo {
    // Common
    pub description: Option<String>,
    pub banner: Option<String>,
    pub banner_delay: i64,
    pub epilog: Option<String>,

    // Supervise
    pub mode: SuperviseMode,
    pub children: TreeMap<String, ChildCommand>,
}

pub mod main {
    use super::{CommandInfo, SuperviseInfo};

    #[deriving(Decodable, PartialEq, Eq, Clone)]
    pub enum MainCommand {
        Command(CommandInfo),
        Supervise(SuperviseInfo),
    }

    impl MainCommand {
        pub fn description<'x>(&'x self) -> Option<&'x String> {
            match *self {
                Command(ref cmd) => cmd.description.as_ref(),
                Supervise(ref cmd) => cmd.description.as_ref(),
            }
        }
    }
}

pub mod child {
    use super::{ChildCommandInfo};

    #[deriving(Decodable, PartialEq, Eq, Clone)]
    pub enum ChildCommand {
        Command(ChildCommandInfo),
    }

    impl ChildCommand {
        pub fn get_container<'x>(&'x self) -> &String {
            match *self {
                Command(ref info) => &info.container,
            }
        }
    }
}

fn shell_command(ast: A::Ast) -> Vec<A::Ast> {
    match ast {
        A::Scalar(pos, _, style, value) => {
            return vec!(
                A::Scalar(pos.clone(), A::NonSpecific, A::Plain,
                          "/bin/sh".to_string()),
                A::Scalar(pos.clone(), A::NonSpecific, A::Plain,
                          "-c".to_string()),
                A::Scalar(pos.clone(), A::NonSpecific, style,
                          value),
                );
        }
        _ => unreachable!(),
    }
}

fn run_fields<'a>() -> Vec<(String, Box<V::Validator + 'a>)> {
    return vec!(
        ("pid1mode".to_string(), box V::Scalar {
            default: Some("wait".to_string()),
            .. Default::default()} as Box<V::Validator>),
        ("work_dir".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        ("container".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        ("accepts_arguments".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        ("environ".to_string(), box V::Mapping {
            key_element: box V::Scalar {
                .. Default::default()} as Box<V::Validator>,
            value_element: box V::Scalar {
                .. Default::default()} as Box<V::Validator>,
            .. Default::default()} as Box<V::Validator>),
        ("inherit_environ".to_string(), box V::Sequence {
            element: box V::Scalar {
                .. Default::default()} as Box<V::Validator>,
            .. Default::default()} as Box<V::Validator>),
        ("write_mode".to_string(), box V::Scalar {
            default: Some("read-only".to_string()),
            .. Default::default()} as Box<V::Validator>),
        ("run".to_string(), box V::Sequence {
            from_scalar: Some(shell_command),
            element: box V::Scalar {
                .. Default::default()} as Box<V::Validator>,
            .. Default::default()} as Box<V::Validator>),
        );
}

fn command_fields<'a>() -> Vec<(String, Box<V::Validator + 'a>)> {
    return vec!(
        ("description".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        ("banner".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        ("banner_delay".to_string(), box V::Numeric {
            min: Some(0),
            default: Some(0i64),
            .. Default::default()} as Box<V::Validator>),
        ("epilog".to_string(), box V::Scalar {
            optional: true,
            .. Default::default()} as Box<V::Validator>),
        );
}

fn subcommand_validator<'a>() -> Box<V::Validator + 'a> {
    return box V::Enum { options: vec!(
        ("Command".to_string(), box V::Structure {
            members: run_fields(),
            .. Default::default()} as Box<V::Validator>),
    ), .. Default::default()} as Box<V::Validator>;
}

pub fn command_validator<'a>() -> Box<V::Validator + 'a> {
    let mut command_members = vec!();
    command_members.extend(command_fields().into_iter());
    command_members.extend(run_fields().into_iter());

    let mut supervise_members = vec!(
        ("mode".to_string(), box V::Scalar {
            default: Some("stop-on-failure".to_string()),
            .. Default::default()} as Box<V::Validator>),
        ("children".to_string(), box V::Mapping {
            key_element: box V::Scalar {
                ..Default::default()} as Box<V::Validator>,
            value_element: subcommand_validator(),
            .. Default::default()} as Box<V::Validator>),
        );
    supervise_members.extend(command_fields().into_iter());

    return box V::Enum { options: vec!(
        ("Command".to_string(), box V::Structure {
            members: command_members,
            .. Default::default()} as Box<V::Validator>),
        ("Supervise".to_string(), box V::Structure {
            members: supervise_members,
            .. Default::default()} as Box<V::Validator>),
    ), .. Default::default()} as Box<V::Validator>;
}
<|endoftext|>


<commit_before>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![allow(clippy::missing_docs_in_private_items)]

// FIXME: switch to something more ergonomic here, once available.
// (currently there is no way to opt into sysroot crates w/o `extern crate`)
#[allow(unused_extern_crates)]
extern crate rustc_driver;
#[allow(unused_extern_crates)]
extern crate rustc_plugin;
use self::rustc_driver::{driver::CompileController, Compilation};

use std::convert::TryInto;
use std::path::Path;
use std::process::{exit, Command};

fn show_version() {
    println!(env!("CARGO_PKG_VERSION"));
}

/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
fn arg_value<'a>(
    args: impl IntoIterator<Item = &'a String>,
    find_arg: &str,
    pred: impl Fn(&str) -> bool,
) -> Option<&'a str> {
    let mut args = args.into_iter().map(String::as_str);

    while let Some(arg) = args.next() {
        let arg: Vec<_> = arg.splitn(2, '=').collect();
        if arg.get(0) != Some(&find_arg) {
            continue;
        }

        let value = arg.get(1).cloned().or_else(|| args.next());
        if value.as_ref().map_or(false, |p| pred(p)) {
            return value;
        }
    }
    None
}

#[test]
fn test_arg_value() {
    let args: Vec<_> = ["--bar=bar", "--foobar", "123", "--foo"]
        .iter()
        .map(std::string::ToString::to_string)
        .collect();

    assert_eq!(arg_value(None, "--foobar", |_| true), None);
    assert_eq!(arg_value(&args, "--bar", |_| false), None);
    assert_eq!(arg_value(&args, "--bar", |_| true), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "bar"), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "123"), Some("123"));
    assert_eq!(arg_value(&args, "--foo", |_| true), None);
}

#[allow(clippy::too_many_lines)]
pub fn main() {
    rustc_driver::init_rustc_env_logger();
    exit(
        rustc_driver::run(move || {
            use std::env;

            if std::env::args().any(|a| a == "--version" || a == "-V") {
                show_version();
                exit(0);
            }

            let mut orig_args: Vec<String> = env::args().collect();

            // Get the sysroot, looking from most specific to this invocation to the least:
            // - command line
            // - runtime environment
            //    - SYSROOT
            //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
            // - sysroot from rustc in the path
            // - compile-time environment
            let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
            let have_sys_root_arg = sys_root_arg.is_some();
            let sys_root = sys_root_arg
                .map(std::string::ToString::to_string)
                .or_else(|| std::env::var("SYSROOT").ok())
                .or_else(|| {
                    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
                    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
                    home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain)))
                })
                .or_else(|| {
                    Command::new("rustc")
                        .arg("--print")
                        .arg("sysroot")
                        .output()
                        .ok()
                        .and_then(|out| String::from_utf8(out.stdout).ok())
                        .map(|s| s.trim().to_owned())
                })
                .or_else(|| option_env!("SYSROOT").map(String::from))
                .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

            // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
            // We're invoking the compiler programmatically, so we ignore this/
            if orig_args.len() <= 1 {
                std::process::exit(1);
            }
            if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) {
                // we still want to be able to invoke it normally though
                orig_args.remove(1);
            }
            // this conditional check for the --sysroot flag is there so users can call
            // `clippy_driver` directly
            // without having to pass --sysroot or anything
            let mut args: Vec<String> = if have_sys_root_arg {
                orig_args.clone()
            } else {
                orig_args
                    .clone()
                    .into_iter()
                    .chain(Some("--sysroot".to_owned()))
                    .chain(Some(sys_root))
                    .collect()
            };

            // this check ensures that dependencies are built but not linted and the final
            // crate is
            // linted but not built
            let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
                || arg_value(&orig_args, "--emit", |val| val.split(',').any(|e| e == "metadata")).is_some();

            if clippy_enabled {
                args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
                if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
                    args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| {
                        if s.is_empty() {
                            None
                        } else {
                            Some(s.to_string())
                        }
                    }));
                }
            }

            let mut controller = CompileController::basic();
            if clippy_enabled {
                controller.after_parse.callback = Box::new(move |state| {
                    let mut registry = rustc_plugin::registry::Registry::new(
                        state.session,
                        state
                            .krate
                            .as_ref()
                            .expect(
                                "at this compilation stage \
                                 the crate must be parsed",
                            )
                            .span,
                    );
                    registry.args_hidden = Some(Vec::new());

                    let conf = clippy_lints::read_conf(&registry);
                    clippy_lints::register_plugins(&mut registry, &conf);

                    let rustc_plugin::registry::Registry {
                        early_lint_passes,
                        late_lint_passes,
                        lint_groups,
                        llvm_passes,
                        attributes,
                        ..
                    } = registry;
                    let sess = &state.session;
                    let mut ls = sess.lint_store.borrow_mut();
                    for pass in early_lint_passes {
                        ls.register_early_pass(Some(sess), true, false, pass);
                    }
                    for pass in late_lint_passes {
                        ls.register_late_pass(Some(sess), true, pass);
                    }

                    for (name, (to, deprecated_name)) in lint_groups {
                        ls.register_group(Some(sess), true, name, deprecated_name, to);
                    }
                    clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf);
                    clippy_lints::register_renamed(&mut ls);

                    sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                    sess.plugin_attributes.borrow_mut().extend(attributes);
                });
            }
            controller.compilation_done.stop = Compilation::Stop;

            let args = args;
            rustc_driver::run_compiler(&args, Box::new(controller), None, None)
        })
        .try_into()
        .expect("exit code too large"),
    )
}
<commit_msg>Use the new rustc interface<commit_after>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![allow(clippy::missing_docs_in_private_items)]

// FIXME: switch to something more ergonomic here, once available.
// (currently there is no way to opt into sysroot crates w/o `extern crate`)
#[allow(unused_extern_crates)]
extern crate rustc_driver;
#[allow(unused_extern_crates)]
extern crate rustc_plugin;
#[allow(unused_extern_crates)]
extern crate rustc_interface;

use rustc_interface::interface;
use std::path::Path;
use std::process::{exit, Command};

fn show_version() {
    println!(env!("CARGO_PKG_VERSION"));
}

/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
fn arg_value<'a>(
    args: impl IntoIterator<Item = &'a String>,
    find_arg: &str,
    pred: impl Fn(&str) -> bool,
) -> Option<&'a str> {
    let mut args = args.into_iter().map(String::as_str);

    while let Some(arg) = args.next() {
        let arg: Vec<_> = arg.splitn(2, '=').collect();
        if arg.get(0) != Some(&find_arg) {
            continue;
        }

        let value = arg.get(1).cloned().or_else(|| args.next());
        if value.as_ref().map_or(false, |p| pred(p)) {
            return value;
        }
    }
    None
}

#[test]
fn test_arg_value() {
    let args: Vec<_> = ["--bar=bar", "--foobar", "123", "--foo"]
        .iter()
        .map(std::string::ToString::to_string)
        .collect();

    assert_eq!(arg_value(None, "--foobar", |_| true), None);
    assert_eq!(arg_value(&args, "--bar", |_| false), None);
    assert_eq!(arg_value(&args, "--bar", |_| true), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "bar"), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "123"), Some("123"));
    assert_eq!(arg_value(&args, "--foo", |_| true), None);
}

#[allow(clippy::too_many_lines)]

struct ClippyCallbacks;

impl rustc_driver::Callbacks for ClippyCallbacks {
    fn after_parsing(&mut self, compiler: &interface::Compiler) -> bool {
        let sess = compiler.session();
        let mut registry = rustc_plugin::registry::Registry::new(
            sess,
            compiler.parse().expect(
                "at this compilation stage \
                    the crate must be parsed",
            ).peek().span,
        );
        registry.args_hidden = Some(Vec::new());

        let conf = clippy_lints::read_conf(&registry);
        clippy_lints::register_plugins(&mut registry, &conf);

        let rustc_plugin::registry::Registry {
            early_lint_passes,
            late_lint_passes,
            lint_groups,
            llvm_passes,
            attributes,
            ..
        } = registry;
        let mut ls = sess.lint_store.borrow_mut();
        for pass in early_lint_passes {
            ls.register_early_pass(Some(sess), true, false, pass);
        }
        for pass in late_lint_passes {
            ls.register_late_pass(Some(sess), true, pass);
        }

        for (name, (to, deprecated_name)) in lint_groups {
            ls.register_group(Some(sess), true, name, deprecated_name, to);
        }
        clippy_lints::register_pre_expansion_lints(sess, &mut ls, &conf);
        clippy_lints::register_renamed(&mut ls);

        sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
        sess.plugin_attributes.borrow_mut().extend(attributes);

        // Continue execution
        true
    }
}

pub fn main() {
    rustc_driver::init_rustc_env_logger();
    exit(
        rustc_driver::report_ices_to_stderr_if_any(move || {
            use std::env;

            if std::env::args().any(|a| a == "--version" || a == "-V") {
                show_version();
                exit(0);
            }

            let mut orig_args: Vec<String> = env::args().collect();

            // Get the sysroot, looking from most specific to this invocation to the least:
            // - command line
            // - runtime environment
            //    - SYSROOT
            //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
            // - sysroot from rustc in the path
            // - compile-time environment
            let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
            let have_sys_root_arg = sys_root_arg.is_some();
            let sys_root = sys_root_arg
                .map(std::string::ToString::to_string)
                .or_else(|| std::env::var("SYSROOT").ok())
                .or_else(|| {
                    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
                    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
                    home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain)))
                })
                .or_else(|| {
                    Command::new("rustc")
                        .arg("--print")
                        .arg("sysroot")
                        .output()
                        .ok()
                        .and_then(|out| String::from_utf8(out.stdout).ok())
                        .map(|s| s.trim().to_owned())
                })
                .or_else(|| option_env!("SYSROOT").map(String::from))
                .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

            // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
            // We're invoking the compiler programmatically, so we ignore this/
            if orig_args.len() <= 1 {
                std::process::exit(1);
            }
            if Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref()) {
                // we still want to be able to invoke it normally though
                orig_args.remove(1);
            }
            // this conditional check for the --sysroot flag is there so users can call
            // `clippy_driver` directly
            // without having to pass --sysroot or anything
            let mut args: Vec<String> = if have_sys_root_arg {
                orig_args.clone()
            } else {
                orig_args
                    .clone()
                    .into_iter()
                    .chain(Some("--sysroot".to_owned()))
                    .chain(Some(sys_root))
                    .collect()
            };

            // this check ensures that dependencies are built but not linted and the final
            // crate is
            // linted but not built
            let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
                || arg_value(&orig_args, "--emit", |val| val.split(',').any(|e| e == "metadata")).is_some();

            if clippy_enabled {
                args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
                if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
                    args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| {
                        if s.is_empty() {
                            None
                        } else {
                            Some(s.to_string())
                        }
                    }));
                }
            }

            let mut clippy = ClippyCallbacks;
            let mut default = rustc_driver::DefaultCallbacks;
            let callbacks: &mut (dyn rustc_driver::Callbacks + Send) = if clippy_enabled {
                &mut clippy
            } else {
                &mut default
            };
            let args = args;
            rustc_driver::run_compiler(&args, callbacks, None, None)
        }).and_then(|result| result).is_err() as i32
    )
}
<|endoftext|>