<commit_before>use std::io::Read;
use std::net::{TcpStream, Shutdown};
use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver, TryRecvError};
use byteorder::{BigEndian, ReadBytesExt};
use ::{zrle, protocol, Rect, Colour, Error, Result};
use protocol::Message;

#[derive(Debug)]
pub enum AuthMethod {
    None,
    /* more to come */
    #[doc(hidden)]
    __Nonexhaustive,
}

#[derive(Debug)]
pub enum AuthChoice {
    None,
    /* more to come */
    #[doc(hidden)]
    __Nonexhaustive,
}

#[derive(Debug)]
pub enum Event {
    Disconnected(Option<Error>),
    Resize(u16, u16),
    SetColourMap { first_colour: u16, colours: Vec<Colour> },
    PutPixels(Rect, Vec<u8>),
    CopyPixels { src: Rect, dst: Rect },
    EndOfFrame,
    SetCursor { size: (u16, u16), hotspot: (u16, u16), pixels: Vec<u8>, mask_bits: Vec<u8> },
    Clipboard(String),
    Bell,
}

macro_rules! send_or_return {
    ($chan:expr, $data:expr) => ({
        match $chan.send($data) {
            Ok(()) => (),
            Err(_) => return Ok(false)
        }
    })
}

impl Event {
    fn pump_one(stream: &mut TcpStream, format: &Arc<Mutex<protocol::PixelFormat>>,
                zrle_decoder: &mut zrle::Decoder, tx_events: &mut Sender<Event>) -> Result<bool> {
        let packet =
            match protocol::S2C::read_from(stream) {
                Ok(packet) => packet,
                Err(Error::Disconnected) => {
                    send_or_return!(tx_events, Event::Disconnected(None));
                    return Ok(false)
                },
                Err(error) => return Err(error)
            };
        debug!("<- {:?}", packet);

        let format = *format.lock().unwrap();
        match packet {
            protocol::S2C::SetColourMapEntries { first_colour, colours } => {
                send_or_return!(tx_events, Event::SetColourMap {
                    first_colour: first_colour, colours: colours
                })
            },
            protocol::S2C::FramebufferUpdate { count } => {
                for _ in 0..count {
                    let rectangle = try!(protocol::Rectangle::read_from(stream));
                    debug!("<- {:?}", rectangle);

                    let dst = Rect {
                        left:   rectangle.x_position,
                        top:    rectangle.y_position,
                        width:  rectangle.width,
                        height: rectangle.height
                    };
                    match rectangle.encoding {
                        protocol::Encoding::Raw => {
                            let mut pixels = vec![0; (rectangle.width as usize) *
                                                     (rectangle.height as usize) *
                                                     (format.bits_per_pixel as usize / 8)];
                            try!(stream.read_exact(&mut pixels));
                            debug!("<- ...pixels");
                            send_or_return!(tx_events, Event::PutPixels(dst, pixels))
                        },
                        protocol::Encoding::CopyRect => {
                            let copy_rect = try!(protocol::CopyRect::read_from(stream));
                            let src = Rect {
                                left:   copy_rect.src_x_position,
                                top:    copy_rect.src_y_position,
                                width:  rectangle.width,
                                height: rectangle.height
                            };
                            send_or_return!(tx_events, Event::CopyPixels { src: src, dst: dst })
                        },
                        protocol::Encoding::Zrle => {
                            let length = try!(stream.read_u32::<BigEndian>());
                            let mut data = vec![0; length as usize];
                            try!(stream.read_exact(&mut data));
                            debug!("<- ...compressed pixels");
                            let result = try!(zrle_decoder.decode(format, dst, &data,
                                |tile, pixels| {
                                    send_or_return!(tx_events, Event::PutPixels(tile, pixels));
                                    Ok(true)
                                }));
                            if !result { return Ok(false) }
                        }
                        protocol::Encoding::Cursor => {
                            let mut pixels    = vec![0; (rectangle.width as usize) *
                                                        (rectangle.height as usize) *
                                                        (format.bits_per_pixel as usize / 8)];
                            try!(stream.read_exact(&mut pixels));
                            let mut mask_bits = vec![0; ((rectangle.width as usize + 7) / 8) *
                                                        (rectangle.height as usize)];
                            try!(stream.read_exact(&mut mask_bits));
                            send_or_return!(tx_events, Event::SetCursor {
                                size:      (rectangle.width, rectangle.height),
                                hotspot:   (rectangle.x_position, rectangle.y_position),
                                pixels:    pixels,
                                mask_bits: mask_bits
                            })
                        },
                        protocol::Encoding::DesktopSize => {
                            send_or_return!(tx_events,
                                Event::Resize(rectangle.width, rectangle.height))
                        }
                        _ => return Err(Error::Unexpected("encoding"))
                    };
                }

                send_or_return!(tx_events, Event::EndOfFrame);
            },
            protocol::S2C::Bell =>
                send_or_return!(tx_events, Event::Bell),
            protocol::S2C::CutText(text) =>
                send_or_return!(tx_events, Event::Clipboard(text))
        };
        Ok(true)
    }

    fn pump(mut stream: TcpStream, format: Arc<Mutex<protocol::PixelFormat>>) -> Receiver<Event> {
        let (mut tx_events, rx_events) = channel();
        thread::spawn(move || {
            let mut zrle_decoder = zrle::Decoder::new();
            loop {
                match Event::pump_one(&mut stream, &format, &mut zrle_decoder, &mut tx_events) {
                    Ok(true) => (),
                    Ok(false) => break,
                    Err(error) => {
                        let _ = tx_events.send(Event::Disconnected(Some(error)));
                        break
                    }
                }
            }
        });
        rx_events
    }
}

pub struct Client {
    stream:  TcpStream,
    events:  Receiver<Event>,
    name:    String,
    size:    (u16, u16),
    format:  Arc<Mutex<protocol::PixelFormat>>
}

impl Client {
    pub fn from_tcp_stream<Auth>(mut stream: TcpStream, shared: bool,
                                 auth: Auth) -> Result<Client>
            where Auth: FnOnce(&[AuthMethod]) -> Option<AuthChoice> {
        let version = try!(protocol::Version::read_from(&mut stream));
        debug!("<- Version::{:?}", version);
        debug!("-> Version::{:?}", version);
        try!(protocol::Version::write_to(&version, &mut stream));

        let security_types = match version {
            protocol::Version::Rfb33 => {
                let security_type = try!(protocol::SecurityType::read_from(&mut stream));
                debug!("<- SecurityType::{:?}", security_type);
                if security_type == protocol::SecurityType::Invalid {
                    vec![]
                } else {
                    vec![security_type]
                }
            },
            _ => {
                let security_types = try!(protocol::SecurityTypes::read_from(&mut stream));
                debug!("<- {:?}", security_types);
                security_types.0
            }
        };

        if security_types.len() == 0 {
            let reason = try!(String::read_from(&mut stream));
            debug!("<- {:?}", reason);
            return Err(Error::Server(reason))
        }

        let mut auth_methods = Vec::new();
        for security_type in security_types {
            match security_type {
                protocol::SecurityType::None =>
                    auth_methods.push(AuthMethod::None),
                _ => ()
            }
        }

        let auth_choice = try!(auth(&auth_methods).ok_or(Error::AuthenticationUnavailable));

        match version {
            protocol::Version::Rfb33 => (),
            _ => {
                let used_security_type = match auth_choice {
                    AuthChoice::None => protocol::SecurityType::None,
                    AuthChoice::__Nonexhaustive => unreachable!()
                };
                debug!("-> SecurityType::{:?}", used_security_type);
                try!(protocol::SecurityType::write_to(&used_security_type, &mut stream));
            }
        }

        let mut skip_security_result = false;
        match &(auth_choice, version) {
            &(AuthChoice::None, protocol::Version::Rfb33) |
            &(AuthChoice::None, protocol::Version::Rfb37) => skip_security_result = true,
            _ => ()
        }

        if !skip_security_result {
            match try!(protocol::SecurityResult::read_from(&mut stream)) {
                protocol::SecurityResult::Succeeded => (),
                protocol::SecurityResult::Failed => {
                    match version {
                        protocol::Version::Rfb33 |
                        protocol::Version::Rfb37 =>
                            return Err(Error::AuthenticationFailure(String::from(""))),
                        protocol::Version::Rfb38 => {
                            let reason = try!(String::read_from(&mut stream));
                            debug!("<- {:?}", reason);
                            return Err(Error::AuthenticationFailure(reason))
                        }
                    }
                }
            }
        }

        let client_init = protocol::ClientInit { shared: shared };
        debug!("-> {:?}", client_init);
        try!(protocol::ClientInit::write_to(&client_init, &mut stream));

        let server_init = try!(protocol::ServerInit::read_from(&mut stream));
        debug!("<- {:?}", server_init);

        let format = Arc::new(Mutex::new(server_init.pixel_format));
        let events = Event::pump(stream.try_clone().unwrap(), format.clone());

        Ok(Client {
            stream:  stream,
            events:  events,
            name:    server_init.name,
            size:    (server_init.framebuffer_width, server_init.framebuffer_height),
            format:  format
        })
    }

    pub fn name(&self) -> &str { &self.name }
    pub fn size(&self) -> (u16, u16) { self.size }
    pub fn format(&self) -> protocol::PixelFormat { *self.format.lock().unwrap() }

    pub fn set_encodings(&mut self, encodings: &[protocol::Encoding]) -> Result<()> {
        let set_encodings = protocol::C2S::SetEncodings(Vec::from(encodings));
        debug!("-> {:?}", set_encodings);
        try!(protocol::C2S::write_to(&set_encodings, &mut self.stream));
        Ok(())
    }

    pub fn request_update(&mut self, rect: Rect, incremental: bool) -> Result<()> {
        let update_req = protocol::C2S::FramebufferUpdateRequest {
            incremental: incremental,
            x_position:  rect.left,
            y_position:  rect.top,
            width:       rect.width,
            height:      rect.height
        };
        trace!("-> {:?}", update_req);
        try!(protocol::C2S::write_to(&update_req, &mut self.stream));
        Ok(())
    }

