<commit_before>use std::rc::Rc;

use xcb;
use cairo::{self, XCBSurface};
use cairo_sys;

use text::Text;

fn get_root_visual_type(conn: &xcb::Connection, screen: &xcb::Screen) -> xcb::Visualtype {
    for root in conn.get_setup().roots() {
        for allowed_depth in root.allowed_depths() {
            for visual in allowed_depth.visuals() {
                if visual.visual_id() == screen.root_visual() {
                    return visual;
                }
            }
        }
    }
    panic!("No visual type found");
}

// TODO: impl Drop?
pub struct Window {
    conn: Rc<xcb::Connection>,
    screen_idx: usize,
    surface: cairo::Surface,
}

impl Window {
    pub fn new(conn: Rc<xcb::Connection>, screen_idx: usize) -> Window {
        let id = conn.generate_id();

        let surface = {
            let screen = conn.get_setup()
                .roots()
                .nth(screen_idx)
                .expect("invalid screen");
            let values = [(xcb::CW_BACK_PIXEL, screen.black_pixel()),
                          (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE)];

            let (width, height) = (screen.width_in_pixels(), 100);

            xcb::create_window(&conn,
                               xcb::COPY_FROM_PARENT as u8,
                               id,
                               screen.root(),
                               0,
                               0,
                               width,
                               height,
                               10,
                               xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
                               screen.root_visual(),
                               &values);

            unsafe {
                let cairo_conn = cairo::XCBConnection::from_raw_none(conn.get_raw_conn() as
                                                                     *mut cairo_sys::xcb_connection_t);
                let visual =
                    cairo::XCBVisualType::from_raw_none(&mut get_root_visual_type(&conn, &screen).base as
                                                        *mut xcb::ffi::xcb_visualtype_t as
                                                        *mut cairo_sys::xcb_visualtype_t);
                let drawable = cairo::XCBDrawable(id);
                cairo::Surface::create(&cairo_conn, &drawable, &visual, width as i32, height as i32)
                // TODO: Update surface width/height when window size changes.
            }
        };

        xcb::map_window(&conn, id);
        conn.flush();

        Window {
            conn,
            screen_idx,
            surface,
        }
    }

    fn screen(&self) -> xcb::Screen {
        self.conn
            .get_setup()
            .roots()
            .nth(self.screen_idx)
            .expect("Invalid screen")
    }

    pub fn expose(&self, texts: Vec<Text>) {
        self.render_text_blocks(texts);
        self.conn.flush();
    }

    fn render_text_blocks(&self, texts: Vec<Text>) {
        // Layout each block of text. After this, we can query the width of each
        // block, which will allow us to do more complex layout below.
        let mut layouts: Vec<_> = texts.into_iter().map(|t| t.layout(&self.surface)).collect();

        // Calculate how much free space we have after laying out all the
        // non-stretch blocks. Split the remaining space (if any) between the
        // stretch blocks. If there isn't enough space for the non-stretch blocks
        // do nothing and allow it to overflow.
        {
            let mut width = 0.0;
            let mut stretched = Vec::new();
            for layout in layouts.iter_mut() {
                if !layout.stretch() {
                    width += layout.width();
                } else {
                    stretched.push(layout);
                }
            }

            let remaining_width = self.screen().width_in_pixels() as f64 - width;
            let remaining_width = if remaining_width < 0.0 {
                0.0
            } else {
                remaining_width
            };
            let width_per_stretched = remaining_width / (stretched.len() as f64);
            for layout in stretched.iter_mut() {
                layout.set_width(width_per_stretched);
            }
        }

        // TODO: Set the height of the window and the height of each text block(?)
        // to the height of the largest bit of text.

        // Finally, just render each block of text in turn.
        let mut x = 0.0;
        for layout in &layouts {
            layout.render(x, 0.0);
            x += layout.width();
        }
    }
}
<commit_msg>Use `&mut something` rather than `something.iter_mut()`.<commit_after>use std::rc::Rc;

use xcb;
use cairo::{self, XCBSurface};
use cairo_sys;

use text::Text;

fn get_root_visual_type(conn: &xcb::Connection, screen: &xcb::Screen) -> xcb::Visualtype {
    for root in conn.get_setup().roots() {
        for allowed_depth in root.allowed_depths() {
            for visual in allowed_depth.visuals() {
                if visual.visual_id() == screen.root_visual() {
                    return visual;
                }
            }
        }
    }
    panic!("No visual type found");
}

// TODO: impl Drop?
pub struct Window {
    conn: Rc<xcb::Connection>,
    screen_idx: usize,
    surface: cairo::Surface,
}

impl Window {
    pub fn new(conn: Rc<xcb::Connection>, screen_idx: usize) -> Window {
        let id = conn.generate_id();

        let surface = {
            let screen = conn.get_setup()
                .roots()
                .nth(screen_idx)
                .expect("invalid screen");
            let values = [(xcb::CW_BACK_PIXEL, screen.black_pixel()),
                          (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE)];

            let (width, height) = (screen.width_in_pixels(), 100);

            xcb::create_window(&conn,
                               xcb::COPY_FROM_PARENT as u8,
                               id,
                               screen.root(),
                               0,
                               0,
                               width,
                               height,
                               10,
                               xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
                               screen.root_visual(),
                               &values);

            unsafe {
                let cairo_conn = cairo::XCBConnection::from_raw_none(conn.get_raw_conn() as
                                                                     *mut cairo_sys::xcb_connection_t);
                let visual =
                    cairo::XCBVisualType::from_raw_none(&mut get_root_visual_type(&conn, &screen).base as
                                                        *mut xcb::ffi::xcb_visualtype_t as
                                                        *mut cairo_sys::xcb_visualtype_t);
                let drawable = cairo::XCBDrawable(id);
                cairo::Surface::create(&cairo_conn, &drawable, &visual, width as i32, height as i32)
                // TODO: Update surface width/height when window size changes.
            }
        };

        xcb::map_window(&conn, id);
        conn.flush();

        Window {
            conn,
            screen_idx,
            surface,
        }
    }

    fn screen(&self) -> xcb::Screen {
        self.conn
            .get_setup()
            .roots()
            .nth(self.screen_idx)
            .expect("Invalid screen")
    }

    pub fn expose(&self, texts: Vec<Text>) {
        self.render_text_blocks(texts);
        self.conn.flush();
    }

    fn render_text_blocks(&self, texts: Vec<Text>) {
        // Layout each block of text. After this, we can query the width of each
        // block, which will allow us to do more complex layout below.
        let mut layouts: Vec<_> = texts.into_iter().map(|t| t.layout(&self.surface)).collect();

        // Calculate how much free space we have after laying out all the
        // non-stretch blocks. Split the remaining space (if any) between the
        // stretch blocks. If there isn't enough space for the non-stretch blocks
        // do nothing and allow it to overflow.
        {
            let mut width = 0.0;
            let mut stretched = Vec::new();
            for layout in &mut layouts {
                if !layout.stretch() {
                    width += layout.width();
                } else {
                    stretched.push(layout);
                }
            }

            let remaining_width = self.screen().width_in_pixels() as f64 - width;
            let remaining_width = if remaining_width < 0.0 {
                0.0
            } else {
                remaining_width
            };
            let width_per_stretched = remaining_width / (stretched.len() as f64);
            for layout in &mut stretched {
                layout.set_width(width_per_stretched);
            }
        }

        // TODO: Set the height of the window and the height of each text block(?)
        // to the height of the largest bit of text.

        // Finally, just render each block of text in turn.
        let mut x = 0.0;
        for layout in &layouts {
            layout.render(x, 0.0);
            x += layout.width();
        }
    }
}
<|endoftext|>


<commit_before>
use std::cell::RefCell;
use std::sync::Arc;
use std::thread;
use std::sync::mpsc::Receiver;
use std::boxed::FnBox;

use pulse::Signal;
use libc::funcs::posix88::unistd::usleep;
use rand::{self, Rng};
use deque::{self, Stolen};
use back::{Backend, ReadyTask};
use bran;

pub enum Command {
    Add(usize, deque::Stealer<ReadyTask>),
    Exit
}

thread_local!(static WORKER: RefCell<Option<Worker>> = RefCell::new(None));

pub struct Worker {
    index: usize,
    back: Arc<Backend>,
    queue: deque::Worker<ReadyTask>,
    command: Option<Receiver<Command>>
}

impl Worker {
    pub fn new(back: Arc<Backend>) -> Worker {
        let (index, worker, rx) = back.new_deque();

        Worker {
            back: back,
            index: index,
            queue: worker,
            command: Some(rx)
        }
    }

    pub fn start(self) {
        let name = format!("Worker {}", self.index);
        let back = self.back.clone();
        let guard = thread::Builder::new().name(name).spawn(move || {
            WORKER.with(|worker| {
                *worker.borrow_mut() = Some(self);
            });
            work();
        }).unwrap();

        back.register_worker(guard);
    }
}

#[inline(never)]
fn work() {
    WORKER.with(|worker| {
        let cmd = worker.borrow_mut().as_mut().unwrap().command.take().unwrap();

        let mut rand = rand::XorShiftRng::new_unseeded();
        let mut stealers: Vec<(usize, deque::Stealer<ReadyTask>)> = Vec::new();

        let mut i = 0;
        let mut run = true;
        let mut backoff = 0;

        while run {
            // Try to grab form our own queue
            if let Some(task) = worker.borrow().as_ref().unwrap().queue.pop() {
                task.run();
                i = 0;
                backoff = 0;
                continue;
            }

            while run {
                i += 1;

                // Try to grab from one of the stealers
                if stealers.len() > 0 {
                    let x: usize = rand.gen();
                    let x = x % stealers.len();
                    if let Stolen::Data(task) = stealers[x].1.steal() {
                        task.run();
                        i = 0;
                        backoff = 0;
                        break;
                    }
                }

                // Try to go to sleep
                if i >= stealers.len() * 2 {
                    while let Ok(msg) = cmd.try_recv() {
                        match msg {
                            Command::Add(key, value) => {
                                stealers.push((key, value));
                            }
                            Command::Exit => {
                                run = false;
                            }
                        }
                        i = 0;
                    }

                    if i != 0 {
                        backoff += 5;
                        unsafe { usleep(backoff) };
                        i = stealers.len();
                    }
                }
            }
        }
    });
}