    pub fn send_key_event(&mut self, down: bool, key: u32) -> Result<()> {
        let key_event = protocol::C2S::KeyEvent {
            down: down,
            key:  key
        };
        debug!("-> {:?}", key_event);
        try!(protocol::C2S::write_to(&key_event, &mut self.stream));
        Ok(())
    }

    pub fn send_pointer_event(&mut self, buttons: u8, x: u16, y: u16) -> Result<()> {
        let pointer_event = protocol::C2S::PointerEvent {
            button_mask: buttons,
            x_position:  x,
            y_position:  y
        };
        debug!("-> {:?}", pointer_event);
        try!(protocol::C2S::write_to(&pointer_event, &mut self.stream));
        Ok(())
    }

    pub fn update_clipboard(&mut self, text: &str) -> Result<()> {
        let cut_text = protocol::C2S::CutText(String::from(text));
        debug!("-> {:?}", cut_text);
        try!(protocol::C2S::write_to(&cut_text, &mut self.stream));
        Ok(())
    }

    // Note that due to inherent weaknesses of the VNC protocol, this
    // function is prone to race conditions that break the connection framing.
    // The ZRLE encoding is self-delimiting and if both the client and server
    // support and use it, there can be no race condition, but we currently don't.
    pub fn set_format(&mut self, format: protocol::PixelFormat) -> Result<()> {
        // Request (and discard) one full update to try and ensure that there
        // are no FramebufferUpdate's in the buffers somewhere.
        // This is not fully robust though (and cannot possibly be).
        let _ = self.poll_iter().count(); // drain it
        let framebuffer_rect = Rect { left: 0, top: 0, width: self.size.0, height: self.size.1 };
        try!(self.request_update(framebuffer_rect, false));
        'outer: loop {
            for event in self.poll_iter() {
                match event {
                    Event::PutPixels(rect, _) if rect == framebuffer_rect => break 'outer,
                    _ => ()
                }
            }
        }

        // Since VNC is fully client-driven, by this point the event thread is stuck
        // waiting for the next message and the server is not sending us anything,
        // so it's safe to switch to the new pixel format.
        let set_pixel_format = protocol::C2S::SetPixelFormat(format);
        debug!("-> {:?}", set_pixel_format);
        try!(protocol::C2S::write_to(&set_pixel_format, &mut self.stream));
        *self.format.lock().unwrap() = format;

        Ok(())
    }

    #[doc(hidden)]
    pub fn poke_qemu(&mut self) -> Result<()> {
        let set_pixel_format = protocol::C2S::SetPixelFormat(*self.format.lock().unwrap());
        debug!("-> {:?}", set_pixel_format);
        try!(protocol::C2S::write_to(&set_pixel_format, &mut self.stream));
        Ok(())
    }

    pub fn poll_event(&mut self) -> Option<Event> {
        match self.events.try_recv() {
            Err(TryRecvError::Empty) |
            Err(TryRecvError::Disconnected) => None,
            Ok(Event::Resize(width, height)) => {
                self.size = (width, height);
                Some(Event::Resize(width, height))
            }
            Ok(event) => Some(event)
        }
    }

    pub fn poll_iter(&mut self) -> EventPollIterator {
        EventPollIterator { client: self }
    }

    pub fn disconnect(self) -> Result<()> {
        try!(self.stream.shutdown(Shutdown::Both));
        Ok(())
    }
}

pub struct EventPollIterator<'a> {
    client: &'a mut Client
}

impl<'a> Iterator for EventPollIterator<'a> {
    type Item = Event;

    fn next(&mut self) -> Option<Self::Item> { self.client.poll_event() }
}
<commit_msg>Refactor client::Event::pump.<commit_after>use std::io::Read;
use std::net::{TcpStream, Shutdown};
use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver, TryRecvError};
use byteorder::{BigEndian, ReadBytesExt};
use ::{zrle, protocol, Rect, Colour, Error, Result};
use protocol::Message;

#[derive(Debug)]
pub enum AuthMethod {
    None,
    /* more to come */
    #[doc(hidden)]
    __Nonexhaustive,
}

#[derive(Debug)]
pub enum AuthChoice {
    None,
    /* more to come */
    #[doc(hidden)]
    __Nonexhaustive,
}

#[derive(Debug)]
pub enum Event {
    Disconnected(Option<Error>),
    Resize(u16, u16),
    SetColourMap { first_colour: u16, colours: Vec<Colour> },
    PutPixels(Rect, Vec<u8>),
    CopyPixels { src: Rect, dst: Rect },
    EndOfFrame,
    SetCursor { size: (u16, u16), hotspot: (u16, u16), pixels: Vec<u8>, mask_bits: Vec<u8> },
    Clipboard(String),
    Bell,
}

impl Event {
    fn pump(mut stream: TcpStream, format: Arc<Mutex<protocol::PixelFormat>>,
            tx_events: &mut Sender<Event>) -> Result<()> {
        macro_rules! send {
            ($chan:expr, $data:expr) => ({
                match $chan.send($data) {
                    Ok(()) => (),
                    Err(_) => break
                }
            })
        }

        let mut zrle_decoder = zrle::Decoder::new();
        loop {
            let packet =
                match protocol::S2C::read_from(&mut stream) {
                    Ok(packet) => packet,
                    Err(Error::Disconnected) => {
                        send!(tx_events, Event::Disconnected(None));
                        break
                    },
                    Err(error) => return Err(error)
                };
            debug!("<- {:?}", packet);

            let format = *format.lock().unwrap();
            match packet {
                protocol::S2C::SetColourMapEntries { first_colour, colours } => {
                    send!(tx_events, Event::SetColourMap {
                        first_colour: first_colour, colours: colours
                    })
                },
                protocol::S2C::FramebufferUpdate { count } => {
                    for _ in 0..count {
                        let rectangle = try!(protocol::Rectangle::read_from(&mut stream));
                        debug!("<- {:?}", rectangle);

                        let dst = Rect {
                            left:   rectangle.x_position,
                            top:    rectangle.y_position,
                            width:  rectangle.width,
                            height: rectangle.height
                        };
                        match rectangle.encoding {
                            protocol::Encoding::Raw => {
                                let mut pixels = vec![0; (rectangle.width as usize) *
                                                         (rectangle.height as usize) *
                                                         (format.bits_per_pixel as usize / 8)];
                                try!(stream.read_exact(&mut pixels));
                                debug!("<- ...pixels");
                                send!(tx_events, Event::PutPixels(dst, pixels))
                            },
                            protocol::Encoding::CopyRect => {
                                let copy_rect = try!(protocol::CopyRect::read_from(&mut stream));
                                let src = Rect {
                                    left:   copy_rect.src_x_position,
                                    top:    copy_rect.src_y_position,
                                    width:  rectangle.width,
                                    height: rectangle.height
                                };
                                send!(tx_events, Event::CopyPixels { src: src, dst: dst })
                            },
                            protocol::Encoding::Zrle => {
                                let length = try!(stream.read_u32::<BigEndian>());
                                let mut data = vec![0; length as usize];
                                try!(stream.read_exact(&mut data));
                                debug!("<- ...compressed pixels");
                                let result = try!(zrle_decoder.decode(format, dst, &data,
                                    |tile, pixels| {
                                        Ok(tx_events.send(Event::PutPixels(tile, pixels)).is_ok())
                                    }));
                                if !result { break }
                            }
                            protocol::Encoding::Cursor => {
                                let mut pixels    = vec![0; (rectangle.width as usize) *
                                                            (rectangle.height as usize) *
                                                            (format.bits_per_pixel as usize / 8)];
                                try!(stream.read_exact(&mut pixels));
                                let mut mask_bits = vec![0; ((rectangle.width as usize + 7) / 8) *
                                                            (rectangle.height as usize)];
                                try!(stream.read_exact(&mut mask_bits));
                                send!(tx_events, Event::SetCursor {
                                    size:      (rectangle.width, rectangle.height),
                                    hotspot:   (rectangle.x_position, rectangle.y_position),
                                    pixels:    pixels,
                                    mask_bits: mask_bits
                                })
                            },
                            protocol::Encoding::DesktopSize => {
                                send!(tx_events,
                                    Event::Resize(rectangle.width, rectangle.height))
                            }
                            _ => return Err(Error::Unexpected("encoding"))
                        };
                    }

                    send!(tx_events, Event::EndOfFrame);
                },
                protocol::S2C::Bell =>
                    send!(tx_events, Event::Bell),
                protocol::S2C::CutText(text) =>
                    send!(tx_events, Event::Clipboard(text))
            }
        }

        Ok(())
    }
}

pub struct Client {
    stream:  TcpStream,
    events:  Receiver<Event>,
    name:    String,
    size:    (u16, u16),
    format:  Arc<Mutex<protocol::PixelFormat>>
}

impl Client {
    pub fn from_tcp_stream<Auth>(mut stream: TcpStream, shared: bool,
                                 auth: Auth) -> Result<Client>
            where Auth: FnOnce(&[AuthMethod]) -> Option<AuthChoice> {
        let version = try!(protocol::Version::read_from(&mut stream));
        debug!("<- Version::{:?}", version);
        debug!("-> Version::{:?}", version);
        try!(protocol::Version::write_to(&version, &mut stream));

        let security_types = match version {
            protocol::Version::Rfb33 => {
                let security_type = try!(protocol::SecurityType::read_from(&mut stream));
                debug!("<- SecurityType::{:?}", security_type);
                if security_type == protocol::SecurityType::Invalid {
                    vec![]
                } else {
                    vec![security_type]
                }
            },
            _ => {
                let security_types = try!(protocol::SecurityTypes::read_from(&mut stream));
                debug!("<- {:?}", security_types);
                security_types.0
            }
        };

        if security_types.len() == 0 {
            let reason = try!(String::read_from(&mut stream));
            debug!("<- {:?}", reason);
            return Err(Error::Server(reason))
        }

        let mut auth_methods = Vec::new();
        for security_type in security_types {
            match security_type {
                protocol::SecurityType::None =>
                    auth_methods.push(AuthMethod::None),
                _ => ()
            }
        }

        let auth_choice = try!(auth(&auth_methods).ok_or(Error::AuthenticationUnavailable));

        match version {
            protocol::Version::Rfb33 => (),
            _ => {
                let used_security_type = match auth_choice {
                    AuthChoice::None => protocol::SecurityType::None,
                    AuthChoice::__Nonexhaustive => unreachable!()
                };
                debug!("-> SecurityType::{:?}", used_security_type);
                try!(protocol::SecurityType::write_to(&used_security_type, &mut stream));
            }
        }

        let mut skip_security_result = false;
        match &(auth_choice, version) {
            &(AuthChoice::None, protocol::Version::Rfb33) |
            &(AuthChoice::None, protocol::Version::Rfb37) => skip_security_result = true,
            _ => ()
        }

        if !skip_security_result {
            match try!(protocol::SecurityResult::read_from(&mut stream)) {
                protocol::SecurityResult::Succeeded => (),
                protocol::SecurityResult::Failed => {
                    match version {
                        protocol::Version::Rfb33 |
                        protocol::Version::Rfb37 =>
                            return Err(Error::AuthenticationFailure(String::from(""))),
                        protocol::Version::Rfb38 => {
                            let reason = try!(String::read_from(&mut stream));
                            debug!("<- {:?}", reason);
                            return Err(Error::AuthenticationFailure(reason))
                        }
                    }
                }
            }
        }

        let client_init = protocol::ClientInit { shared: shared };
        debug!("-> {:?}", client_init);
        try!(protocol::ClientInit::write_to(&client_init, &mut stream));

        let server_init = try!(protocol::ServerInit::read_from(&mut stream));
        debug!("<- {:?}", server_init);

        let format = Arc::new(Mutex::new(server_init.pixel_format));

        let (tx_events, rx_events) = channel();
        {
            let stream = stream.try_clone().unwrap();
            let format = format.clone();
            thread::spawn(move || {
                let mut tx_events = tx_events;
                let error = Event::pump(stream, format, &mut tx_events).err();
                let _ = tx_events.send(Event::Disconnected(error));
            });
        }

        Ok(Client {
            stream:  stream,
            events:  rx_events,
            name:    server_init.name,
            size:    (server_init.framebuffer_width, server_init.framebuffer_height),
            format:  format
        })
    }

    pub fn name(&self) -> &str { &self.name }
    pub fn size(&self) -> (u16, u16) { self.size }
    pub fn format(&self) -> protocol::PixelFormat { *self.format.lock().unwrap() }

    pub fn set_encodings(&mut self, encodings: &[protocol::Encoding]) -> Result<()> {
        let set_encodings = protocol::C2S::SetEncodings(Vec::from(encodings));
        debug!("-> {:?}", set_encodings);
        try!(protocol::C2S::write_to(&set_encodings, &mut self.stream));
        Ok(())
    }

    pub fn request_update(&mut self, rect: Rect, incremental: bool) -> Result<()> {
        let update_req = protocol::C2S::FramebufferUpdateRequest {
            incremental: incremental,
            x_position:  rect.left,
            y_position:  rect.top,
            width:       rect.width,
            height:      rect.height
        };
        trace!("-> {:?}", update_req);
        try!(protocol::C2S::write_to(&update_req, &mut self.stream));
        Ok(())
    }

    pub fn send_key_event(&mut self, down: bool, key: u32) -> Result<()> {
        let key_event = protocol::C2S::KeyEvent {
            down: down,
            key:  key
        };
        debug!("-> {:?}", key_event);
        try!(protocol::C2S::write_to(&key_event, &mut self.stream));
        Ok(())
    }

    pub fn send_pointer_event(&mut self, buttons: u8, x: u16, y: u16) -> Result<()> {
        let pointer_event = protocol::C2S::PointerEvent {
            button_mask: buttons,
            x_position:  x,
            y_position:  y
        };
        debug!("-> {:?}", pointer_event);
        try!(protocol::C2S::write_to(&pointer_event, &mut self.stream));
        Ok(())
    }

    pub fn update_clipboard(&mut self, text: &str) -> Result<()> {
        let cut_text = protocol::C2S::CutText(String::from(text));
        debug!("-> {:?}", cut_text);
        try!(protocol::C2S::write_to(&cut_text, &mut self.stream));
        Ok(())
    }

    // Note that due to inherent weaknesses of the VNC protocol, this
    // function is prone to race conditions that break the connection framing.
    // The ZRLE encoding is self-delimiting and if both the client and server
    // support and use it, there can be no race condition, but we currently don't.
    pub fn set_format(&mut self, format: protocol::PixelFormat) -> Result<()> {
        // Request (and discard) one full update to try and ensure that there
        // are no FramebufferUpdate's in the buffers somewhere.
        // This is not fully robust though (and cannot possibly be).
        let _ = self.poll_iter().count(); // drain it
        let framebuffer_rect = Rect { left: 0, top: 0, width: self.size.0, height: self.size.1 };
        try!(self.request_update(framebuffer_rect, false));
        'outer: loop {
            for event in self.poll_iter() {
                match event {
                    Event::PutPixels(rect, _) if rect == framebuffer_rect => break 'outer,
                    _ => ()
                }
            }
        }

        // Since VNC is fully client-driven, by this point the event thread is stuck
        // waiting for the next message and the server is not sending us anything,
        // so it's safe to switch to the new pixel format.
        let set_pixel_format = protocol::C2S::SetPixelFormat(format);
        debug!("-> {:?}", set_pixel_format);
        try!(protocol::C2S::write_to(&set_pixel_format, &mut self.stream));
        *self.format.lock().unwrap() = format;

        Ok(())
    }

    #[doc(hidden)]
    pub fn poke_qemu(&mut self) -> Result<()> {
        let set_pixel_format = protocol::C2S::SetPixelFormat(*self.format.lock().unwrap());
        debug!("-> {:?}", set_pixel_format);
        try!(protocol::C2S::write_to(&set_pixel_format, &mut self.stream));
        Ok(())
    }

    pub fn poll_event(&mut self) -> Option<Event> {
        match self.events.try_recv() {
            Err(TryRecvError::Empty) |
            Err(TryRecvError::Disconnected) => None,
            Ok(Event::Resize(width, height)) => {
                self.size = (width, height);
                Some(Event::Resize(width, height))
            }
            Ok(event) => Some(event)
        }
    }

    pub fn poll_iter(&mut self) -> EventPollIterator {
        EventPollIterator { client: self }
    }

    pub fn disconnect(self) -> Result<()> {
        try!(self.stream.shutdown(Shutdown::Both));
        Ok(())
    }
}

pub struct EventPollIterator<'a> {
    client: &'a mut Client
}

impl<'a> Iterator for EventPollIterator<'a> {
    type Item = Event;

    fn next(&mut self) -> Option<Self::Item> { self.client.poll_event() }
}
<|endoftext|>


<commit_before>#![recursion_limit = "128"]

extern crate proc_macro;
extern crate proc_macro2;
extern crate syn;
#[macro_use]
extern crate quote;

mod format;
mod attr;

use proc_macro::TokenStream;

#[proc_macro_derive(Protocol, attributes(protocol))]
pub fn protocol(input: TokenStream) -> TokenStream {
    // Parse the string representation
    let ast: syn::DeriveInput = syn::parse(input).unwrap();

    // Build the impl
    let gen = impl_parcel(&ast);

    // Return the generated impl
    gen.to_string().parse().expect("Could not parse generated parcel impl")
}

// The `Parcel` trait is used for data that can be sent/received.
fn impl_parcel(ast: &syn::DeriveInput) -> proc_macro2::TokenStream {
    match ast.data {
        syn::Data::Struct(ref s) => impl_parcel_for_struct(ast, s),
        syn::Data::Enum(ref e) => impl_parcel_for_enum(ast, e),
        syn::Data::Union(..) => unimplemented!(),
    }
}

/// Builds generics for a new impl.
///
/// Returns `(generics, where_predicates)`
fn build_generics(ast: &syn::DeriveInput) -> (Vec<proc_macro2::TokenStream>, Vec<proc_macro2::TokenStream>) {
    let mut where_predicates = Vec::new();
    let generics: Vec<_> = ast.generics.params.iter().enumerate().map(|(i, p)| {
        match p {
            syn::GenericParam::Type(t) => {
                let ident = &t.ident;
                where_predicates.push(quote!(#ident : ::protocol::Parcel));
                quote!(#ident)
            },
            syn::GenericParam::Lifetime(l) => {
                let letter = ('a' as u8 + i as u8) as char;
                quote!(#letter)
            },
            syn::GenericParam::Const(..) => panic!("const generics are unsupported"),
        }
    }).collect();

    (generics, where_predicates)
}

fn impl_parcel_for_struct(ast: &syn::DeriveInput,
                          strukt: &syn::DataStruct) -> proc_macro2::TokenStream {
    let strukt_name = &ast.ident;
    let anon_const_name = syn::Ident::new(&format!("__IMPL_PARCEL_FOR_{}", strukt_name.to_owned()), proc_macro2::Span::call_site());

    let (generics, where_predicates) = build_generics(ast);
    let (generics, where_predicates) = (&generics, where_predicates);

    match strukt.fields {
        syn::Fields::Named(ref fields_named) => {
            let field_names: Vec<_> = fields_named.named.iter().map(|field| {
                &field.ident
            }).collect();
            let field_names = &field_names[..];

            quote! {
                #[allow(non_upper_case_globals)]
                const #anon_const_name: () = {
                    extern crate protocol;
                    use std::io;

                    impl < #(#generics),* > protocol::Parcel for #strukt_name < #(#generics),* >
                        where #(#where_predicates),* {
                        #[allow(unused_variables)]
                        fn read(read: &mut io::Read)
                            -> Result<Self, protocol::Error> {
                            Ok(#strukt_name {
                                #(
                                    #field_names: protocol::Parcel::read(read)?
                                ),*
                            })
                        }

                        #[allow(unused_variables)]
                        fn write(&self, write: &mut io::Write)
                            -> Result<(), protocol::Error> {
                            #( protocol::Parcel::write(&self. #field_names, write )?; )*
                            Ok(())
                        }
                    }
                };
            }
        },
        syn::Fields::Unnamed(ref fields_unnamed) => {
            let field_numbers: Vec<_> = (0..fields_unnamed.unnamed.len()).into_iter().map(syn::Index::from).collect();
            let field_numbers = &field_numbers[..];

            let field_expressions = field_numbers.iter().map(|_| {
                quote!{ protocol::Parcel::read(read)? }
            });

            quote! {
                #[allow(non_upper_case_globals)]
                const #anon_const_name: () = {
                    extern crate protocol;
                    use std::io;

                    impl < #(#generics),* > protocol::Parcel for #strukt_name < #(#generics),* >
                        where #(#where_predicates),* {
                        #[allow(unused_variables)]
                        fn read(read: &mut io::Read)
                            -> Result<Self, protocol::Error> {
                            Ok(#strukt_name(
                                #(#field_expressions),*
                            ))
                        }

                        #[allow(unused_variables)]
                        fn write(&self, write: &mut io::Write)
                            -> Result<(), protocol::Error> {
                            #( protocol::Parcel::write(&self. #field_numbers, write )?; )*
                            Ok(())
                        }
                    }
                };
            }
        },
        syn::Fields::Unit => {
            quote! {
                #[allow(non_upper_case_globals)]
                const #anon_const_name: () = {
                    extern crate protocol;
                    use std::io;

                    impl protocol::Parcel for #strukt_name {
                        fn read(_: &mut io::Read) -> Result<Self, protocol::Error> {
                            Ok(#strukt_name)
                        }

                        fn write(&self, _: &mut io::Write)
                            -> Result<(), protocol::Error> {
                            Ok(())
                        }
                    }
                };
            }
        },
    }
}