// Use the task on the TLS queue or the queue in the backend
#[inline]
pub fn start(rt: ReadyTask) -> Result<bool, ReadyTask> {
    WORKER.with(|worker| {
        if let Some(worker) = worker.borrow().as_ref() {
            worker.queue.push(rt);
            Ok(true)
        } else {
            Err(rt)
        }
    })
}

/// used for fibers to give them child task spawning
pub struct FiberSchedule;

impl super::Schedule for FiberSchedule {
    fn add_task(&mut self, task: Box<FnBox()+Send>, after: Vec<Signal>) {
        let back = WORKER.with(|worker| {
            worker.borrow()
                  .as_ref()
                  .expect("a fiber was resumed outside of a worker")
                  .back.clone()
        });
        Backend::start(back, task, after)
    }
}

pub fn requeue(task: bran::Handle, after: Signal) {
    let back = WORKER.with(|worker| {
        worker.borrow()
              .as_ref()
              .expect("a fiber was resumed outside of a worker")
              .back.clone()
    });
    Backend::enqueue(back, task, after)
}<commit_msg>use sleep_ms for windows reason<commit_after>
use std::cell::RefCell;
use std::sync::Arc;
use std::thread;
use std::sync::mpsc::Receiver;
use std::boxed::FnBox;
use std::thread::sleep_ms;

use pulse::Signal;
use rand::{self, Rng};
use deque::{self, Stolen};
use back::{Backend, ReadyTask};
use bran;

pub enum Command {
    Add(usize, deque::Stealer<ReadyTask>),
    Exit
}

thread_local!(static WORKER: RefCell<Option<Worker>> = RefCell::new(None));

pub struct Worker {
    index: usize,
    back: Arc<Backend>,
    queue: deque::Worker<ReadyTask>,
    command: Option<Receiver<Command>>
}

impl Worker {
    pub fn new(back: Arc<Backend>) -> Worker {
        let (index, worker, rx) = back.new_deque();

        Worker {
            back: back,
            index: index,
            queue: worker,
            command: Some(rx)
        }
    }

    pub fn start(self) {
        let name = format!("Worker {}", self.index);
        let back = self.back.clone();
        let guard = thread::Builder::new().name(name).spawn(move || {
            WORKER.with(|worker| {
                *worker.borrow_mut() = Some(self);
            });
            work();
        }).unwrap();

        back.register_worker(guard);
    }
}

#[inline(never)]
fn work() {
    WORKER.with(|worker| {
        let cmd = worker.borrow_mut().as_mut().unwrap().command.take().unwrap();

        let mut rand = rand::XorShiftRng::new_unseeded();
        let mut stealers: Vec<(usize, deque::Stealer<ReadyTask>)> = Vec::new();

        let mut i = 0;
        let mut run = true;
        let mut backoff = 0;

        while run {
            // Try to grab form our own queue
            if let Some(task) = worker.borrow().as_ref().unwrap().queue.pop() {
                task.run();
                i = 0;
                backoff = 0;
                continue;
            }

            while run {
                i += 1;

                // Try to grab from one of the stealers
                if stealers.len() > 0 {
                    let x: usize = rand.gen();
                    let x = x % stealers.len();
                    if let Stolen::Data(task) = stealers[x].1.steal() {
                        task.run();
                        i = 0;
                        backoff = 0;
                        break;
                    }
                }

                // Try to go to sleep
                if i >= stealers.len() * 2 {
                    while let Ok(msg) = cmd.try_recv() {
                        match msg {
                            Command::Add(key, value) => {
                                stealers.push((key, value));
                            }
                            Command::Exit => {
                                run = false;
                            }
                        }
                        i = 0;
                    }

                    if i != 0 {
                        backoff += 1;
                        sleep_ms(backoff);
                        i = stealers.len();
                    }
                }
            }
        }
    });
}

// Use the task on the TLS queue or the queue in the backend
#[inline]
pub fn start(rt: ReadyTask) -> Result<bool, ReadyTask> {
    WORKER.with(|worker| {
        if let Some(worker) = worker.borrow().as_ref() {
            worker.queue.push(rt);
            Ok(true)
        } else {
            Err(rt)
        }
    })
}

/// used for fibers to give them child task spawning
pub struct FiberSchedule;

impl super::Schedule for FiberSchedule {
    fn add_task(&mut self, task: Box<FnBox()+Send>, after: Vec<Signal>) {
        let back = WORKER.with(|worker| {
            worker.borrow()
                  .as_ref()
                  .expect("a fiber was resumed outside of a worker")
                  .back.clone()
        });
        Backend::start(back, task, after)
    }
}

pub fn requeue(task: bran::Handle, after: Signal) {
    let back = WORKER.with(|worker| {
        worker.borrow()
              .as_ref()
              .expect("a fiber was resumed outside of a worker")
              .back.clone()
    });
    Backend::enqueue(back, task, after)
}<|endoftext|>


<commit_before>//! Write las points.
//!
//! A `Writer` uses a `Header` for its configuration:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Writer, Header};
//! let mut header = Header::default();
//! header.version = (1, 4).into();
//! let writer = Writer::new(Cursor::new(Vec::new()), header).unwrap();
//! ```
//!
//! The set of optional fields on the point format and the points must match exactly:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Writer, Header, Point};
//! use las::point::Format;
//! use las::Color;
//!
//! let mut header = Header::default();
//! header.point_format = Format::new(1).unwrap();
//! let mut writer = Writer::new(Cursor::new(Vec::new()), header).unwrap();
//!
//! let mut point = Point::default(); // default points don't have any optional attributes
//! assert!(writer.write(point.clone()).is_err());
//!
//! point.gps_time = Some(42.); // point format 1 requires gps time
//! writer.write(point.clone()).unwrap();
//!
//! point.color = Some(Color::new(1, 2, 3));
//! assert!(writer.write(point).is_err()); // the point's color would be lost
//! ```

use {Header, Point, Result};
use point::Format;
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufWriter, Seek, SeekFrom, Write};
use std::path::Path;

quick_error! {
    /// Writer errors.
    #[derive(Debug)]
    pub enum Error {
        /// The writer is closed.
        Closed {
            description("the writer is closed")
        }
        /// The attributes of the point format and point do not match.
        PointAttributes(format: Format, point: Point) {
            description("the attributes of the point format and point do not match")
            display("the attributes of point format {:?} does not match point {:?}", format, point)
        }
    }
}

/// Writes LAS data.
///
/// The LAS header needs to be re-written when the writer closes. For convenience, this is done via
/// the `Drop` implementation of the writer. One consequence is that if the header re-write fails
/// during the drop, a panic will result. If you want to check for errors instead of panicing, use
/// `close` explicitly.
///
/// ```
/// use std::io::Cursor;
/// # use las::Writer;
/// {
///     let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
///     writer.close().unwrap();
/// } // <- `close` is not called
/// ```
#[derive(Debug)]
pub struct Writer<W: Seek + Write> {
    closed: bool,
    header: Header,
    write: W,
}

impl<W: Seek + Write> Writer<W> {
    /// Creates a new writer.
    ///
    /// The header that is passed in will have various fields zero'd, e.g. bounds, number of
    /// points, etc.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let writer = Writer::new(Cursor::new(Vec::new()), Default::default());
    /// ```
    pub fn new(mut write: W, mut header: Header) -> Result<Writer<W>> {
        header.bounds = Default::default();
        header.number_of_points = 0;
        header.number_of_points_by_return = HashMap::new();
        if header.version.requires_point_data_start_signature() {
            // TODO we shouldn't overwrite the old vlr padding
            header.vlr_padding = ::raw::POINT_DATA_START_SIGNATURE.to_vec();
        }
        header.clone().into_raw().and_then(|raw_header| {
            raw_header.write_to(&mut write)
        })?;
        for vlr in header.vlrs().iter() {
            (*vlr).clone().into_raw(false).and_then(|raw_vlr| {
                raw_vlr.write_to(&mut write)
            })?;
        }
        if !header.vlr_padding.is_empty() {
            write.write_all(&header.vlr_padding)?;
        }
        Ok(Writer {
            closed: false,
            header: header,
            write: write,
        })
    }

    /// Writes a point.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    ///
    /// let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
    /// writer.write(Default::default()).unwrap();
    /// ```
    pub fn write(&mut self, point: Point) -> Result<()> {
        if self.closed {
            return Err(Error::Closed.into());
        }
        if !point.matches(self.header.point_format) {
            return Err(
                Error::PointAttributes(self.header.point_format, point).into(),
            );
        }
        self.header.number_of_points += 1;
        {
            let entry = self.header
                .number_of_points_by_return
                .entry(point.return_number)
                .or_insert(0);
            *entry += 1;
        }
        self.header.bounds.grow(&point);
        point.into_raw(self.header.transforms).and_then(
            |raw_point| {
                raw_point.write_to(&mut self.write, self.header.point_format)
            },
        )?;
        Ok(())
    }

    /// Close this writer.
    ///
    /// A second call to close is a no-op.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
    /// writer.close().unwrap();
    /// writer.close().unwrap(); // <- no-op
    ///
    pub fn close(&mut self) -> Result<()> {
        if !self.closed {
            for raw_evlr in self.header.evlrs().into_iter().map(|evlr| {
                evlr.clone().into_raw(true)
            })
            {
                raw_evlr?.write_to(&mut self.write)?;
            }
            self.write.seek(SeekFrom::Start(0))?;
            self.header.clone().into_raw().and_then(|raw_header| {
                raw_header.write_to(&mut self.write)
            })?;
            self.closed = true;
        }
        Ok(())
    }
}

impl Writer<BufWriter<File>> {
    /// Creates a new writer for a path.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Writer;
    /// let writer = Writer::from_path("/dev/null", Default::default());
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P, header: Header) -> Result<Writer<BufWriter<File>>> {
        File::create(path).map_err(::Error::from).and_then(|file| {
            Writer::new(BufWriter::new(file), header)
        })
    }
}

impl<W: Seek + Write> Drop for Writer<W> {
    fn drop(&mut self) {
        if !self.closed {
            self.close().expect("Error when dropping the writer");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use {Header, Version};
    use byteorder::{LittleEndian, ReadBytesExt};
    use point::Format;
    use std::io::Cursor;

    fn writer(format: Format, version: Version) -> Writer<Cursor<Vec<u8>>> {
        let mut header = Header::default();
        header.point_format = format;
        header.version = version;
        Writer::new(Cursor::new(Vec::new()), header).unwrap()
    }

    #[test]
    fn las_1_0_point_data_start_signature() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut header = Header::default();
            header.version = (1, 0).into();
            header.push_vlr(Default::default());
            let mut writer = Writer::new(&mut cursor, header).unwrap();
            writer.write(Default::default()).unwrap();
        }
        cursor.set_position(281);
        assert_eq!(0xCCDD, cursor.read_u16::<LittleEndian>().unwrap());
    }