fn impl_parcel_for_enum(ast: &syn::DeriveInput,
                        e: &syn::DataEnum) -> proc_macro2::TokenStream {
    let enum_name = &ast.ident;
    let anon_const_name = syn::Ident::new(&format!("__IMPL_PARCEL_FOR_{}", ast.ident), proc_macro2::Span::call_site());

    let format = attr::discriminant_format::<format::Enum>(&ast.attrs).unwrap_or(format::Enum::IntegerDiscriminator);

    let variant_writers = e.variants.iter().map(|variant| {
        let variant_name = &variant.ident;

        let discriminator = format.discriminator(e, variant);
        let write_discriminator = quote! { protocol::Parcel::write(&#discriminator, __io_writer)?; };

        match variant.fields {
            syn::Fields::Named(ref fields_named) => {
                let field_names = fields_named.named.iter().map(|f| &f.ident);
                let field_name_refs = fields_named.named.iter().map(|f| &f.ident).map(|n| quote! { ref #n });

                quote! {
                    #enum_name :: #variant_name { #( #field_name_refs ),* } => {
                        #write_discriminator

                        #( protocol::Parcel::write(#field_names, __io_writer)?; )*
                    }
                }
            },
            syn::Fields::Unnamed(ref fields_unnamed) => {
                let binding_names: Vec<_> = (0..fields_unnamed.unnamed.len()).into_iter()
                    .map(|i| syn::Ident::new(&format!("field_{}", i), proc_macro2::Span::call_site()))
                    .collect();

                let field_refs: Vec<_> = binding_names.iter().map(|i| quote! { ref #i }).collect();

                quote! {
                    #enum_name :: #variant_name ( #( #field_refs ),* ) => {
                        #write_discriminator
                        #( protocol::Parcel::write(#binding_names, __io_writer)?; )*
                    }
                }
            },
            syn::Fields::Unit => {
                quote!{
                    #enum_name :: #variant_name => {
                        #write_discriminator;
                    }
                }
            },
        }
    });

    let variant_readers = e.variants.iter().map(|ref variant| {
        let variant_name = &variant.ident;
        let discriminator = format.discriminator_variant_for_pattern_matching(e, variant);

        match variant.fields {
            syn::Fields::Named(ref fields_named) => {
                let field_names = fields_named.named.iter().map(|f| &f.ident);

                quote! {
                    #discriminator => Ok(#enum_name :: #variant_name {
                        #( #field_names : protocol::Parcel::read(__io_reader)? ),*
                    })
                }
            },
            syn::Fields::Unnamed(ref fields_unnamed) => {
                let binding_names: Vec<_> = (0..fields_unnamed.unnamed.len()).into_iter()
                    .map(|i| syn::Ident::new(&format!("field_{}", i), proc_macro2::Span::call_site()))
                    .collect();

                let field_readers = binding_names.iter().map(|_| {
                    quote! {
                        protocol::Parcel::read(__io_reader)?
                    }
                });

                quote! {
                    #discriminator => Ok(#enum_name :: #variant_name (
                        #(#field_readers),*
                    ))
                }
            },
            syn::Fields::Unit => {
                quote! {
                    #discriminator => Ok(#enum_name :: #variant_name)
                }
            },
        }
    });

    let (generics, where_predicates) = build_generics(ast);
    let (generics, where_predicates) = (&generics, where_predicates);

    let discriminator_type = format.discriminator_type();
    let discriminator_for_pattern_matching = format.discriminator_for_pattern_matching();
    quote! {
        #[allow(non_upper_case_globals)]
        const #anon_const_name: () = {
            extern crate protocol;
            use std::io;

            impl < #(#generics),* > protocol::Parcel for #enum_name < #(#generics),* >
                where #(#where_predicates),* {
                #[allow(unused_variables)]
                fn read(__io_reader: &mut io::Read) -> Result<Self, protocol::Error> {
                    let discriminator: #discriminator_type = protocol::Parcel::read(__io_reader)?;
                    match #discriminator_for_pattern_matching {
                        #(#variant_readers,)*
                        _ => panic!("unknown discriminator"),
                    }
                }

                #[allow(unused_variables)]
                fn write(&self, __io_writer: &mut io::Write)
                    -> Result<(), protocol::Error> {
                    match *self {
                        #(#variant_writers),*
                    }

                    Ok(())
                }
            }
        };
    }
}

<commit_msg>fix warning<commit_after>#![recursion_limit = "128"]

extern crate proc_macro;
extern crate proc_macro2;
extern crate syn;
#[macro_use]
extern crate quote;

mod format;
mod attr;

use proc_macro::TokenStream;

#[proc_macro_derive(Protocol, attributes(protocol))]
pub fn protocol(input: TokenStream) -> TokenStream {
    // Parse the string representation
    let ast: syn::DeriveInput = syn::parse(input).unwrap();

    // Build the impl
    let gen = impl_parcel(&ast);

    // Return the generated impl
    gen.to_string().parse().expect("Could not parse generated parcel impl")
}

// The `Parcel` trait is used for data that can be sent/received.
fn impl_parcel(ast: &syn::DeriveInput) -> proc_macro2::TokenStream {
    match ast.data {
        syn::Data::Struct(ref s) => impl_parcel_for_struct(ast, s),
        syn::Data::Enum(ref e) => impl_parcel_for_enum(ast, e),
        syn::Data::Union(..) => unimplemented!(),
    }
}

/// Builds generics for a new impl.
///
/// Returns `(generics, where_predicates)`
fn build_generics(ast: &syn::DeriveInput) -> (Vec<proc_macro2::TokenStream>, Vec<proc_macro2::TokenStream>) {
    let mut where_predicates = Vec::new();
    let generics: Vec<_> = ast.generics.params.iter().enumerate().map(|(i, p)| {
        match p {
            syn::GenericParam::Type(t) => {
                let ident = &t.ident;
                where_predicates.push(quote!(#ident : ::protocol::Parcel));
                quote!(#ident)
            },
            syn::GenericParam::Lifetime(..) => {
                let letter = ('a' as u8 + i as u8) as char;
                quote!(#letter)
            },
            syn::GenericParam::Const(..) => panic!("const generics are unsupported"),
        }
    }).collect();

    (generics, where_predicates)
}

fn impl_parcel_for_struct(ast: &syn::DeriveInput,
                          strukt: &syn::DataStruct) -> proc_macro2::TokenStream {
    let strukt_name = &ast.ident;
    let anon_const_name = syn::Ident::new(&format!("__IMPL_PARCEL_FOR_{}", strukt_name.to_owned()), proc_macro2::Span::call_site());

    let (generics, where_predicates) = build_generics(ast);
    let (generics, where_predicates) = (&generics, where_predicates);

    match strukt.fields {
        syn::Fields::Named(ref fields_named) => {
            let field_names: Vec<_> = fields_named.named.iter().map(|field| {
                &field.ident
            }).collect();
            let field_names = &field_names[..];

            quote! {
                #[allow(non_upper_case_globals)]
                const #anon_const_name: () = {
                    extern crate protocol;
                    use std::io;

                    impl < #(#generics),* > protocol::Parcel for #strukt_name < #(#generics),* >
                        where #(#where_predicates),* {
                        #[allow(unused_variables)]
                        fn read(read: &mut io::Read)
                            -> Result<Self, protocol::Error> {
                            Ok(#strukt_name {
                                #(
                                    #field_names: protocol::Parcel::read(read)?
                                ),*
                            })
                        }

                        #[allow(unused_variables)]
                        fn write(&self, write: &mut io::Write)
                            -> Result<(), protocol::Error> {
                            #( protocol::Parcel::write(&self. #field_names, write )?; )*
                            Ok(())
                        }
                    }
                };
            }
        },
        syn::Fields::Unnamed(ref fields_unnamed) => {
            let field_numbers: Vec<_> = (0..fields_unnamed.unnamed.len()).into_iter().map(syn::Index::from).collect();
            let field_numbers = &field_numbers[..];

            let field_expressions = field_numbers.iter().map(|_| {
                quote!{ protocol::Parcel::read(read)? }
            });

            quote! {
                #[allow(non_upper_case_globals)]
                const #anon_const_name: () = {
                    extern crate protocol;
                    use std::io;

                    impl < #(#generics),* > protocol::Parcel for #strukt_name < #(#generics),* >
                        where #(#where_predicates),* {
                        #[allow(unused_variables)]
                        fn read(read: &mut io::Read)
                            -> Result<Self, protocol::Error> {
                            Ok(#strukt_name(
                                #(#field_expressions),*
                            ))
                        }

                        #[allow(unused_variables)]
                        fn write(&self, write: &mut io::Write)
                            -> Result<(), protocol::Error> {
                            #( protocol::Parcel::write(&self. #field_numbers, write )?; )*
                            Ok(())
                        }
                    }
                };
            }
        },
        syn::Fields::Unit => {
            quote! {
                #[allow(non_upper_case_globals)]
                const #anon_const_name: () = {
                    extern crate protocol;
                    use std::io;

                    impl protocol::Parcel for #strukt_name {
                        fn read(_: &mut io::Read) -> Result<Self, protocol::Error> {
                            Ok(#strukt_name)
                        }

                        fn write(&self, _: &mut io::Write)
                            -> Result<(), protocol::Error> {
                            Ok(())
                        }
                    }
                };
            }
        },
    }
}