    #[test]
    fn already_closed() {
        let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
        writer.close().unwrap();
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_extra_bytes() {
        let format = Format {
            extra_bytes: 1,
            ..Default::default()
        };
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_gps_time() {
        let format = Format::new(1).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_color() {
        let format = Format::new(2).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_nir() {
        let format = Format::new(8).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        let point = Point {
            gps_time: Some(0.),
            color: Some(Default::default()),
            ..Default::default()
        };
        assert!(writer.write(point).is_err());
    }

    #[test]
    fn missing_waveform() {
        let format = Format::new(4).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }
}
<commit_msg>Show `use las::Writer` in docs<commit_after>//! Write las points.
//!
//! A `Writer` uses a `Header` for its configuration:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Writer, Header};
//! let mut header = Header::default();
//! header.version = (1, 4).into();
//! let writer = Writer::new(Cursor::new(Vec::new()), header).unwrap();
//! ```
//!
//! The set of optional fields on the point format and the points must match exactly:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Writer, Header, Point};
//! use las::point::Format;
//! use las::Color;
//!
//! let mut header = Header::default();
//! header.point_format = Format::new(1).unwrap();
//! let mut writer = Writer::new(Cursor::new(Vec::new()), header).unwrap();
//!
//! let mut point = Point::default(); // default points don't have any optional attributes
//! assert!(writer.write(point.clone()).is_err());
//!
//! point.gps_time = Some(42.); // point format 1 requires gps time
//! writer.write(point.clone()).unwrap();
//!
//! point.color = Some(Color::new(1, 2, 3));
//! assert!(writer.write(point).is_err()); // the point's color would be lost
//! ```

use {Header, Point, Result};
use point::Format;
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufWriter, Seek, SeekFrom, Write};
use std::path::Path;

quick_error! {
    /// Writer errors.
    #[derive(Debug)]
    pub enum Error {
        /// The writer is closed.
        Closed {
            description("the writer is closed")
        }
        /// The attributes of the point format and point do not match.
        PointAttributes(format: Format, point: Point) {
            description("the attributes of the point format and point do not match")
            display("the attributes of point format {:?} does not match point {:?}", format, point)
        }
    }
}

/// Writes LAS data.
///
/// The LAS header needs to be re-written when the writer closes. For convenience, this is done via
/// the `Drop` implementation of the writer. One consequence is that if the header re-write fails
/// during the drop, a panic will result. If you want to check for errors instead of panicing, use
/// `close` explicitly.
///
/// ```
/// use std::io::Cursor;
/// use las::Writer;
/// {
///     let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
///     writer.close().unwrap();
/// } // <- `close` is not called
/// ```
#[derive(Debug)]
pub struct Writer<W: Seek + Write> {
    closed: bool,
    header: Header,
    write: W,
}

impl<W: Seek + Write> Writer<W> {
    /// Creates a new writer.
    ///
    /// The header that is passed in will have various fields zero'd, e.g. bounds, number of
    /// points, etc.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// use las::Writer;
    /// let writer = Writer::new(Cursor::new(Vec::new()), Default::default());
    /// ```
    pub fn new(mut write: W, mut header: Header) -> Result<Writer<W>> {
        header.bounds = Default::default();
        header.number_of_points = 0;
        header.number_of_points_by_return = HashMap::new();
        if header.version.requires_point_data_start_signature() {
            // TODO we shouldn't overwrite the old vlr padding
            header.vlr_padding = ::raw::POINT_DATA_START_SIGNATURE.to_vec();
        }
        header.clone().into_raw().and_then(|raw_header| {
            raw_header.write_to(&mut write)
        })?;
        for vlr in header.vlrs().iter() {
            (*vlr).clone().into_raw(false).and_then(|raw_vlr| {
                raw_vlr.write_to(&mut write)
            })?;
        }
        if !header.vlr_padding.is_empty() {
            write.write_all(&header.vlr_padding)?;
        }
        Ok(Writer {
            closed: false,
            header: header,
            write: write,
        })
    }

    /// Writes a point.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// use las::Writer;
    ///
    /// let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
    /// writer.write(Default::default()).unwrap();
    /// ```
    pub fn write(&mut self, point: Point) -> Result<()> {
        if self.closed {
            return Err(Error::Closed.into());
        }
        if !point.matches(self.header.point_format) {
            return Err(
                Error::PointAttributes(self.header.point_format, point).into(),
            );
        }
        self.header.number_of_points += 1;
        {
            let entry = self.header
                .number_of_points_by_return
                .entry(point.return_number)
                .or_insert(0);
            *entry += 1;
        }
        self.header.bounds.grow(&point);
        point.into_raw(self.header.transforms).and_then(
            |raw_point| {
                raw_point.write_to(&mut self.write, self.header.point_format)
            },
        )?;
        Ok(())
    }

    /// Close this writer.
    ///
    /// A second call to close is a no-op.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// use las::Writer;
    /// let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
    /// writer.close().unwrap();
    /// writer.close().unwrap(); // <- no-op
    ///
    pub fn close(&mut self) -> Result<()> {
        if !self.closed {
            for raw_evlr in self.header.evlrs().into_iter().map(|evlr| {
                evlr.clone().into_raw(true)
            })
            {
                raw_evlr?.write_to(&mut self.write)?;
            }
            self.write.seek(SeekFrom::Start(0))?;
            self.header.clone().into_raw().and_then(|raw_header| {
                raw_header.write_to(&mut self.write)
            })?;
            self.closed = true;
        }
        Ok(())
    }
}

impl Writer<BufWriter<File>> {
    /// Creates a new writer for a path.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::Writer;
    /// let writer = Writer::from_path("/dev/null", Default::default());
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P, header: Header) -> Result<Writer<BufWriter<File>>> {
        File::create(path).map_err(::Error::from).and_then(|file| {
            Writer::new(BufWriter::new(file), header)
        })
    }
}

impl<W: Seek + Write> Drop for Writer<W> {
    fn drop(&mut self) {
        if !self.closed {
            self.close().expect("Error when dropping the writer");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use {Header, Version};
    use byteorder::{LittleEndian, ReadBytesExt};
    use point::Format;
    use std::io::Cursor;

    fn writer(format: Format, version: Version) -> Writer<Cursor<Vec<u8>>> {
        let mut header = Header::default();
        header.point_format = format;
        header.version = version;
        Writer::new(Cursor::new(Vec::new()), header).unwrap()
    }

    #[test]
    fn las_1_0_point_data_start_signature() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut header = Header::default();
            header.version = (1, 0).into();
            header.push_vlr(Default::default());
            let mut writer = Writer::new(&mut cursor, header).unwrap();
            writer.write(Default::default()).unwrap();
        }
        cursor.set_position(281);
        assert_eq!(0xCCDD, cursor.read_u16::<LittleEndian>().unwrap());
    }

    #[test]
    fn already_closed() {
        let mut writer = Writer::new(Cursor::new(Vec::new()), Default::default()).unwrap();
        writer.close().unwrap();
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_extra_bytes() {
        let format = Format {
            extra_bytes: 1,
            ..Default::default()
        };
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_gps_time() {
        let format = Format::new(1).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_color() {
        let format = Format::new(2).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_nir() {
        let format = Format::new(8).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        let point = Point {
            gps_time: Some(0.),
            color: Some(Default::default()),
            ..Default::default()
        };
        assert!(writer.write(point).is_err());
    }

    #[test]
    fn missing_waveform() {
        let format = Format::new(4).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }
}
<|endoftext|>


<commit_before>// ----------------------------------------------------------------------
// Preserve(Ex, S) holds if ToAddr(Ex) will remain valid for the entirety of
// the scope S.
export public_methods;

impl public_methods for borrowck_ctxt {
    fn preserve(cmt: cmt, opt_scope_id: option<ast::node_id>) -> bckres<()> {
        #debug["preserve(%s)", self.cmt_to_repr(cmt)];
        let _i = indenter();

        alt cmt.cat {
          cat_rvalue | cat_special(_) {
            ok(())
          }
          cat_stack_upvar(cmt) {
            self.preserve(cmt, opt_scope_id)
          }
          cat_local(_) {
            // This should never happen.  Local variables are always lendable,
            // so either `loan()` should be called or there must be some
            // intermediate @ or &---they are not lendable but do not recurse.
            self.tcx.sess.span_bug(
                cmt.span,
                "preserve() called with local");
          }
          cat_arg(_) {
            // This can happen as not all args are lendable (e.g., &&
            // modes).  In that case, the caller guarantees stability.
            // This is basically a deref of a region ptr.
            ok(())
          }
          cat_comp(cmt_base, comp_field(*)) |
          cat_comp(cmt_base, comp_index(*)) |
          cat_comp(cmt_base, comp_tuple) |
          cat_comp(cmt_base, comp_res) {
            // Most embedded components: if the base is stable, the
            // type never changes.
            self.preserve(cmt_base, opt_scope_id)
          }
          cat_comp(cmt1, comp_variant) {
            self.require_imm(cmt, cmt1, opt_scope_id, err_mut_variant)
          }
          cat_deref(cmt1, _, uniq_ptr) {
            self.require_imm(cmt, cmt1, opt_scope_id, err_mut_uniq)
          }
          cat_deref(_, _, region_ptr) {
            // References are always "stable" by induction (when the
            // reference of type &MT was created, the memory must have
            // been stable)
            ok(())
          }
          cat_deref(_, _, unsafe_ptr) {
            // Unsafe pointers are the user's problem
            ok(())
          }
          cat_deref(base, derefs, gc_ptr) {
            // GC'd pointers of type @MT: always stable because we can
            // inc the ref count or keep a GC root as necessary.  We
            // need to insert this id into the root_map, however.
            alt opt_scope_id {
              some(scope_id) {
                #debug["Inserting root map entry for %s: \
                        node %d:%u -> scope %d",
                       self.cmt_to_repr(cmt), base.id,
                       derefs, scope_id];

                let rk = {id: base.id, derefs: derefs};
                self.root_map.insert(rk, scope_id);
                ok(())
              }
              none {
                err({cmt:cmt, code:err_preserve_gc})
              }
            }
          }
          cat_discr(base, alt_id) {
            // Subtle: in an alt, we must ensure that each binding
            // variable remains valid for the duration of the arm in
            // which it appears, presuming that this arm is taken.
            // But it is inconvenient in trans to root something just
            // for one arm.  Therefore, we insert a cat_discr(),
            // basically a special kind of category that says "if this
            // value must be dynamically rooted, root it for the scope
            // `alt_id`.
            //
            // As an example, consider this scenario:
            //
            //    let mut x = @some(3);
            //    alt *x { some(y) {...} none {...} }
            //
            // Technically, the value `x` need only be rooted
            // in the `some` arm.  However, we evaluate `x` in trans
            // before we know what arm will be taken, so we just
            // always root it for the duration of the alt.
            //
            // As a second example, consider *this* scenario:
            //
            //    let x = @mut @some(3);
            //    alt x { @@some(y) {...} @@none {...} }
            //
            // Here again, `x` need only be rooted in the `some` arm.
            // In this case, the value which needs to be rooted is
            // found only when checking which pattern matches: but
            // this check is done before entering the arm.  Therefore,
            // even in this case we just choose to keep the value
            // rooted for the entire alt.  This means the value will be
            // rooted even if the none arm is taken.  Oh well.
            //
            // At first, I tried to optimize the second case to only
            // root in one arm, but the result was suboptimal: first,
            // it interfered with the construction of phi nodes in the
            // arm, as we were adding code to root values before the
            // phi nodes were added.  This could have been addressed
            // with a second basic block.  However, the naive approach
            // also yielded suboptimal results for patterns like:
            //
            //    let x = @mut @...;
            //    alt x { @@some_variant(y) | @@some_other_variant(y) {...} }
            //
            // The reason is that we would root the value once for
            // each pattern and not once per arm.  This is also easily
            // fixed, but it's yet more code for what is really quite
            // the corner case.
            //
            // Nonetheless, if you decide to optimize this case in the
            // future, you need only adjust where the cat_discr()
            // node appears to draw the line between what will be rooted
            // in the *arm* vs the *alt*.

            // current scope must be the arm, which is always a child of alt:
            assert self.tcx.region_map.get(opt_scope_id.get()) == alt_id;

            self.preserve(base, some(alt_id))
          }
        }
    }
}

impl private_methods for borrowck_ctxt {
    fn require_imm(cmt: cmt,
                   cmt1: cmt,
                   opt_scope_id: option<ast::node_id>,
                   code: bckerr_code) -> bckres<()> {
        // Variant contents and unique pointers: must be immutably
        // rooted to a preserved address.
        alt cmt1.mutbl {
          m_mutbl | m_const { err({cmt:cmt, code:code}) }
          m_imm { self.preserve(cmt1, opt_scope_id) }
        }
    }
}
<commit_msg>avoid rooting @ptrs that live in immutable, stable memory<commit_after>// ----------------------------------------------------------------------
// Preserve(Ex, S) holds if ToAddr(Ex) will remain valid for the entirety of
// the scope S.
export public_methods;

impl public_methods for borrowck_ctxt {
    fn preserve(cmt: cmt, opt_scope_id: option<ast::node_id>) -> bckres<()> {
        #debug["preserve(%s)", self.cmt_to_repr(cmt)];
        let _i = indenter();

        alt cmt.cat {
          cat_rvalue | cat_special(_) {
            ok(())
          }
          cat_stack_upvar(cmt) {
            self.preserve(cmt, opt_scope_id)
          }
          cat_local(_) {
            // Normally, local variables are lendable, and so this
            // case should never trigged.  However, if we are
            // preserving an expression like a.b where the field `b`
            // has @ type, then it will recurse to ensure that the `a`
            // is stable to try and avoid rooting the value `a.b`.  In
            // this case, opt_scope_id will be none.
            if opt_scope_id.is_some() {
                self.tcx.sess.span_bug(
                    cmt.span,
                    "preserve() called with local and non-none opt_scope_id");
            }
            ok(())
          }
          cat_arg(_) {
            // This can happen as not all args are lendable (e.g., &&
            // modes).  In that case, the caller guarantees stability.
            // This is basically a deref of a region ptr.
            ok(())
          }
          cat_comp(cmt_base, comp_field(*)) |
          cat_comp(cmt_base, comp_index(*)) |
          cat_comp(cmt_base, comp_tuple) |
          cat_comp(cmt_base, comp_res) {
            // Most embedded components: if the base is stable, the
            // type never changes.
            self.preserve(cmt_base, opt_scope_id)
          }
          cat_comp(cmt_base, comp_variant) {
            self.require_imm(cmt, cmt_base, opt_scope_id, err_mut_variant)
          }
          cat_deref(cmt_base, _, uniq_ptr) {
            self.require_imm(cmt, cmt_base, opt_scope_id, err_mut_uniq)
          }
          cat_deref(_, _, region_ptr) {
            // References are always "stable" by induction (when the
            // reference of type &MT was created, the memory must have
            // been stable)
            ok(())
          }
          cat_deref(_, _, unsafe_ptr) {
            // Unsafe pointers are the user's problem
            ok(())
          }
          cat_deref(base, derefs, gc_ptr) {
            // GC'd pointers of type @MT: if this pointer lives in
            // immutable, stable memory, then everything is fine.  But
            // otherwise we have no guarantee the pointer will stay
            // live, so we must root the pointer (i.e., inc the ref
            // count) for the duration of the loan.
            if base.mutbl == m_imm {
                alt self.preserve(base, none) {
                  ok(()) {ok(())}
                  err(_) {self.attempt_root(cmt, opt_scope_id, base, derefs)}
                }
            } else {
                self.attempt_root(cmt, opt_scope_id, base, derefs)
            }
          }
          cat_discr(base, alt_id) {
            // Subtle: in an alt, we must ensure that each binding
            // variable remains valid for the duration of the arm in
            // which it appears, presuming that this arm is taken.
            // But it is inconvenient in trans to root something just
            // for one arm.  Therefore, we insert a cat_discr(),
            // basically a special kind of category that says "if this
            // value must be dynamically rooted, root it for the scope
            // `alt_id`.
            //
            // As an example, consider this scenario:
            //
            //    let mut x = @some(3);
            //    alt *x { some(y) {...} none {...} }
            //
            // Technically, the value `x` need only be rooted
            // in the `some` arm.  However, we evaluate `x` in trans
            // before we know what arm will be taken, so we just
            // always root it for the duration of the alt.
            //
            // As a second example, consider *this* scenario:
            //
            //    let x = @mut @some(3);
            //    alt x { @@some(y) {...} @@none {...} }
            //
            // Here again, `x` need only be rooted in the `some` arm.
            // In this case, the value which needs to be rooted is
            // found only when checking which pattern matches: but
            // this check is done before entering the arm.  Therefore,
            // even in this case we just choose to keep the value
            // rooted for the entire alt.  This means the value will be
            // rooted even if the none arm is taken.  Oh well.
            //
            // At first, I tried to optimize the second case to only
            // root in one arm, but the result was suboptimal: first,
            // it interfered with the construction of phi nodes in the
            // arm, as we were adding code to root values before the
            // phi nodes were added.  This could have been addressed
            // with a second basic block.  However, the naive approach
            // also yielded suboptimal results for patterns like:
            //
            //    let x = @mut @...;
            //    alt x { @@some_variant(y) | @@some_other_variant(y) {...} }
            //
            // The reason is that we would root the value once for
            // each pattern and not once per arm.  This is also easily
            // fixed, but it's yet more code for what is really quite
            // the corner case.
            //
            // Nonetheless, if you decide to optimize this case in the
            // future, you need only adjust where the cat_discr()
            // node appears to draw the line between what will be rooted
            // in the *arm* vs the *alt*.

            // current scope must be the arm, which is always a child of alt:
            assert self.tcx.region_map.get(opt_scope_id.get()) == alt_id;

            self.preserve(base, some(alt_id))
          }
        }
    }
}

impl private_methods for borrowck_ctxt {
    fn require_imm(cmt: cmt,
                   cmt_base: cmt,
                   opt_scope_id: option<ast::node_id>,
                   code: bckerr_code) -> bckres<()> {
        // Variant contents and unique pointers: must be immutably
        // rooted to a preserved address.
        alt cmt_base.mutbl {
          m_mutbl | m_const { err({cmt:cmt, code:code}) }
          m_imm { self.preserve(cmt_base, opt_scope_id) }
        }
    }

    fn attempt_root(cmt: cmt, opt_scope_id: option<ast::node_id>,
                    base: cmt, derefs: uint) -> bckres<()> {
        alt opt_scope_id {
          some(scope_id) {
            #debug["Inserting root map entry for %s: \
                    node %d:%u -> scope %d",
                   self.cmt_to_repr(cmt), base.id,
                   derefs, scope_id];

            let rk = {id: base.id, derefs: derefs};
            self.root_map.insert(rk, scope_id);
            ok(())
          }
          none {
            err({cmt:cmt, code:err_preserve_gc})
          }
        }
    }
}
<|endoftext|>


<commit_before>use stats::median;
use request_response_matcher::*;

pub mod percentile;

#[derive(PartialEq)]
#[derive(Debug)]
pub struct RequestLogAnalyzerResult {
    pub count: usize,
    pub max: usize,
    pub min: usize,
    pub avg: usize,
    pub median: usize,
    pub percentile90: usize,
}

pub fn analyze(times: &Vec<i64>) -> Option<RequestLogAnalyzerResult> {
    if times.len() == 0 {
        return None;
    }

    let sum: usize = times.iter().sum::<i64>() as usize;
    let avg: usize = sum / times.len();

    let max: usize = *times.iter().max().unwrap() as usize;
    let min: usize = *times.iter().min().unwrap() as usize;

    let percentile90: usize = percentile::percentile(&times, 0.9) as usize;

    let median = median(times.iter().cloned()).unwrap() as usize;

    Some(RequestLogAnalyzerResult {
        count: times.len().into(),
        max: max,
        min: min,
        avg: avg,
        median: median,
        percentile90: percentile90,
    })
}

#[cfg(test)]
mod tests {
    use log_parser::log_events::*;
    use request_response_matcher::*;
    use super::*;

    #[test]
    fn test_analyze() {
        let times: Vec<i64> = vec![1, 10, 100];

        let result = analyze(&times);

        let expected = Some(RequestLogAnalyzerResult {
            count: 3,
            max: 100,
            min: 1,
            avg: 37,
            median: 10,
            percentile90: 100,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_empty() {
        let times = vec![];

        let result = analyze(&times);

        let expected = None;

        assert_eq!(result, expected);
    }
}
<commit_msg>Remove unused import<commit_after>use stats::median;

pub mod percentile;

#[derive(PartialEq)]
#[derive(Debug)]
pub struct RequestLogAnalyzerResult {
    pub count: usize,
    pub max: usize,
    pub min: usize,
    pub avg: usize,
    pub median: usize,
    pub percentile90: usize,
}

pub fn analyze(times: &Vec<i64>) -> Option<RequestLogAnalyzerResult> {
    if times.len() == 0 {
        return None;
    }

    let sum: usize = times.iter().sum::<i64>() as usize;
    let avg: usize = sum / times.len();

    let max: usize = *times.iter().max().unwrap() as usize;
    let min: usize = *times.iter().min().unwrap() as usize;

    let percentile90: usize = percentile::percentile(&times, 0.9) as usize;

    let median = median(times.iter().cloned()).unwrap() as usize;

    Some(RequestLogAnalyzerResult {
        count: times.len().into(),
        max: max,
        min: min,
        avg: avg,
        median: median,
        percentile90: percentile90,
    })
}

#[cfg(test)]
mod tests {
    use log_parser::log_events::*;
    use request_response_matcher::*;
    use super::*;

    #[test]
    fn test_analyze() {
        let times: Vec<i64> = vec![1, 10, 100];

        let result = analyze(&times);

        let expected = Some(RequestLogAnalyzerResult {
            count: 3,
            max: 100,
            min: 1,
            avg: 37,
            median: 10,
            percentile90: 100,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_empty() {
        let times = vec![];

        let result = analyze(&times);

        let expected = None;

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


<commit_before>use std::ffi::CString;
use std::mem;
use libc::size_t;

use {encode, Encode};
use runtime::{Class, Imp, Sel};
use runtime;

/// A type for declaring a new method.
/// `MethodDecl`s are usually created using the `method!` macro.
pub struct MethodDecl {
    /// The method's selector.
    pub sel: Sel,
    /// The method's implementation.
    pub imp: Imp,
    /// The types of the method's arguments.
    pub types: String,
}

/// A type for declaring a new class and adding new methods and ivars to it
/// before registering it.
pub struct ClassDecl {
    cls: *mut Class,
}

impl ClassDecl {
    /// Constructs a `ClassDecl` with the given superclass and name.
    /// Returns `None` if the class couldn't be allocated.
    pub fn new(superclass: &Class, name: &str) -> Option<ClassDecl> {
        let name = CString::from_slice(name.as_bytes());
        let cls = unsafe {
            runtime::objc_allocateClassPair(superclass, name.as_ptr(), 0)
        };
        if cls.is_null() {
            None
        } else {
            Some(ClassDecl { cls: cls })
        }
    }

    /// Adds a method declared with the given `MethodDecl` to self.
    /// Returns true if the method was sucessfully added.
    pub fn add_method(&mut self, method: MethodDecl) -> bool {
        let MethodDecl { sel, imp, types } = method;
        let types = CString::from_vec(types.into_bytes());
        unsafe {
            runtime::class_addMethod(self.cls, sel, imp, types.as_ptr())
        }
    }

    /// Adds an ivar with type `T` and the provided name to self.
    /// Returns true if the ivar was sucessfully added.
    pub fn add_ivar<T: Encode>(&mut self, name: &str) -> bool {
        let name = CString::from_slice(name.as_bytes());
        let types = CString::from_slice(encode::<T>().as_bytes());
        let size = mem::size_of::<T>() as size_t;
        let align = mem::align_of::<T>() as u8;
        unsafe {
            runtime::class_addIvar(self.cls, name.as_ptr(), size, align,
                types.as_ptr())
        }
    }

    /// Registers self, consuming it and returning a reference to the
    /// newly registered `Class`.
    pub fn register(self) -> &'static Class {
        unsafe {
            let cls = self.cls;
            runtime::objc_registerClassPair(cls);
            // Forget self otherwise the class will be disposed in drop
            mem::forget(self);
            &*cls
        }
    }
}

impl Drop for ClassDecl {
    fn drop(&mut self) {
        unsafe {
            runtime::objc_disposeClassPair(self.cls);
        }
    }
}

#[cfg(test)]
mod tests {
    use runtime::{Class, Object};
    use super::ClassDecl;

    #[test]
    fn test_custom_class() {
        let superclass = Class::get("NSObject").unwrap();
        let decl = ClassDecl::new(superclass, "MyObject");
        assert!(decl.is_some());
        let mut decl = decl.unwrap();

        decl.add_ivar::<uint>("_foo");
        decl.add_method(method!(
            (*mut Object)_this, doNothing; {
                ()
            }
        ));
        decl.add_method(method!(
            (&mut Object)this, setFoo:(uint)foo; {
                unsafe {
                    this.set_ivar::<uint>("_foo", foo);
                }
            }
        ));
        decl.add_method(method!(
            (&Object)this, foo -> uint, {
                unsafe {
                    *this.get_ivar::<uint>("_foo")
                }
            }
        ));
        decl.add_method(method!(
            (*mut Object)this, doSomethingWithFoo:(uint)_foo -> *mut Object, {
                this
            }
        ));

        let cls = decl.register();
        unsafe {
            let obj = msg_send![cls, alloc];
            let obj = msg_send![obj, init];

            msg_send![obj, doNothing];
            msg_send![obj, setFoo:13u];
            let result = msg_send![obj, foo] as uint;
            assert!(result == 13);
            let result = msg_send![obj, doSomethingWithFoo:13u];
            assert!(result == obj);

            msg_send![obj, release];
        }
    }
}
<commit_msg>Tested multiple arguments when declaring methods.<commit_after>use std::ffi::CString;
use std::mem;
use libc::size_t;

use {encode, Encode};
use runtime::{Class, Imp, Sel};
use runtime;

/// A type for declaring a new method.
/// `MethodDecl`s are usually created using the `method!` macro.
pub struct MethodDecl {
    /// The method's selector.
    pub sel: Sel,
    /// The method's implementation.
    pub imp: Imp,
    /// The types of the method's arguments.
    pub types: String,
}

/// A type for declaring a new class and adding new methods and ivars to it
/// before registering it.
pub struct ClassDecl {
    cls: *mut Class,
}

impl ClassDecl {
    /// Constructs a `ClassDecl` with the given superclass and name.
    /// Returns `None` if the class couldn't be allocated.
    pub fn new(superclass: &Class, name: &str) -> Option<ClassDecl> {
        let name = CString::from_slice(name.as_bytes());
        let cls = unsafe {
            runtime::objc_allocateClassPair(superclass, name.as_ptr(), 0)
        };
        if cls.is_null() {
            None
        } else {
            Some(ClassDecl { cls: cls })
        }
    }

    /// Adds a method declared with the given `MethodDecl` to self.
    /// Returns true if the method was sucessfully added.
    pub fn add_method(&mut self, method: MethodDecl) -> bool {
        let MethodDecl { sel, imp, types } = method;
        let types = CString::from_vec(types.into_bytes());
        unsafe {
            runtime::class_addMethod(self.cls, sel, imp, types.as_ptr())
        }
    }

    /// Adds an ivar with type `T` and the provided name to self.
    /// Returns true if the ivar was sucessfully added.
    pub fn add_ivar<T: Encode>(&mut self, name: &str) -> bool {
        let name = CString::from_slice(name.as_bytes());
        let types = CString::from_slice(encode::<T>().as_bytes());
        let size = mem::size_of::<T>() as size_t;
        let align = mem::align_of::<T>() as u8;
        unsafe {
            runtime::class_addIvar(self.cls, name.as_ptr(), size, align,
                types.as_ptr())
        }
    }

    /// Registers self, consuming it and returning a reference to the
    /// newly registered `Class`.
    pub fn register(self) -> &'static Class {
        unsafe {
            let cls = self.cls;
            runtime::objc_registerClassPair(cls);
            // Forget self otherwise the class will be disposed in drop
            mem::forget(self);
            &*cls
        }
    }
}

impl Drop for ClassDecl {
    fn drop(&mut self) {
        unsafe {
            runtime::objc_disposeClassPair(self.cls);
        }
    }
}

#[cfg(test)]
mod tests {
    use runtime::{Class, Object};
    use super::ClassDecl;

    #[test]
    fn test_custom_class() {
        let superclass = Class::get("NSObject").unwrap();
        let decl = ClassDecl::new(superclass, "MyObject");
        assert!(decl.is_some());
        let mut decl = decl.unwrap();

        decl.add_ivar::<uint>("_foo");
        decl.add_method(method!(
            (*mut Object)_this, doNothing; {
                ()
            }
        ));
        decl.add_method(method!(
            (&mut Object)this, setFoo:(uint)foo, bar:(uint)_bar; {
                unsafe {
                    this.set_ivar::<uint>("_foo", foo);
                }
            }
        ));
        decl.add_method(method!(
            (&Object)this, foo -> uint, {
                unsafe {
                    *this.get_ivar::<uint>("_foo")
                }
            }
        ));
        decl.add_method(method!(
            (*mut Object)this, doSomethingWithFoo:(uint)_foo, bar:(uint)_bar -> *mut Object, {
                this
            }
        ));

        let cls = decl.register();
        unsafe {
            let obj = msg_send![cls, alloc];
            let obj = msg_send![obj, init];

            msg_send![obj, doNothing];
            msg_send![obj, setFoo:13u bar:0u];
            let result = msg_send![obj, foo] as uint;
            assert!(result == 13);
            let result = msg_send![obj, doSomethingWithFoo:13u bar:0u];
            assert!(result == obj);

            msg_send![obj, release];
        }
    }
}
<|endoftext|>


<commit_before>/// Lazy iterator over bits of a vector of bytes, starting with the LSB
/// (least-significat bit) of the first element of the vector.
pub struct BitIterator<'a> {
    object: &'a Vec<u8>,
    current_byte: usize,
    current_bit: usize
}

impl<'a> BitIterator<'a> {
    pub fn new(obj: &'a Vec<u8>) -> BitIterator {
        BitIterator { object: obj, current_byte: 0, current_bit: 0 }
    }
}

impl<'a> Iterator for BitIterator<'a> {
    type Item = u8;

    fn next(&mut self) -> Option<u8> {
        let result = self.object[self.current_byte] >> self.current_bit & 0x1;

        if self.current_bit + 1 == ::std::u8::BITS as usize {
            self.current_byte += 1;
        }
        self.current_bit = (self.current_bit + 1) % ::std::u8::BITS as usize;

        if self.current_byte == self.object.len() {
            return None;
        } else {
            return Some(result);
        }
    }
}

#[test]
fn test_iterator() {
    let bytes = vec!(0xCA, 0xFE);
    let expected_bits = vec!(0,1,0,1, 0,0,1,1, 0,1,1,1, 1,1,1,1);
    let mut i = 0;

    for bit in BitIterator::new(&bytes) {
        println!("{} == {}", bit, expected_bits[i]);
        assert_eq!(bit, expected_bits[i]);
        i += 1;
    }
}
<commit_msg>Replace unstable `std::u8::BITS` with a constant.<commit_after>/// Lazy iterator over bits of a vector of bytes, starting with the LSB
/// (least-significat bit) of the first element of the vector.
pub struct BitIterator<'a> {
    object: &'a Vec<u8>,
    current_byte: usize,
    current_bit: usize
}

impl<'a> BitIterator<'a> {
    pub fn new(obj: &'a Vec<u8>) -> BitIterator {
        BitIterator { object: obj, current_byte: 0, current_bit: 0 }
    }
}

impl<'a> Iterator for BitIterator<'a> {
    type Item = u8;

    fn next(&mut self) -> Option<u8> {
        const U8BITS: usize = 8;
        let result = self.object[self.current_byte] >> self.current_bit & 0x1;

        if self.current_bit + 1 == U8BITS {
            self.current_byte += 1;
        }
        self.current_bit = (self.current_bit + 1) % U8BITS;

        if self.current_byte == self.object.len() {
            return None;
        } else {
            return Some(result);
        }
    }
}

#[test]
fn test_iterator() {
    let bytes = vec!(0xCA, 0xFE);
    let expected_bits = vec!(0,1,0,1, 0,0,1,1, 0,1,1,1, 1,1,1,1);
    let mut i = 0;

    for bit in BitIterator::new(&bytes) {
        println!("{} == {}", bit, expected_bits[i]);
        assert_eq!(bit, expected_bits[i]);
        i += 1;
    }
}
<|endoftext|>


<commit_before>use std::io::Write;

use rmp::encode::write_bool;
use rmp::encode::write_nil;
use rmp::encode::write_sint;
use rmp::encode::{write_uint, write_f32, write_f64, write_str, write_bin, write_array_len, write_map_len, write_ext_meta};

use ValueRef;
use super::Error;

/// Encodes and attempts to write the given non-owning ValueRef into the Write.
///
/// # Errors
///
/// This function returns Error with an underlying I/O error if unable to properly write entire
/// value. Interruption errors are handled internally by silent operation restarting.
///
/// # Examples
/// ```
/// use rmpv::ValueRef;
/// use rmpv::encode::write_value_ref;
///
/// let mut buf = Vec::new();
/// let val = ValueRef::String("le message");
///
/// write_value_ref(&mut buf, &val).unwrap();
/// assert_eq!(vec![0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65], buf);
/// ```
pub fn write_value_ref<W>(wr: &mut W, val: &ValueRef) -> Result<(), Error>
    where W: Write
{
    match *val {
        ValueRef::Nil => {
            write_nil(wr).map_err(|err| Error::InvalidMarkerWrite(err))?;
        }
        ValueRef::Boolean(val) => {
            write_bool(wr, val).map_err(|err| Error::InvalidMarkerWrite(err))?;
        }
        ValueRef::U64(val) => {
            write_uint(wr, val)?;
        }
        ValueRef::I64(val) => {
            write_sint(wr, val)?;
        }
        ValueRef::F32(val) => {
            write_f32(wr, val)?;
        }
        ValueRef::F64(val) => {
            write_f64(wr, val)?;
        }
        ValueRef::String(val) => {
            write_str(wr, val)?;
        }
        ValueRef::Binary(val) => {
            write_bin(wr, val)?;
        }
        ValueRef::Array(ref vec) => {
            write_array_len(wr, vec.len() as u32)?;
            for v in vec {
                write_value_ref(wr, v)?;
            }
        }
        ValueRef::Map(ref map) => {
            write_map_len(wr, map.len() as u32)?;
            for &(ref key, ref val) in map {
                write_value_ref(wr, key)?;
                write_value_ref(wr, val)?;
            }
        }
        ValueRef::Ext(ty, data) => {
            write_ext_meta(wr, data.len() as u32, ty)?;
            wr.write_all(data).map_err(|err| Error::InvalidDataWrite(err))?;
        }
    }

    Ok(())
}
<commit_msg>refactor: tiny includes clean up<commit_after>use std::io::Write;

use rmp::encode::{write_bool, write_nil, write_sint, write_uint, write_f32, write_f64, write_str,
                  write_bin, write_array_len, write_map_len, write_ext_meta};

use ValueRef;
use super::Error;

/// Encodes and attempts to write the given non-owning ValueRef into the Write.
///
/// # Errors
///
/// This function returns Error with an underlying I/O error if unable to properly write entire
/// value. Interruption errors are handled internally by silent operation restarting.
///
/// # Examples
/// ```
/// use rmpv::ValueRef;
/// use rmpv::encode::write_value_ref;
///
/// let mut buf = Vec::new();
/// let val = ValueRef::String("le message");
///
/// write_value_ref(&mut buf, &val).unwrap();
/// assert_eq!(vec![0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65], buf);
/// ```
pub fn write_value_ref<W>(wr: &mut W, val: &ValueRef) -> Result<(), Error>
    where W: Write
{
    match *val {
        ValueRef::Nil => {
            write_nil(wr).map_err(|err| Error::InvalidMarkerWrite(err))?;
        }
        ValueRef::Boolean(val) => {
            write_bool(wr, val).map_err(|err| Error::InvalidMarkerWrite(err))?;
        }
        ValueRef::U64(val) => {
            write_uint(wr, val)?;
        }
        ValueRef::I64(val) => {
            write_sint(wr, val)?;
        }
        ValueRef::F32(val) => {
            write_f32(wr, val)?;
        }
        ValueRef::F64(val) => {
            write_f64(wr, val)?;
        }
        ValueRef::String(val) => {
            write_str(wr, val)?;
        }
        ValueRef::Binary(val) => {
            write_bin(wr, val)?;
        }
        ValueRef::Array(ref vec) => {
            write_array_len(wr, vec.len() as u32)?;
            for v in vec {
                write_value_ref(wr, v)?;
            }
        }
        ValueRef::Map(ref map) => {
            write_map_len(wr, map.len() as u32)?;
            for &(ref key, ref val) in map {
                write_value_ref(wr, key)?;
                write_value_ref(wr, val)?;
            }
        }
        ValueRef::Ext(ty, data) => {
            write_ext_meta(wr, data.len() as u32, ty)?;
            wr.write_all(data).map_err(|err| Error::InvalidDataWrite(err))?;
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::cmp::Eq;
use std::fmt::Display;
use std::iter::FromIterator;

trait Parser<T: Display + Eq, E>: Sized {
    fn preview(&self) -> Option<&T>;
    fn consume(&mut self) -> Option<T>;
    fn current_pos(&self) -> (i32, i32);
    fn error<S: Into<String>>(&self, message: S) -> E;

    fn export(&self) -> Self;
    fn import(&mut self, backup: Self);

    fn next(&mut self) -> Result<T, E> {
        self.consume().ok_or(self.error("unexpected eof"))
    }

    fn predicate<F>(&mut self, pred: F) -> Result<T, E>
        where F: Fn(&T) -> bool
    {
        let x = try!(self.next());
        if pred(&x) {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}", x)))
        }
    }

    fn atom(&mut self, expected: T) -> Result<T, E> {
        let x = try!(self.next());
        if x == expected {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}, expected {}", x, expected)))
        }
    }

    fn string<S, O>(&mut self, s: S) -> Result<O, E>
        where S: IntoIterator<Item = T>,
              O: FromIterator<T>
    {
        let mut res: Vec<T> = Vec::new();
        for c in s {
            match self.atom(c) {
                Ok(x) => res.push(x),
                Err(err) => return Err(err),
            }
        }
        Ok(O::from_iter(res))
    }

    fn try<O, F>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<O, E>
    {
        let backup = self.export();
        parser(self).map_err(|x| {
                                 self.import(backup);
                                 x
                             })
    }

    fn choose<O>(&mut self, parsers: &[&Fn(&mut Self) -> Result<O, E>]) -> Result<O, E> {
        for parser in parsers {
            match self.try(parser) {
                Ok(x) => return Ok(x),
                Err(_) => continue,
            }
        }

        Err(self.error(match self.preview() {
                           Some(x) => format!("unexpected token {}", x),
                           None => String::from("unexpected eof"),
                       }))
    }

    fn many<X, F, O>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<X, E>,
              O: FromIterator<X>
    {
        let mut res: Vec<X> = Vec::new();
        loop {
            match self.try(&parser) {
                Ok(x) => res.push(x),
                Err(_) => break,
            }
        }
        Ok(O::from_iter(res))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::vec_deque::VecDeque;

    struct TP {
        input: VecDeque<i32>,
    }

    impl TP {
        fn new(input: &[i32]) -> TP {
            TP { input: VecDeque::from(input.to_vec()) }
        }
    }

    impl Parser<i32, String> for TP {
        fn consume(&mut self) -> Option<i32> {
            self.input.pop_front()
        }

        fn preview(&self) -> Option<&i32> {
            self.input.front()
        }

        fn current_pos(&self) -> (i32, i32) {
            (0, 0)
        }

        fn error<S: Into<String>>(&self, message: S) -> String {
            message.into()
        }

        fn export(&self) -> Self {
            TP { input: self.input.clone() }
        }

        fn import(&mut self, backup: Self) {
            self.input = backup.input;
        }
    }

    type TPR = Result<Vec<i32>, String>;

    fn err<T>(m: &str) -> Result<T, String> {
        Err(String::from(m))
    }

    #[test]
    fn next_success() {
        let mut p = TP::new(&[1, 2, 3]);
        assert_eq!(p.next(), Ok(1));
        assert_eq!(p.next(), Ok(2));
        assert_eq!(p.next(), Ok(3));
    }

    #[test]
    fn next_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.next(), err("unexpected eof"));
    }

    #[test]
    fn predicate_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(2));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(4));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(6));
    }

    #[test]
    fn predicate_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected eof"));
    }

    #[test]
    fn predicate_fail_not_satisfy() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected token 3"));
    }

    #[test]
    fn atom_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.atom(2), Ok(2));
        assert_eq!(p.atom(4), Ok(4));
        assert_eq!(p.atom(6), Ok(6));
    }