fn impl_parcel_for_enum(ast: &syn::DeriveInput,
                        e: &syn::DataEnum) -> proc_macro2::TokenStream {
    let enum_name = &ast.ident;
    let anon_const_name = syn::Ident::new(&format!("__IMPL_PARCEL_FOR_{}", ast.ident), proc_macro2::Span::call_site());

    let format = attr::discriminant_format::<format::Enum>(&ast.attrs).unwrap_or(format::Enum::IntegerDiscriminator);

    let variant_writers = e.variants.iter().map(|variant| {
        let variant_name = &variant.ident;

        let discriminator = format.discriminator(e, variant);
        let write_discriminator = quote! { protocol::Parcel::write(&#discriminator, __io_writer)?; };

        match variant.fields {
            syn::Fields::Named(ref fields_named) => {
                let field_names = fields_named.named.iter().map(|f| &f.ident);
                let field_name_refs = fields_named.named.iter().map(|f| &f.ident).map(|n| quote! { ref #n });

                quote! {
                    #enum_name :: #variant_name { #( #field_name_refs ),* } => {
                        #write_discriminator

                        #( protocol::Parcel::write(#field_names, __io_writer)?; )*
                    }
                }
            },
            syn::Fields::Unnamed(ref fields_unnamed) => {
                let binding_names: Vec<_> = (0..fields_unnamed.unnamed.len()).into_iter()
                    .map(|i| syn::Ident::new(&format!("field_{}", i), proc_macro2::Span::call_site()))
                    .collect();

                let field_refs: Vec<_> = binding_names.iter().map(|i| quote! { ref #i }).collect();

                quote! {
                    #enum_name :: #variant_name ( #( #field_refs ),* ) => {
                        #write_discriminator
                        #( protocol::Parcel::write(#binding_names, __io_writer)?; )*
                    }
                }
            },
            syn::Fields::Unit => {
                quote!{
                    #enum_name :: #variant_name => {
                        #write_discriminator;
                    }
                }
            },
        }
    });

    let variant_readers = e.variants.iter().map(|ref variant| {
        let variant_name = &variant.ident;
        let discriminator = format.discriminator_variant_for_pattern_matching(e, variant);

        match variant.fields {
            syn::Fields::Named(ref fields_named) => {
                let field_names = fields_named.named.iter().map(|f| &f.ident);

                quote! {
                    #discriminator => Ok(#enum_name :: #variant_name {
                        #( #field_names : protocol::Parcel::read(__io_reader)? ),*
                    })
                }
            },
            syn::Fields::Unnamed(ref fields_unnamed) => {
                let binding_names: Vec<_> = (0..fields_unnamed.unnamed.len()).into_iter()
                    .map(|i| syn::Ident::new(&format!("field_{}", i), proc_macro2::Span::call_site()))
                    .collect();

                let field_readers = binding_names.iter().map(|_| {
                    quote! {
                        protocol::Parcel::read(__io_reader)?
                    }
                });

                quote! {
                    #discriminator => Ok(#enum_name :: #variant_name (
                        #(#field_readers),*
                    ))
                }
            },
            syn::Fields::Unit => {
                quote! {
                    #discriminator => Ok(#enum_name :: #variant_name)
                }
            },
        }
    });

    let (generics, where_predicates) = build_generics(ast);
    let (generics, where_predicates) = (&generics, where_predicates);

    let discriminator_type = format.discriminator_type();
    let discriminator_for_pattern_matching = format.discriminator_for_pattern_matching();
    quote! {
        #[allow(non_upper_case_globals)]
        const #anon_const_name: () = {
            extern crate protocol;
            use std::io;

            impl < #(#generics),* > protocol::Parcel for #enum_name < #(#generics),* >
                where #(#where_predicates),* {
                #[allow(unused_variables)]
                fn read(__io_reader: &mut io::Read) -> Result<Self, protocol::Error> {
                    let discriminator: #discriminator_type = protocol::Parcel::read(__io_reader)?;
                    match #discriminator_for_pattern_matching {
                        #(#variant_readers,)*
                        _ => panic!("unknown discriminator"),
                    }
                }

                #[allow(unused_variables)]
                fn write(&self, __io_writer: &mut io::Write)
                    -> Result<(), protocol::Error> {
                    match *self {
                        #(#variant_writers),*
                    }

                    Ok(())
                }
            }
        };
    }
}

<|endoftext|>


<commit_before>//! Some common code used by both the event and reply modules.
use std::collections::HashMap;
use serde_json as json;
use reply;

/// Recursively build the tree of containers from the given json value.
pub fn build_tree(val: &json::Value) -> reply::Node {
    reply::Node {
        focus: match val.find("focus") {
            Some(xs) => xs.as_array()
                          .unwrap()
                          .iter()
                          .map(|x| x.as_i64().unwrap())
                          .collect(),
            None => vec![]
        },
        nodes: match val.find("nodes") {
            Some(nds) => nds.as_array()
                            .unwrap()
                            .iter()
                            .map(|n| build_tree(n))
                            .collect::<Vec<_>>(),
            None => vec![]
        },
        floating_nodes: match val.find("floating_nodes") {
            Some(nds) => nds.as_array()
                            .unwrap()
                            .iter()
                            .map(|n| build_tree(n))
                            .collect::<Vec<_>>(),
            None => vec![]
        },
        id: val.find("id").unwrap().as_i64().unwrap(),
        name: match val.find("name") {
            Some(n) => match n.as_string() {
                Some(s) => Some(s.to_owned()),
                None => None
            },
            None => None
        },
        nodetype: match val.find("type").unwrap().as_string().unwrap().as_ref() {
            "root" => reply::NodeType::Root,
            "output" => reply::NodeType::Output,
            "con" => reply::NodeType::Con,
            "floating_con" => reply::NodeType::FloatingCon,
            "workspace" => reply::NodeType::Workspace,
            "dockarea" => reply::NodeType::DockArea,
            other => {
                warn!(target: "i3ipc", "Unknown NodeType {}", other);
                reply::NodeType::Unknown
            }
        },
        border: match val.find("border").unwrap().as_string().unwrap().as_ref() {
            "normal" => reply::NodeBorder::Normal,
            "none" => reply::NodeBorder::None,
            "pixel" => reply::NodeBorder::Pixel,
            other => {
                warn!(target: "i3ipc", "Unknown NodeBorder {}", other);
                reply::NodeBorder::Unknown
            }
        },
        current_border_width: val.find("current_border_width").unwrap().as_i64().unwrap() as i32,
        layout: match val.find("layout").unwrap().as_string().unwrap().as_ref() {
            "splith" => reply::NodeLayout::SplitH,
            "splitv" => reply::NodeLayout::SplitV,
            "stacked" => reply::NodeLayout::Stacked,
            "tabbed" => reply::NodeLayout::Tabbed,
            "dockarea" => reply::NodeLayout::DockArea,
            "output" => reply::NodeLayout::Output,
            other => {
                warn!(target: "i3ipc", "Unknown NodeLayout {}", other);
                reply::NodeLayout::Unknown
            }
        },
        percent: match *val.find("percent").unwrap() {
            json::Value::F64(f) => Some(f),
            json::Value::Null => None,
            _ => unreachable!()
        },
        rect: build_rect(val.find("rect").unwrap()),
        window_rect: build_rect(val.find("window_rect").unwrap()),
        deco_rect: build_rect(val.find("deco_rect").unwrap()),
        geometry: build_rect(val.find("geometry").unwrap()),
        window: match val.find("window").unwrap().clone() {
            json::Value::I64(i) => Some(i as i32),
            json::Value::U64(u) => Some(u as i32),
            json::Value::Null => None,
            _ => unreachable!()
        },
        urgent: val.find("urgent").unwrap().as_boolean().unwrap(),
        focused: val.find("focused").unwrap().as_boolean().unwrap()
    }
}

pub fn build_rect(jrect: &json::Value) -> (i32, i32, i32, i32) {
    let x = jrect.find("x").unwrap().as_i64().unwrap() as i32;
    let y = jrect.find("y").unwrap().as_i64().unwrap() as i32;
    let width = jrect.find("width").unwrap().as_i64().unwrap() as i32;
    let height = jrect.find("height").unwrap().as_i64().unwrap() as i32;
    (x, y, width, height)
}