    #[test]
    fn atom_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.atom(2), err("unexpected eof"));
    }

    #[test]
    fn atom_fail_not_expected() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.atom(3), Ok(3));
        assert_eq!(p.atom(4), err("unexpected token 5, expected 4"));
    }

    #[test]
    fn string_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.string(vec![2, 4, 6]), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn string_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR, err("unexpected eof"));
    }

    #[test]
    fn string_fail_not_expected() {
        let mut p = TP::new(&[2, 5, 6]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR,
                   err("unexpected token 5, expected 4"));
    }

    #[test]
    fn try_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn try_fail_recover() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 7])) as TPR,
                   err("unexpected token 6, expected 7"));
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn choose_success() {
        let mut p = TP::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 7]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![1, 2, 3]));
    }

    #[test]
    fn choose_success_with_recover() {
        let mut p = TP::new(&[4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![4, 5, 6]));
    }

    #[test]
    fn choose_fail_no_match() {
        let mut p = TP::new(&[5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected token 5"));
    }

    #[test]
    fn choose_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected eof"));
    }

    #[test]
    fn many_success() {
        let lt5 = |p: &mut TP| -> Result<i32, String> { p.predicate(|x| *x < 5) };

        assert_eq!(TP::new(&[1, 2, 3, 4]).many(&lt5), Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[1, 2, 3, 4, 5, 6, 7, 8]).many(&lt5),
                   Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[4, 5, 6, 7, 8]).many(&lt5), Ok(vec![4]));
        assert_eq!(TP::new(&[5, 6, 7, 8]).many(&lt5), Ok(vec![]));
    }
}
<commit_msg>Add unimplemented many1 and its tests<commit_after>use std::cmp::Eq;
use std::fmt::Display;
use std::iter::FromIterator;

trait Parser<T: Display + Eq, E>: Sized {
    fn preview(&self) -> Option<&T>;
    fn consume(&mut self) -> Option<T>;
    fn current_pos(&self) -> (i32, i32);
    fn error<S: Into<String>>(&self, message: S) -> E;

    fn export(&self) -> Self;
    fn import(&mut self, backup: Self);

    fn next(&mut self) -> Result<T, E> {
        self.consume().ok_or(self.error("unexpected eof"))
    }

    fn predicate<F>(&mut self, pred: F) -> Result<T, E>
        where F: Fn(&T) -> bool
    {
        let x = try!(self.next());
        if pred(&x) {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}", x)))
        }
    }

    fn atom(&mut self, expected: T) -> Result<T, E> {
        let x = try!(self.next());
        if x == expected {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}, expected {}", x, expected)))
        }
    }

    fn string<S, O>(&mut self, s: S) -> Result<O, E>
        where S: IntoIterator<Item = T>,
              O: FromIterator<T>
    {
        let mut res: Vec<T> = Vec::new();
        for c in s {
            match self.atom(c) {
                Ok(x) => res.push(x),
                Err(err) => return Err(err),
            }
        }
        Ok(O::from_iter(res))
    }

    fn try<O, F>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<O, E>
    {
        let backup = self.export();
        parser(self).map_err(|x| {
                                 self.import(backup);
                                 x
                             })
    }

    fn choose<O>(&mut self, parsers: &[&Fn(&mut Self) -> Result<O, E>]) -> Result<O, E> {
        for parser in parsers {
            match self.try(parser) {
                Ok(x) => return Ok(x),
                Err(_) => continue,
            }
        }

        Err(self.error(match self.preview() {
                           Some(x) => format!("unexpected token {}", x),
                           None => String::from("unexpected eof"),
                       }))
    }

    fn many<X, F, O>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<X, E>,
              O: FromIterator<X>
    {
        let mut res: Vec<X> = Vec::new();
        loop {
            match self.try(&parser) {
                Ok(x) => res.push(x),
                Err(_) => break,
            }
        }
        Ok(O::from_iter(res))
    }

    fn many1<X, F, O>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<X, E>,
              O: FromIterator<X>
    {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::vec_deque::VecDeque;

    struct TP {
        input: VecDeque<i32>,
    }

    impl TP {
        fn new(input: &[i32]) -> TP {
            TP { input: VecDeque::from(input.to_vec()) }
        }
    }

    impl Parser<i32, String> for TP {
        fn consume(&mut self) -> Option<i32> {
            self.input.pop_front()
        }

        fn preview(&self) -> Option<&i32> {
            self.input.front()
        }

        fn current_pos(&self) -> (i32, i32) {
            (0, 0)
        }

        fn error<S: Into<String>>(&self, message: S) -> String {
            message.into()
        }

        fn export(&self) -> Self {
            TP { input: self.input.clone() }
        }

        fn import(&mut self, backup: Self) {
            self.input = backup.input;
        }
    }

    type TPR = Result<Vec<i32>, String>;

    fn err<T>(m: &str) -> Result<T, String> {
        Err(String::from(m))
    }

    #[test]
    fn next_success() {
        let mut p = TP::new(&[1, 2, 3]);
        assert_eq!(p.next(), Ok(1));
        assert_eq!(p.next(), Ok(2));
        assert_eq!(p.next(), Ok(3));
    }

    #[test]
    fn next_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.next(), err("unexpected eof"));
    }

    #[test]
    fn predicate_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(2));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(4));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(6));
    }

    #[test]
    fn predicate_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected eof"));
    }

    #[test]
    fn predicate_fail_not_satisfy() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected token 3"));
    }

    #[test]
    fn atom_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.atom(2), Ok(2));
        assert_eq!(p.atom(4), Ok(4));
        assert_eq!(p.atom(6), Ok(6));
    }

    #[test]
    fn atom_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.atom(2), err("unexpected eof"));
    }

    #[test]
    fn atom_fail_not_expected() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.atom(3), Ok(3));
        assert_eq!(p.atom(4), err("unexpected token 5, expected 4"));
    }

    #[test]
    fn string_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.string(vec![2, 4, 6]), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn string_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR, err("unexpected eof"));
    }

    #[test]
    fn string_fail_not_expected() {
        let mut p = TP::new(&[2, 5, 6]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR,
                   err("unexpected token 5, expected 4"));
    }

    #[test]
    fn try_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn try_fail_recover() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 7])) as TPR,
                   err("unexpected token 6, expected 7"));
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn choose_success() {
        let mut p = TP::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 7]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![1, 2, 3]));
    }

    #[test]
    fn choose_success_with_recover() {
        let mut p = TP::new(&[4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![4, 5, 6]));
    }

    #[test]
    fn choose_fail_no_match() {
        let mut p = TP::new(&[5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected token 5"));
    }

    #[test]
    fn choose_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected eof"));
    }

    #[test]
    fn many_success() {
        let lt5 = |p: &mut TP| -> Result<i32, String> { p.predicate(|x| *x < 5) };

        assert_eq!(TP::new(&[1, 2, 3, 4]).many(&lt5), Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[1, 2, 3, 4, 5, 6, 7, 8]).many(&lt5),
                   Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[4, 5, 6, 7, 8]).many(&lt5), Ok(vec![4]));
        assert_eq!(TP::new(&[5, 6, 7, 8]).many(&lt5), Ok(vec![]));
    }

    #[test]
    fn many1_success() {
        let lt5 = |p: &mut TP| -> Result<i32, String> { p.predicate(|x| *x < 5) };

        assert_eq!(TP::new(&[1, 2, 3, 4]).many1(&lt5), Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[1, 2, 3, 4, 5, 6, 7, 8]).many1(&lt5),
                   Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[4, 5, 6, 7, 8]).many1(&lt5), Ok(vec![4]));
    }

    #[test]
    fn many1_fail() {
        let lt5 = |p: &mut TP| -> Result<i32, String> { p.predicate(|x| *x < 5) };

        assert_eq!(TP::new(&[5, 6, 7, 8]).many1(&lt5) as TPR,
                   err("unexpected token 5"));
    }
}
<|endoftext|>