pub fn build_bar_config(j: &json::Value) -> reply::BarConfig {
    reply::BarConfig {
        id: j.find("id").unwrap().as_string().unwrap().to_owned(),
        mode: j.find("mode").unwrap().as_string().unwrap().to_owned(),
        position: j.find("position").unwrap().as_string().unwrap().to_owned(),
        status_command: j.find("status_command").unwrap().as_string().unwrap().to_owned(),
        font: j.find("font").unwrap().as_string().unwrap().to_owned(),
        workspace_buttons: j.find("workspace_buttons").unwrap().as_boolean().unwrap(),
        binding_mode_indicator: j.find("binding_mode_indicator").unwrap().as_boolean().unwrap(),
        verbose: j.find("verbose").unwrap().as_boolean().unwrap(),
        colors: {
            let colors = j.find("colors").unwrap().as_object().unwrap();
            let mut map = HashMap::new();
            for c in colors.keys() {
                let enum_key = match c.as_ref() {
                    "background" => reply::ColorableBarPart::Background,
                    "statusline" => reply::ColorableBarPart::Statusline,
                    "separator" => reply::ColorableBarPart::Separator,

                    #[cfg(feature = "i3-4-12")]
                    "focused_background" => reply::ColorableBarPart::FocusedBackground,

                    #[cfg(feature = "i3-4-12")]
                    "focused_statusline" => reply::ColorableBarPart::FocusedStatusline,

                    #[cfg(feature = "i3-4-12")]
                    "focused_separator" => reply::ColorableBarPart::FocusedSeparator,

                    "focused_workspace_text" => reply::ColorableBarPart::FocusedWorkspaceText,
                    "focused_workspace_bg" => reply::ColorableBarPart::FocusedWorkspaceBg,
                    "focused_workspace_border" => reply::ColorableBarPart::FocusedWorkspaceBorder,
                    "active_workspace_text" => reply::ColorableBarPart::ActiveWorkspaceText,
                    "active_workspace_bg" => reply::ColorableBarPart::ActiveWorkspaceBg,
                    "active_workspace_border" => reply::ColorableBarPart::ActiveWorkspaceBorder,
                    "inactive_workspace_text" => reply::ColorableBarPart::InactiveWorkspaceText,
                    "inactive_workspace_bg" => reply::ColorableBarPart::InactiveWorkspaceBg,
                    "inactive_workspace_border" => reply::ColorableBarPart::InactiveWorkspaceBorder,
                    "urgent_workspace_text" => reply::ColorableBarPart::UrgentWorkspaceText,
                    "urgent_workspace_bg" => reply::ColorableBarPart::UrgentWorkspaceBg,
                    "urgent_workspace_border" => reply::ColorableBarPart::UrgentWorkspaceBorder,
                    "binding_mode_text" => reply::ColorableBarPart::BindingModeText,
                    "binding_mode_bg" => reply::ColorableBarPart::BindingModeBg,
                    "binding_mode_border" => reply::ColorableBarPart::BindingModeBorder,
                    other => {
                        warn!(target: "i3ipc", "Unknown ColorableBarPart {}", other);
                        reply::ColorableBarPart::Unknown
                    }
                };
                let hex = colors.get(c).unwrap().as_string().unwrap().to_owned();
                map.insert(enum_key, hex);
            }
            map
        }
    }
}
<commit_msg>Remove unneeded type annotations<commit_after>//! Some common code used by both the event and reply modules.
use std::collections::HashMap;
use serde_json as json;
use reply;

/// Recursively build the tree of containers from the given json value.
pub fn build_tree(val: &json::Value) -> reply::Node {
    reply::Node {
        focus: match val.find("focus") {
            Some(xs) => xs.as_array()
                          .unwrap()
                          .iter()
                          .map(|x| x.as_i64().unwrap())
                          .collect(),
            None => vec![]
        },
        nodes: match val.find("nodes") {
            Some(nds) => nds.as_array()
                            .unwrap()
                            .iter()
                            .map(|n| build_tree(n))
                            .collect(),
            None => vec![]
        },
        floating_nodes: match val.find("floating_nodes") {
            Some(nds) => nds.as_array()
                            .unwrap()
                            .iter()
                            .map(|n| build_tree(n))
                            .collect(),
            None => vec![]
        },
        id: val.find("id").unwrap().as_i64().unwrap(),
        name: match val.find("name") {
            Some(n) => match n.as_string() {
                Some(s) => Some(s.to_owned()),
                None => None
            },
            None => None
        },
        nodetype: match val.find("type").unwrap().as_string().unwrap().as_ref() {
            "root" => reply::NodeType::Root,
            "output" => reply::NodeType::Output,
            "con" => reply::NodeType::Con,
            "floating_con" => reply::NodeType::FloatingCon,
            "workspace" => reply::NodeType::Workspace,
            "dockarea" => reply::NodeType::DockArea,
            other => {
                warn!(target: "i3ipc", "Unknown NodeType {}", other);
                reply::NodeType::Unknown
            }
        },
        border: match val.find("border").unwrap().as_string().unwrap().as_ref() {
            "normal" => reply::NodeBorder::Normal,
            "none" => reply::NodeBorder::None,
            "pixel" => reply::NodeBorder::Pixel,
            other => {
                warn!(target: "i3ipc", "Unknown NodeBorder {}", other);
                reply::NodeBorder::Unknown
            }
        },
        current_border_width: val.find("current_border_width").unwrap().as_i64().unwrap() as i32,
        layout: match val.find("layout").unwrap().as_string().unwrap().as_ref() {
            "splith" => reply::NodeLayout::SplitH,
            "splitv" => reply::NodeLayout::SplitV,
            "stacked" => reply::NodeLayout::Stacked,
            "tabbed" => reply::NodeLayout::Tabbed,
            "dockarea" => reply::NodeLayout::DockArea,
            "output" => reply::NodeLayout::Output,
            other => {
                warn!(target: "i3ipc", "Unknown NodeLayout {}", other);
                reply::NodeLayout::Unknown
            }
        },
        percent: match *val.find("percent").unwrap() {
            json::Value::F64(f) => Some(f),
            json::Value::Null => None,
            _ => unreachable!()
        },
        rect: build_rect(val.find("rect").unwrap()),
        window_rect: build_rect(val.find("window_rect").unwrap()),
        deco_rect: build_rect(val.find("deco_rect").unwrap()),
        geometry: build_rect(val.find("geometry").unwrap()),
        window: match val.find("window").unwrap().clone() {
            json::Value::I64(i) => Some(i as i32),
            json::Value::U64(u) => Some(u as i32),
            json::Value::Null => None,
            _ => unreachable!()
        },
        urgent: val.find("urgent").unwrap().as_boolean().unwrap(),
        focused: val.find("focused").unwrap().as_boolean().unwrap()
    }
}

pub fn build_rect(jrect: &json::Value) -> (i32, i32, i32, i32) {
    let x = jrect.find("x").unwrap().as_i64().unwrap() as i32;
    let y = jrect.find("y").unwrap().as_i64().unwrap() as i32;
    let width = jrect.find("width").unwrap().as_i64().unwrap() as i32;
    let height = jrect.find("height").unwrap().as_i64().unwrap() as i32;
    (x, y, width, height)
}