<commit_before>use rustc_errors::Applicability;
use rustc_hir::{
    intravisit::{walk_expr, NestedVisitorMap, Visitor},
    Expr, ExprKind,
};
use rustc_lint::LateContext;
use rustc_middle::hir::map::Map;
use rustc_span::source_map::Span;

use if_chain::if_chain;

use crate::utils::{has_iter_method, match_trait_method, paths, snippet, span_lint_and_then};

use super::EXCESSIVE_FOR_EACH;

pub(super) fn lint(cx: &LateContext<'_>, expr: &'tcx Expr<'_>, args: &[&[Expr<'_>]]) {
    if args.len() < 2 {
        return;
    }

    let for_each_args = args[0];
    if for_each_args.len() < 2 {
        return;
    }
    let for_each_receiver = &for_each_args[0];
    let for_each_arg = &for_each_args[1];
    let iter_receiver = &args[1][0];

    if_chain! {
        if has_iter_method(cx, cx.typeck_results().expr_ty(iter_receiver)).is_some();
        if match_trait_method(cx, expr, &paths::ITERATOR);
        if let ExprKind::Closure(_, _, body_id, ..) = for_each_arg.kind;
        let body = cx.tcx.hir().body(body_id);
        if let ExprKind::Block(..) = body.value.kind;
        then {
            let mut ret_collector = RetCollector::new();
            ret_collector.visit_expr(&body.value);

            // Skip the lint if `return` is used in `Loop` in order not to suggest using `'label`.
            if ret_collector.ret_in_loop {
                return;
            }

            let sugg = format!(
                "for {} in {} {{ .. }}",
                snippet(cx, body.params[0].pat.span, ""),
                snippet(cx, for_each_receiver.span, "")
            );

            span_lint_and_then(
                cx,
                EXCESSIVE_FOR_EACH,
                expr.span,
                "excessive use of `for_each`",
                |diag| {
                    diag.span_suggestion(expr.span, "try", sugg, Applicability::HasPlaceholders);
                    for span in ret_collector.spans {
                        diag.span_note(span, "change `return` to `continue` in the loop body");
                    }
                }
            )
        }
    }
}