pub fn build_bar_config(j: &json::Value) -> reply::BarConfig {
    reply::BarConfig {
        id: j.find("id").unwrap().as_string().unwrap().to_owned(),
        mode: j.find("mode").unwrap().as_string().unwrap().to_owned(),
        position: j.find("position").unwrap().as_string().unwrap().to_owned(),
        status_command: j.find("status_command").unwrap().as_string().unwrap().to_owned(),
        font: j.find("font").unwrap().as_string().unwrap().to_owned(),
        workspace_buttons: j.find("workspace_buttons").unwrap().as_boolean().unwrap(),
        binding_mode_indicator: j.find("binding_mode_indicator").unwrap().as_boolean().unwrap(),
        verbose: j.find("verbose").unwrap().as_boolean().unwrap(),
        colors: {
            let colors = j.find("colors").unwrap().as_object().unwrap();
            let mut map = HashMap::new();
            for c in colors.keys() {
                let enum_key = match c.as_ref() {
                    "background" => reply::ColorableBarPart::Background,
                    "statusline" => reply::ColorableBarPart::Statusline,
                    "separator" => reply::ColorableBarPart::Separator,

                    #[cfg(feature = "i3-4-12")]
                    "focused_background" => reply::ColorableBarPart::FocusedBackground,

                    #[cfg(feature = "i3-4-12")]
                    "focused_statusline" => reply::ColorableBarPart::FocusedStatusline,

                    #[cfg(feature = "i3-4-12")]
                    "focused_separator" => reply::ColorableBarPart::FocusedSeparator,

                    "focused_workspace_text" => reply::ColorableBarPart::FocusedWorkspaceText,
                    "focused_workspace_bg" => reply::ColorableBarPart::FocusedWorkspaceBg,
                    "focused_workspace_border" => reply::ColorableBarPart::FocusedWorkspaceBorder,
                    "active_workspace_text" => reply::ColorableBarPart::ActiveWorkspaceText,
                    "active_workspace_bg" => reply::ColorableBarPart::ActiveWorkspaceBg,
                    "active_workspace_border" => reply::ColorableBarPart::ActiveWorkspaceBorder,
                    "inactive_workspace_text" => reply::ColorableBarPart::InactiveWorkspaceText,
                    "inactive_workspace_bg" => reply::ColorableBarPart::InactiveWorkspaceBg,
                    "inactive_workspace_border" => reply::ColorableBarPart::InactiveWorkspaceBorder,
                    "urgent_workspace_text" => reply::ColorableBarPart::UrgentWorkspaceText,
                    "urgent_workspace_bg" => reply::ColorableBarPart::UrgentWorkspaceBg,
                    "urgent_workspace_border" => reply::ColorableBarPart::UrgentWorkspaceBorder,
                    "binding_mode_text" => reply::ColorableBarPart::BindingModeText,
                    "binding_mode_bg" => reply::ColorableBarPart::BindingModeBg,
                    "binding_mode_border" => reply::ColorableBarPart::BindingModeBorder,
                    other => {
                        warn!(target: "i3ipc", "Unknown ColorableBarPart {}", other);
                        reply::ColorableBarPart::Unknown
                    }
                };
                let hex = colors.get(c).unwrap().as_string().unwrap().to_owned();
                map.insert(enum_key, hex);
            }
            map
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std;
use std::fs::File;
use std::io::Read;
use std::net;
use std::path::Path;
use std::result;
use std::str::FromStr;

use toml;

use error::{Error, Result};

pub trait ConfigFile: Sized {
    type Error: std::error::Error + From<Error>;

    fn from_file<T: AsRef<Path>>(filepath: T) -> result::Result<Self, Self::Error> {
        let mut file = match File::open(filepath.as_ref()) {
            Ok(f) => f,
            Err(e) => return Err(Self::Error::from(Error::ConfigFileIO(e))),
        };
        let mut raw = String::new();
        match file.read_to_string(&mut raw) {
            Ok(_) => (),
            Err(e) => return Err(Self::Error::from(Error::ConfigFileIO(e))),
        }
        match raw.parse() {
            Ok(toml) => Self::from_toml(toml),
            Err(e) => {
                let msg = format_errors(&e);
                Err(Self::Error::from(Error::ConfigFileSyntax(msg)))
            }
        }
    }

    fn from_toml(toml: toml::Value) -> result::Result<Self, Self::Error>;
}

pub trait ParseInto<T> {
    fn parse_into(&self, field: &'static str, out: &mut T) -> Result<bool>;
}

impl ParseInto<Vec<net::SocketAddrV4>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<net::SocketAddrV4>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(slice) = val.as_slice() {
                let mut buf = vec![];
                for entry in slice.iter() {
                    if let Some(v) = entry.as_str() {
                        match net::SocketAddrV4::from_str(v) {
                            Ok(addr) => buf.push(addr),
                            Err(_) => return Err(Error::ConfigInvalidSocketAddrV4(field)),
                        }
                    } else {
                        return Err(Error::ConfigInvalidSocketAddrV4(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                // error, expected array
                Ok(false)
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<net::SocketAddrV4> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut net::SocketAddrV4) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                match net::SocketAddrV4::from_str(v) {
                    Ok(addr) => {
                        *out = addr;
                        Ok(true)
                    }
                    Err(_) => Err(Error::ConfigInvalidSocketAddrV4(field)),
                }
            } else {
                Err(Error::ConfigInvalidSocketAddrV4(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<net::Ipv4Addr> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut net::Ipv4Addr) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                match net::Ipv4Addr::from_str(v) {
                    Ok(addr) => {
                        *out = addr;
                        Ok(true)
                    }
                    Err(_) => Err(Error::ConfigInvalidIpv4Addr(field)),
                }
            } else {
                Err(Error::ConfigInvalidIpv4Addr(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<String> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut String) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                *out = v.to_string();
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Option<String>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Option<String>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                *out = Some(v.to_string());
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            *out = None;
            Ok(true)
        }
    }
}

impl ParseInto<usize> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut usize) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as usize;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<u16> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut u16) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as u16;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u16>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u16>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u16);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u32>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u32>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u32);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

fn format_errors(errors: &Vec<toml::ParserError>) -> String {
    let mut msg = String::new();
    for err in errors {
        msg.push_str(&format!("\terror: {}\n", err.desc));
    }
    msg
}
<commit_msg>Move DataStore ownership from dispatcher/worker to server<commit_after>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std;
use std::fs::File;
use std::io::Read;
use std::net;
use std::path::Path;
use std::result;
use std::str::FromStr;

use toml;

use error::{Error, Result};

pub trait ConfigFile: Sized {
    type Error: std::error::Error + From<Error>;

    fn from_file<T: AsRef<Path>>(filepath: T) -> result::Result<Self, Self::Error> {
        let mut file = match File::open(filepath.as_ref()) {
            Ok(f) => f,
            Err(e) => return Err(Self::Error::from(Error::ConfigFileIO(e))),
        };
        let mut raw = String::new();
        match file.read_to_string(&mut raw) {
            Ok(_) => (),
            Err(e) => return Err(Self::Error::from(Error::ConfigFileIO(e))),
        }
        match raw.parse() {
            Ok(toml) => Self::from_toml(toml),
            Err(e) => {
                let msg = format_errors(&e);
                Err(Self::Error::from(Error::ConfigFileSyntax(msg)))
            }
        }
    }

    fn from_toml(toml: toml::Value) -> result::Result<Self, Self::Error>;
}

pub trait ParseInto<T> {
    fn parse_into(&self, field: &'static str, out: &mut T) -> Result<bool>;
}

impl ParseInto<Vec<net::SocketAddrV4>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<net::SocketAddrV4>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(slice) = val.as_slice() {
                let mut buf = vec![];
                for entry in slice.iter() {
                    if let Some(v) = entry.as_str() {
                        match net::SocketAddrV4::from_str(v) {
                            Ok(addr) => buf.push(addr),
                            Err(_) => return Err(Error::ConfigInvalidSocketAddrV4(field)),
                        }
                    } else {
                        return Err(Error::ConfigInvalidSocketAddrV4(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                // error, expected array
                Ok(false)
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<net::SocketAddrV4> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut net::SocketAddrV4) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                match net::SocketAddrV4::from_str(v) {
                    Ok(addr) => {
                        *out = addr;
                        Ok(true)
                    }
                    Err(_) => Err(Error::ConfigInvalidSocketAddrV4(field)),
                }
            } else {
                Err(Error::ConfigInvalidSocketAddrV4(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<net::Ipv4Addr> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut net::Ipv4Addr) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                match net::Ipv4Addr::from_str(v) {
                    Ok(addr) => {
                        *out = addr;
                        Ok(true)
                    }
                    Err(_) => Err(Error::ConfigInvalidIpv4Addr(field)),
                }
            } else {
                Err(Error::ConfigInvalidIpv4Addr(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<String> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut String) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                *out = v.to_string();
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Option<String>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Option<String>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_str() {
                *out = Some(v.to_string());
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            *out = None;
            Ok(true)
        }
    }
}

impl ParseInto<usize> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut usize) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as usize;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<u16> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut u16) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as u16;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<u32> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut u32) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as u32;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<u64> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut u64) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_integer() {
                *out = v as u64;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidString(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u16>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u16>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u16);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u32>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u32>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u32);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

impl ParseInto<Vec<u64>> for toml::Value {
    fn parse_into(&self, field: &'static str, out: &mut Vec<u64>) -> Result<bool> {
        if let Some(val) = self.lookup(field) {
            if let Some(v) = val.as_slice() {
                let mut buf = vec![];
                for int in v.iter() {
                    if let Some(i) = int.as_integer() {
                        buf.push(i as u64);
                    } else {
                        return Err(Error::ConfigInvalidArray(field));
                    }
                }
                *out = buf;
                Ok(true)
            } else {
                Err(Error::ConfigInvalidArray(field))
            }
        } else {
            Ok(false)
        }
    }
}

fn format_errors(errors: &Vec<toml::ParserError>) -> String {
    let mut msg = String::new();
    for err in errors {
        msg.push_str(&format!("\terror: {}\n", err.desc));
    }
    msg
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::path::Path;

use toml::{Parser, Value, Table};

use error::FatalError;

pub static SIGN_COMMIT: &'static str = "sign-commit";
pub static PUSH_REMOTE: &'static str = "push-remote";
pub static DOC_BRANCH: &'static str = "doc-branch";
pub static DOC_COMMIT_MESSAGE: &'static str = "doc-commit-message";

fn load_from_file(path: &Path) -> io::Result<String> {
    let mut file = try!(File::open(path));
    let mut s = String::new();
    try!(file.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_cargo_config() -> Result<Table, FatalError> {
    let cargo_file_path = Path::new("Cargo.toml");

    let cargo_file_content = try!(load_from_file(&cargo_file_path).map_err(FatalError::from));

    let mut parser = Parser::new(&cargo_file_content);

    match parser.parse() {
        Some(toml) => Ok(toml),
        None => Err(FatalError::InvalidCargoFileFormat),
    }
}

pub fn get_release_config<'a>(config: &'a Table, key: &str) -> Option<&'a Value> {
    config.get("package")
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("metadata"))
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("gh-pages"))
        .and_then(|f| f.as_table())
        .and_then(|f| f.get(key))
}

pub fn verify_release_config(config: &Table) -> Option<Vec<&str>> {
    let valid_keys = vec![SIGN_COMMIT, PUSH_REMOTE, DOC_BRANCH, DOC_COMMIT_MESSAGE];
    if let Some(r) = config.get("package")
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("metadata"))
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("gh-pages"))
        .and_then(|f| f.as_table()) {
        let mut invalid_keys = Vec::new();
        for i in r.keys() {
            if !valid_keys.contains(&i.as_ref()) {
                invalid_keys.push(i.as_ref());
            }
        }
        if invalid_keys.is_empty() {
            None
        } else {
            Some(invalid_keys)
        }
    } else {
        None
    }
}

#[test]
fn test_release_config() {
    if let Ok(cargo_file) = parse_cargo_config() {
        // Check sign-commit set to false in Cargo.toml of this repository.
        assert!(get_release_config(&cargo_file, "sign-commit")
            .and_then(|f| f.as_bool())
            .map(|f| f == false)
            .unwrap_or(false));
    } else {
        panic!("Parse cargo file failed.");
    }
}
<commit_msg>Use ok_or instead of Option match. (#9)<commit_after>use std::io::prelude::*;
use std::io;
use std::fs::File;
use std::path::Path;

use toml::{Parser, Value, Table};

use error::FatalError;

pub static SIGN_COMMIT: &'static str = "sign-commit";
pub static PUSH_REMOTE: &'static str = "push-remote";
pub static DOC_BRANCH: &'static str = "doc-branch";
pub static DOC_COMMIT_MESSAGE: &'static str = "doc-commit-message";

fn load_from_file(path: &Path) -> io::Result<String> {
    let mut file = try!(File::open(path));
    let mut s = String::new();
    try!(file.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_cargo_config() -> Result<Table, FatalError> {
    let cargo_file_path = Path::new("Cargo.toml");

    let cargo_file_content = try!(load_from_file(&cargo_file_path).map_err(FatalError::from));

    let mut parser = Parser::new(&cargo_file_content);

    parser.parse()
        .ok_or(FatalError::InvalidCargoFileFormat)
}

pub fn get_release_config<'a>(config: &'a Table, key: &str) -> Option<&'a Value> {
    config.get("package")
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("metadata"))
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("gh-pages"))
        .and_then(|f| f.as_table())
        .and_then(|f| f.get(key))
}

pub fn verify_release_config(config: &Table) -> Option<Vec<&str>> {
    let valid_keys = vec![SIGN_COMMIT, PUSH_REMOTE, DOC_BRANCH, DOC_COMMIT_MESSAGE];
    if let Some(r) = config.get("package")
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("metadata"))
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("gh-pages"))
        .and_then(|f| f.as_table()) {
        let mut invalid_keys = Vec::new();
        for i in r.keys() {
            if !valid_keys.contains(&i.as_ref()) {
                invalid_keys.push(i.as_ref());
            }
        }
        if invalid_keys.is_empty() {
            None
        } else {
            Some(invalid_keys)
        }
    } else {
        None
    }
}