/// This type plays two roles.
/// 1. Collect spans of `return` in the closure body.
/// 2. Detect use of `return` in `Loop` in the closure body.
struct RetCollector {
    spans: Vec<Span>,
    ret_in_loop: bool,

    loop_depth: u16,
}

impl RetCollector {
    fn new() -> Self {
        Self {
            spans: Vec::new(),
            ret_in_loop: false,
            loop_depth: 0,
        }
    }
}

impl<'tcx> Visitor<'tcx> for RetCollector {
    type Map = Map<'tcx>;

    fn visit_expr(&mut self, expr: &Expr<'_>) {
        match expr.kind {
            ExprKind::Ret(..) => {
                if self.loop_depth > 0 && !self.ret_in_loop {
                    self.ret_in_loop = true
                }

                self.spans.push(expr.span)
            },

            ExprKind::Loop(..) => {
                self.loop_depth += 1;
                walk_expr(self, expr);
                self.loop_depth -= 1;
                return;
            },

            _ => {},
        }

        walk_expr(self, expr);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }
}
<commit_msg>Add comments to clarify why RetCollector is needed<commit_after>use rustc_errors::Applicability;
use rustc_hir::{
    intravisit::{walk_expr, NestedVisitorMap, Visitor},
    Expr, ExprKind,
};
use rustc_lint::LateContext;
use rustc_middle::hir::map::Map;
use rustc_span::source_map::Span;

use if_chain::if_chain;

use crate::utils::{has_iter_method, match_trait_method, paths, snippet, span_lint_and_then};

use super::EXCESSIVE_FOR_EACH;

pub(super) fn lint(cx: &LateContext<'_>, expr: &'tcx Expr<'_>, args: &[&[Expr<'_>]]) {
    if args.len() < 2 {
        return;
    }

    let for_each_args = args[0];
    if for_each_args.len() < 2 {
        return;
    }
    let for_each_receiver = &for_each_args[0];
    let for_each_arg = &for_each_args[1];
    let iter_receiver = &args[1][0];

    if_chain! {
        if has_iter_method(cx, cx.typeck_results().expr_ty(iter_receiver)).is_some();
        if match_trait_method(cx, expr, &paths::ITERATOR);
        if let ExprKind::Closure(_, _, body_id, ..) = for_each_arg.kind;
        let body = cx.tcx.hir().body(body_id);
        if let ExprKind::Block(..) = body.value.kind;
        then {
            let mut ret_collector = RetCollector::new();
            ret_collector.visit_expr(&body.value);

            // Skip the lint if `return` is used in `Loop` in order not to suggest using `'label`.
            if ret_collector.ret_in_loop {
                return;
            }

            let sugg = format!(
                "for {} in {} {{ .. }}",
                snippet(cx, body.params[0].pat.span, ""),
                snippet(cx, for_each_receiver.span, "")
            );

            span_lint_and_then(
                cx,
                EXCESSIVE_FOR_EACH,
                expr.span,
                "excessive use of `for_each`",
                |diag| {
                    diag.span_suggestion(expr.span, "try", sugg, Applicability::HasPlaceholders);
                    for span in ret_collector.spans {
                        diag.span_note(span, "change `return` to `continue` in the loop body");
                    }
                }
            )
        }
    }
}

/// This type plays two roles.
/// 1. Collect spans of `return` in the closure body.
/// 2. Detect use of `return` in `Loop` in the closure body.
///
/// NOTE: The functionality of this type is similar to
/// [`crate::utilts::visitors::find_all_ret_expressions`], but we can't use
/// `find_all_ret_expressions` instead of this type. The reasons are:
/// 1. `find_all_ret_expressions` passes the argument of `ExprKind::Ret` to a callback, but what we
///    need here is `ExprKind::Ret` itself.
/// 2. We can't trace current loop depth with `find_all_ret_expressions`.
struct RetCollector {
    spans: Vec<Span>,
    ret_in_loop: bool,

    loop_depth: u16,
}

impl RetCollector {
    fn new() -> Self {
        Self {
            spans: Vec::new(),
            ret_in_loop: false,
            loop_depth: 0,
        }
    }
}

impl<'tcx> Visitor<'tcx> for RetCollector {
    type Map = Map<'tcx>;

    fn visit_expr(&mut self, expr: &Expr<'_>) {
        match expr.kind {
            ExprKind::Ret(..) => {
                if self.loop_depth > 0 && !self.ret_in_loop {
                    self.ret_in_loop = true
                }

                self.spans.push(expr.span)
            },

            ExprKind::Loop(..) => {
                self.loop_depth += 1;
                walk_expr(self, expr);
                self.loop_depth -= 1;
                return;
            },

            _ => {},
        }

        walk_expr(self, expr);
    }

    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }
}
<|endoftext|>