#[test]
fn test_release_config() {
    if let Ok(cargo_file) = parse_cargo_config() {
        // Check sign-commit set to false in Cargo.toml of this repository.
        assert!(get_release_config(&cargo_file, "sign-commit")
            .and_then(|f| f.as_bool())
            .map(|f| f == false)
            .unwrap_or(false));
    } else {
        panic!("Parse cargo file failed.");
    }
}
<|endoftext|>


<commit_before>// revisions: cfail1 cfail2 cfail3
// compile-flags: -Coverflow-checks=on
// build-pass (FIXME(62277): could be check-pass?)

#![warn(const_err)]

fn main() {
    let _ = 255u8 + 1; //~ WARNING attempt to add with overflow
}
<commit_msg>fix incremental tests<commit_after>// revisions: cfail1 cfail2 cfail3
// compile-flags: -Coverflow-checks=on
// build-pass (FIXME(62277): could be check-pass?)

#![warn(overflow)]

fn main() {
    let _ = 255u8 + 1; //~ WARNING operation will overflow
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

use ecs::*;
use math::Coord;
use grid::{Grid, DynamicGrid};

pub struct SpatialHashCell {
    // sum of opacities of everything in this cell
    opacity: f64,

    // count of solid entities in this cell
    solid: usize,

    entities: EntitySet,
}

pub struct SpatialHashTable {
    grid: DynamicGrid<SpatialHashCell>,
    empty: SpatialHashCell,
}

impl SpatialHashCell {
    fn new() -> Self {
        SpatialHashCell {
            opacity: 0.0,
            solid: 0,
            entities: EntitySet::new(),
        }
    }

    pub fn opacity(&self) -> f64 {
        self.opacity
    }

    pub fn solid(&self) -> bool {
        self.solid != 0
    }
}

impl Default for SpatialHashCell {
    fn default() -> Self {
        Self::new()
    }
}

impl SpatialHashTable {
    pub fn new() -> Self {
        SpatialHashTable {
            grid: DynamicGrid::new(),
            empty: SpatialHashCell::new(),
        }
    }

    pub fn get(&self, coord: Coord) -> &SpatialHashCell {
        self.grid.get(coord).unwrap_or(&self.empty)
    }

    pub fn limits_min(&self) -> Coord {
        self.grid.limits_min()
    }

    pub fn limits_max(&self) -> Coord {
        self.grid.limits_max()
    }

    fn get_mut_with_default(&mut self, coord: Coord) -> &mut SpatialHashCell {
        self.grid.get_mut_with_default(coord)
    }

    fn change_entity_position(&mut self, entity: EntityRef, insertion: ActionInsertionEntityRef, current_position: Coord, new_position: Coord) {
        self.remove_entity_position(entity, current_position);
        self.add_entity_position(insertion, new_position);
    }

    fn remove_entity_position(&mut self, entity: EntityRef, position: Coord) {
        let mut cell = self.get_mut_with_default(position);
        if entity.contains_solid() {
            cell.solid -= 1;
        }
        if let Some(opacity) = entity.opacity() {
            cell.opacity -= opacity;
        }
        cell.entities.remove(&entity.id());
    }

    fn add_entity_position(&mut self, insertion: ActionInsertionEntityRef, position: Coord) {
        let mut cell = self.get_mut_with_default(position);
        if insertion.contains_solid() {
            cell.solid += 1;
        }
        if let Some(opacity) = insertion.opacity() {
            cell.opacity += opacity;
        }
        cell.entities.insert(insertion.id());
    }

    fn update_insertions(&mut self, ctx: &EcsCtx, insertions: &ActionInsertionTable) {
        for (entity_id, new_position) in insertions.position.iter() {
            let entity = ctx.entity(*entity_id);
            let insertion = insertions.entity(*entity_id);
            if let Some(current_position) = entity.position() {
                // the entity is changing position
                self.change_entity_position(entity, insertion, current_position, *new_position);
            } else {
                // the entity is gaining a position
                self.add_entity_position(insertion, *new_position);
            }
        }
    }

    fn update_removals(&mut self, ctx: &EcsCtx, removals: &ActionRemovalTable) {

        // loop through each component tracked by the spatial hash

        for entity_id in removals.solid.iter() {
            if let Some(position) = ctx.position(*entity_id) {
                // removing solid from entity with position
                self.get_mut_with_default(position).solid -= 1;
            }
        }

        for entity_id in removals.opacity.iter() {
            let entity = ctx.entity(*entity_id);
            if let Some(position) = entity.position() {
                if let Some(opacity) = entity.opacity() {
                    // removing opacity from entity with position
                    self.get_mut_with_default(position).opacity -= opacity;
                }
            }
        }

        // remove entities whose positions were removed
        for entity_id in removals.position.iter() {
            let entity = ctx.entity(*entity_id);
            if let Some(position) = entity.position() {
                self.remove_entity_position(entity, position);
            }
        }
    }

    fn update_removed_entities(&mut self,
                               ctx: &EcsCtx,
                               entities: &HashSet<EntityId>) {
        for entity_id in entities.iter() {
            let entity = ctx.entity(*entity_id);
            if let Some(position) = entity.position() {
                self.remove_entity_position(entity, position);
            }
        }
    }

    pub fn update(&mut self, ctx: &EcsCtx, action: &EcsAction) {
        self.update_insertions(ctx, &action.insertions);
        self.update_removals(ctx, &action.removals);
        self.update_removed_entities(ctx, &action.removed_entities);
    }
}
<commit_msg>Fixed bug relating to moving entities<commit_after>use std::collections::HashSet;

use ecs::*;
use math::Coord;
use grid::{Grid, DynamicGrid};

pub struct SpatialHashCell {
    // sum of opacities of everything in this cell
    opacity: f64,

    // count of solid entities in this cell
    solid: usize,

    entities: EntitySet,
}

pub struct SpatialHashTable {
    grid: DynamicGrid<SpatialHashCell>,
    empty: SpatialHashCell,
}

impl SpatialHashCell {
    fn new() -> Self {
        SpatialHashCell {
            opacity: 0.0,
            solid: 0,
            entities: EntitySet::new(),
        }
    }

    pub fn opacity(&self) -> f64 {
        self.opacity
    }

    pub fn solid(&self) -> bool {
        self.solid != 0
    }
}

impl Default for SpatialHashCell {
    fn default() -> Self {
        Self::new()
    }
}

impl SpatialHashTable {
    pub fn new() -> Self {
        SpatialHashTable {
            grid: DynamicGrid::new(),
            empty: SpatialHashCell::new(),
        }
    }

    pub fn get(&self, coord: Coord) -> &SpatialHashCell {
        self.grid.get(coord).unwrap_or(&self.empty)
    }

    pub fn limits_min(&self) -> Coord {
        self.grid.limits_min()
    }

    pub fn limits_max(&self) -> Coord {
        self.grid.limits_max()
    }

    fn get_mut_with_default(&mut self, coord: Coord) -> &mut SpatialHashCell {
        self.grid.get_mut_with_default(coord)
    }

    fn change_entity_position(&mut self, entity: PostInsertionEntityRef, current_position: Coord, new_position: Coord) {
        self.remove_entity_position(entity.to_entity_ref(), current_position);
        self.add_entity_position(entity, new_position);
    }

    fn remove_entity_position(&mut self, entity: EntityRef, position: Coord) {
        let mut cell = self.get_mut_with_default(position);
        if entity.contains_solid() {
            cell.solid -= 1;
        }
        if let Some(opacity) = entity.opacity() {
            cell.opacity -= opacity;
        }
        cell.entities.remove(&entity.id());
    }

    fn add_entity_position(&mut self, entity: PostInsertionEntityRef, position: Coord) {
        let mut cell = self.get_mut_with_default(position);
        if entity.contains_solid() {
            cell.solid += 1;
        }
        if let Some(opacity) = entity.opacity() {
            cell.opacity += opacity;
        }
        cell.entities.insert(entity.id());
    }

    fn update_insertions(&mut self, ctx: &EcsCtx, insertions: &ActionInsertionTable) {
        for (entity_id, new_position) in insertions.position.iter() {
            let entity = ctx.post_insertion_entity(*entity_id, insertions);
            if let Some(current_position) = entity.current_position() {
                // the entity is changing position
                self.change_entity_position(entity, current_position, *new_position);
            } else {
                // the entity is gaining a position
                self.add_entity_position(entity, *new_position);
            }
        }
    }

    fn update_removals(&mut self, ctx: &EcsCtx, removals: &ActionRemovalTable) {

        // loop through each component tracked by the spatial hash

        for entity_id in removals.solid.iter() {
            if let Some(position) = ctx.position(*entity_id) {
                // removing solid from entity with position
                self.get_mut_with_default(position).solid -= 1;
            }
        }

        for entity_id in removals.opacity.iter() {
            let entity = ctx.entity(*entity_id);
            if let Some(position) = entity.position() {
                if let Some(opacity) = entity.opacity() {
                    // removing opacity from entity with position
                    self.get_mut_with_default(position).opacity -= opacity;
                }
            }
        }

        // remove entities whose positions were removed
        for entity_id in removals.position.iter() {
            let entity = ctx.entity(*entity_id);
            if let Some(position) = entity.position() {
                self.remove_entity_position(entity, position);
            }
        }
    }

    fn update_removed_entities(&mut self,
                               ctx: &EcsCtx,
                               entities: &HashSet<EntityId>) {
        for entity_id in entities.iter() {
            let entity = ctx.entity(*entity_id);
            if let Some(position) = entity.position() {
                self.remove_entity_position(entity, position);
            }
        }
    }

    pub fn update(&mut self, ctx: &EcsCtx, action: &EcsAction) {
        self.update_insertions(ctx, &action.insertions);
        self.update_removals(ctx, &action.removals);
        self.update_removed_entities(ctx, &action.removed_entities);
    }
}
<|endoftext|>