<commit_before>//! Read las points.
//!
//! If you're reading any significant number of points, you'll want to make sure you're using a
//! `BufRead` instead of just a `Read`:
//!
//! ```
//! use std::fs::File;
//! use std::io::BufReader;
//! use las::Reader;
//!
//! let read = BufReader::new(File::open("tests/data/autzen.las").unwrap());
//! let reader = Reader::new(read).unwrap();
//! ```
//!
//! `Reader::from_path` does this for you:
//!
//! ```
//! use las::Reader;
//! let reader = Reader::from_path("tests/data/autzen.las").unwrap();
//! ```
//!
//! Ccompressed files are supported when using the feature "laz":
//!
//! ```
//! use las::Reader;
//! if cfg!(feature = "laz") {
//!  assert!(Reader::from_path("tests/data/autzen.laz").is_ok());
//! } else {
//!  assert!(Reader::from_path("tests/data/autzen.laz").is_err());
//! }
//!
//! ```
//!
//! Use `Reader::read` to read one point, and `Reader::points` to get an iterator over
//! `Result<Point>`:
//!
//! ```
//! use las::{Read, Reader};
//! let mut reader = Reader::from_path("tests/data/autzen.las").unwrap();
//! let first_point = reader.read().unwrap().unwrap();
//! let the_rest = reader.points().map(|r| r.unwrap()).collect::<Vec<_>>();
//! ```

use std::fs::File;
use std::io::{BufReader, Seek, SeekFrom};
use std::path::Path;

#[cfg(feature = "laz")]
use compression::CompressedPointReader;

use std::{cmp::Ordering, fmt::Debug};
use thiserror::Error;
use {raw, Builder, Header, Point, Result, Vlr};

/// Error while reading.
#[derive(Error, Clone, Copy, Debug)]
pub enum Error {
    /// The offset to the point data was too small.
    #[error("offset to the point data is too small: {0}")]
    OffsetToPointDataTooSmall(u32),

    /// The offset to the start of the evlrs is too small.
    #[error("offset to the start of the evlrs is too small: {0}")]
    OffsetToEvlrsTooSmall(u64),
}

#[inline]
pub(crate) fn read_point_from<R: std::io::Read>(
    mut source: &mut R,
    header: &Header,
) -> Result<Point> {
    let point = raw::Point::read_from(&mut source, header.point_format())
        .map(|raw_point| Point::new(raw_point, header.transforms()));
    point
}

/// Trait to specify behaviour a a PointReader
pub(crate) trait PointReader: Debug + Send {
    fn read_next(&mut self) -> Option<Result<Point>>;
    fn seek(&mut self, position: u64) -> Result<()>;
    fn header(&self) -> &Header;
}

/// An iterator over of the points in a `Reader`.
///
/// This struct is generally created by calling `points()` on `Reader`.
#[derive(Debug)]
pub struct PointIterator<'a> {
    point_reader: &'a mut dyn PointReader,
}

impl<'a> Iterator for PointIterator<'a> {
    type Item = Result<Point>;

    fn next(&mut self) -> Option<Self::Item> {
        self.point_reader.read_next()
    }
}

#[derive(Debug)]
struct UncompressedPointReader<R: std::io::Read + Seek> {
    source: R,
    header: Header,
    offset_to_point_data: u64,
    /// index of the last point read
    last_point_idx: u64,
}

impl<R: std::io::Read + Seek + Debug + Send> PointReader for UncompressedPointReader<R> {
    fn read_next(&mut self) -> Option<Result<Point>> {
        if self.last_point_idx < self.header.number_of_points() {
            self.last_point_idx += 1;
            Some(read_point_from(&mut self.source, &self.header))
        } else {
            None
        }
    }

    fn seek(&mut self, position: u64) -> Result<()> {
        self.last_point_idx = position;
        self.source.seek(SeekFrom::Start(
            self.offset_to_point_data + position * u64::from(self.header.point_format().len()),
        ))?;
        Ok(())
    }

    fn header(&self) -> &Header {
        &self.header
    }
}

/// A trait for objects which read LAS data.
pub trait Read {
    /// Returns a reference to this reader's header.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::{Read, Reader};
    /// let reader = Reader::from_path("tests/data/autzen.las").unwrap();
    /// let header = reader.header();
    /// ```
    fn header(&self) -> &Header;

    /// Reads a point.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::{Read, Reader};
    /// let mut reader = Reader::from_path("tests/data/autzen.las").unwrap();
    /// let point = reader.read().unwrap().unwrap();
    /// ```
    fn read(&mut self) -> Option<Result<Point>>;

    /// Seeks to the given point number, zero-indexed.
    ///
    /// Note that seeking on compressed (LAZ) data can be expensive as the reader
    /// will have to seek to the closest chunk start and decompress all points up until
    /// the point seeked to.
    ///
    ///
    /// # Examples
    ///
    /// ```
    /// use las::{Read, Reader};
    /// let mut reader = Reader::from_path("tests/data/autzen.las").unwrap();
    /// reader.seek(1).unwrap(); // <- seeks to the second point
    /// let the_second_point = reader.read().unwrap().unwrap();
    /// ```
    fn seek(&mut self, position: u64) -> Result<()>;

    /// Returns an iterator over this reader's points.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::{Read, Reader};
    /// let mut reader = Reader::from_path("tests/data/autzen.las").unwrap();
    /// let points = reader.points().collect::<Result<Vec<_>, _>>().unwrap();
    /// ```
    fn points(&mut self) -> PointIterator;
}

/// Reads LAS data.
#[derive(Debug)]
pub struct Reader {
    point_reader: Box<dyn PointReader>,
}

impl Reader {
    /// Creates a new reader.
    ///
    /// This does *not* wrap the `Read` in a `BufRead`, so if you're concered about performance you
    /// should do that wrapping yourself (or use `from_path`).
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::BufReader;
    /// use std::fs::File;
    /// # use las::Reader;
    /// let file = File::open("tests/data/autzen.las").unwrap();
    /// let reader = Reader::new(BufReader::new(file)).unwrap();
    /// ```
    pub fn new<R: std::io::Read + Seek + Send + Debug + 'static>(mut read: R) -> Result<Reader> {
        use std::io::Read;

        let raw_header = raw::Header::read_from(&mut read)?;
        let mut position = u64::from(raw_header.header_size);
        let number_of_variable_length_records = raw_header.number_of_variable_length_records;
        let offset_to_point_data = u64::from(raw_header.offset_to_point_data);
        let offset_to_end_of_points = raw_header.offset_to_end_of_points();
        let evlr = raw_header.evlr;

        let mut builder = Builder::new(raw_header)?;

        if !cfg!(feature = "laz") && builder.point_format.is_compressed {
            return Err(::Error::Laszip);
        }

        for _ in 0..number_of_variable_length_records {
            let vlr = raw::Vlr::read_from(&mut read, false).map(Vlr::new)?;
            position += vlr.len(false) as u64;
            builder.vlrs.push(vlr);
        }
        match position.cmp(&offset_to_point_data) {
            Ordering::Less => {
                read.by_ref()
                    .take(offset_to_point_data - position)
                    .read_to_end(&mut builder.vlr_padding)?;
            }
            Ordering::Equal => {} // pass
            Ordering::Greater => {
                return Err(Error::OffsetToPointDataTooSmall(offset_to_point_data as u32).into())
            }
        }

        read.seek(SeekFrom::Start(offset_to_end_of_points))?;
        if let Some(evlr) = evlr {
            match evlr.start_of_first_evlr.cmp(&offset_to_end_of_points) {
                Ordering::Less => {
                    return Err(Error::OffsetToEvlrsTooSmall(evlr.start_of_first_evlr).into())
                }
                Ordering::Equal => {} // pass
                Ordering::Greater => {
                    let n = evlr.start_of_first_evlr - offset_to_end_of_points;
                    read.by_ref()
                        .take(n)
                        .read_to_end(&mut builder.point_padding)?;
                }
            }
            builder
                .evlrs
                .push(raw::Vlr::read_from(&mut read, true).map(Vlr::new)?);
        }

        read.seek(SeekFrom::Start(offset_to_point_data))?;

        let header = builder.into_header()?;

        #[cfg(feature = "laz")]
        {
            if header.point_format().is_compressed {
                Ok(Reader {
                    point_reader: Box::new(CompressedPointReader::new(read, header)?),
                })
            } else {
                Ok(Reader {
                    point_reader: Box::new(UncompressedPointReader {
                        source: read,
                        header,
                        offset_to_point_data,
                        last_point_idx: 0,
                    }),
                })
            }
        }
        #[cfg(not(feature = "laz"))]
        {
            Ok(Reader {
                point_reader: Box::new(UncompressedPointReader {
                    source: read,
                    header,
                    offset_to_point_data,
                    last_point_idx: 0,
                }),
            })
        }
    }
}

impl Read for Reader {
    /// Returns a reference to this reader's header.
    fn header(&self) -> &Header {
        self.point_reader.header()
    }

    /// Reads a point.
    fn read(&mut self) -> Option<Result<Point>> {
        self.point_reader.read_next()
    }

    /// Seeks to the given point number, zero-indexed.
    fn seek(&mut self, position: u64) -> Result<()> {
        self.point_reader.seek(position)
    }

    /// Returns an iterator over this reader's points.
    fn points(&mut self) -> PointIterator {
        PointIterator {
            point_reader: &mut *self.point_reader,
        }
    }
}

impl Reader {
    /// Creates a new reader from a path.
    ///
    /// The underlying `File` is wrapped in a `BufReader` for performance reasons.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Reader;
    /// let reader = Reader::from_path("tests/data/autzen.las").unwrap();
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Reader> {
        File::open(path)
            .map_err(::Error::from)
            .and_then(|file| Reader::new(BufReader::new(file)))
    }
}

#[cfg(test)]
mod tests {
    use {Write, Writer};

    use super::*;

    #[test]
    fn seek() {
        let mut writer = Writer::default();
        writer.write(Default::default()).unwrap();
        let point = Point {
            x: 1.,
            y: 2.,
            z: 3.,
            ..Default::default()
        };
        writer.write(point.clone()).unwrap();
        let mut reader = Reader::new(writer.into_inner().unwrap()).unwrap();
        reader.seek(1).unwrap();
        assert_eq!(point, reader.read().unwrap().unwrap());
        assert!(reader.read().is_none());
    }
}
<commit_msg>Remove static lifetime<commit_after>//! Read las points.
//!
//! If you're reading any significant number of points, you'll want to make sure you're using a
//! `BufRead` instead of just a `Read`:
//!
//! ```
//! use std::fs::File;
//! use std::io::BufReader;
//! use las::Reader;
//!
//! let read = BufReader::new(File::open("tests/data/autzen.las").unwrap());
//! let reader = Reader::new(read).unwrap();
//! ```
//!
//! `Reader::from_path` does this for you:
//!
//! ```
//! use las::Reader;
//! let reader = Reader::from_path("tests/data/autzen.las").unwrap();
//! ```
//!
//! Ccompressed files are supported when using the feature "laz":
//!
//! ```
//! use las::Reader;
//! if cfg!(feature = "laz") {
//!  assert!(Reader::from_path("tests/data/autzen.laz").is_ok());
//! } else {
//!  assert!(Reader::from_path("tests/data/autzen.laz").is_err());
//! }
//!
//! ```
//!
//! Use `Reader::read` to read one point, and `Reader::points` to get an iterator over
//! `Result<Point>`:
//!
//! ```
//! use las::{Read, Reader};
//! let mut reader = Reader::from_path("tests/data/autzen.las").unwrap();
//! let first_point = reader.read().unwrap().unwrap();
//! let the_rest = reader.points().map(|r| r.unwrap()).collect::<Vec<_>>();
//! ```

use std::fs::File;
use std::io::{BufReader, Seek, SeekFrom};
use std::path::Path;

#[cfg(feature = "laz")]
use compression::CompressedPointReader;

use std::{cmp::Ordering, fmt::Debug};
use thiserror::Error;
use {raw, Builder, Header, Point, Result, Vlr};

/// Error while reading.
#[derive(Error, Clone, Copy, Debug)]
pub enum Error {
    /// The offset to the point data was too small.
    #[error("offset to the point data is too small: {0}")]
    OffsetToPointDataTooSmall(u32),

    /// The offset to the start of the evlrs is too small.
    #[error("offset to the start of the evlrs is too small: {0}")]
    OffsetToEvlrsTooSmall(u64),
}

#[inline]
pub(crate) fn read_point_from<R: std::io::Read>(
    mut source: &mut R,
    header: &Header,
) -> Result<Point> {
    let point = raw::Point::read_from(&mut source, header.point_format())
        .map(|raw_point| Point::new(raw_point, header.transforms()));
    point
}

/// Trait to specify behaviour a a PointReader
pub(crate) trait PointReader: Debug + Send {
    fn read_next(&mut self) -> Option<Result<Point>>;
    fn seek(&mut self, position: u64) -> Result<()>;
    fn header(&self) -> &Header;
}

/// An iterator over of the points in a `Reader`.
///
/// This struct is generally created by calling `points()` on `Reader`.
#[derive(Debug)]
pub struct PointIterator<'a> {
    point_reader: &'a mut dyn PointReader,
}

impl<'a> Iterator for PointIterator<'a> {
    type Item = Result<Point>;

    fn next(&mut self) -> Option<Self::Item> {
        self.point_reader.read_next()
    }
}

#[derive(Debug)]
struct UncompressedPointReader<R: std::io::Read + Seek> {
    source: R,
    header: Header,
    offset_to_point_data: u64,
    /// index of the last point read
    last_point_idx: u64,
}

impl<R: std::io::Read + Seek + Debug + Send> PointReader for UncompressedPointReader<R> {
    fn read_next(&mut self) -> Option<Result<Point>> {
        if self.last_point_idx < self.header.number_of_points() {
            self.last_point_idx += 1;
            Some(read_point_from(&mut self.source, &self.header))
        } else {
            None
        }
    }

    fn seek(&mut self, position: u64) -> Result<()> {
        self.last_point_idx = position;
        self.source.seek(SeekFrom::Start(
            self.offset_to_point_data + position * u64::from(self.header.point_format().len()),
        ))?;
        Ok(())
    }

    fn header(&self) -> &Header {
        &self.header
    }
}

/// A trait for objects which read LAS data.
pub trait Read {
    /// Returns a reference to this reader's header.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::{Read, Reader};
    /// let reader = Reader::from_path("tests/data/autzen.las").unwrap();
    /// let header = reader.header();
    /// ```
    fn header(&self) -> &Header;

    /// Reads a point.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::{Read, Reader};
    /// let mut reader = Reader::from_path("tests/data/autzen.las").unwrap();
    /// let point = reader.read().unwrap().unwrap();
    /// ```
    fn read(&mut self) -> Option<Result<Point>>;

    /// Seeks to the given point number, zero-indexed.
    ///
    /// Note that seeking on compressed (LAZ) data can be expensive as the reader
    /// will have to seek to the closest chunk start and decompress all points up until
    /// the point seeked to.
    ///
    ///
    /// # Examples
    ///
    /// ```
    /// use las::{Read, Reader};
    /// let mut reader = Reader::from_path("tests/data/autzen.las").unwrap();
    /// reader.seek(1).unwrap(); // <- seeks to the second point
    /// let the_second_point = reader.read().unwrap().unwrap();
    /// ```
    fn seek(&mut self, position: u64) -> Result<()>;

    /// Returns an iterator over this reader's points.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::{Read, Reader};
    /// let mut reader = Reader::from_path("tests/data/autzen.las").unwrap();
    /// let points = reader.points().collect::<Result<Vec<_>, _>>().unwrap();
    /// ```
    fn points(&mut self) -> PointIterator;
}

/// Reads LAS data.
#[derive(Debug)]
pub struct Reader<'a> {
    point_reader: Box<dyn PointReader + 'a>,
}

impl<'a> Reader<'a> {
    /// Creates a new reader.
    ///
    /// This does *not* wrap the `Read` in a `BufRead`, so if you're concered about performance you
    /// should do that wrapping yourself (or use `from_path`).
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::BufReader;
    /// use std::fs::File;
    /// # use las::Reader;
    /// let file = File::open("tests/data/autzen.las").unwrap();
    /// let reader = Reader::new(BufReader::new(file)).unwrap();
    /// ```
    pub fn new<R: std::io::Read + Seek + Send + Debug + 'a>(mut read: R) -> Result<Reader<'a>> {
        use std::io::Read;

        let raw_header = raw::Header::read_from(&mut read)?;
        let mut position = u64::from(raw_header.header_size);
        let number_of_variable_length_records = raw_header.number_of_variable_length_records;
        let offset_to_point_data = u64::from(raw_header.offset_to_point_data);
        let offset_to_end_of_points = raw_header.offset_to_end_of_points();
        let evlr = raw_header.evlr;

        let mut builder = Builder::new(raw_header)?;

        if !cfg!(feature = "laz") && builder.point_format.is_compressed {
            return Err(::Error::Laszip);
        }

        for _ in 0..number_of_variable_length_records {
            let vlr = raw::Vlr::read_from(&mut read, false).map(Vlr::new)?;
            position += vlr.len(false) as u64;
            builder.vlrs.push(vlr);
        }
        match position.cmp(&offset_to_point_data) {
            Ordering::Less => {
                read.by_ref()
                    .take(offset_to_point_data - position)
                    .read_to_end(&mut builder.vlr_padding)?;
            }
            Ordering::Equal => {} // pass
            Ordering::Greater => {
                return Err(Error::OffsetToPointDataTooSmall(offset_to_point_data as u32).into())
            }
        }

        read.seek(SeekFrom::Start(offset_to_end_of_points))?;
        if let Some(evlr) = evlr {
            match evlr.start_of_first_evlr.cmp(&offset_to_end_of_points) {
                Ordering::Less => {
                    return Err(Error::OffsetToEvlrsTooSmall(evlr.start_of_first_evlr).into())
                }
                Ordering::Equal => {} // pass
                Ordering::Greater => {
                    let n = evlr.start_of_first_evlr - offset_to_end_of_points;
                    read.by_ref()
                        .take(n)
                        .read_to_end(&mut builder.point_padding)?;
                }
            }
            builder
                .evlrs
                .push(raw::Vlr::read_from(&mut read, true).map(Vlr::new)?);
        }

        read.seek(SeekFrom::Start(offset_to_point_data))?;

        let header = builder.into_header()?;

        #[cfg(feature = "laz")]
        {
            if header.point_format().is_compressed {
                Ok(Reader {
                    point_reader: Box::new(CompressedPointReader::new(read, header)?),
                })
            } else {
                Ok(Reader {
                    point_reader: Box::new(UncompressedPointReader {
                        source: read,
                        header,
                        offset_to_point_data,
                        last_point_idx: 0,
                    }),
                })
            }
        }
        #[cfg(not(feature = "laz"))]
        {
            Ok(Reader {
                point_reader: Box::new(UncompressedPointReader {
                    source: read,
                    header,
                    offset_to_point_data,
                    last_point_idx: 0,
                }),
            })
        }
    }
}

impl<'a> Read for Reader<'a> {
    /// Returns a reference to this reader's header.
    fn header(&self) -> &Header {
        self.point_reader.header()
    }

    /// Reads a point.
    fn read(&mut self) -> Option<Result<Point>> {
        self.point_reader.read_next()
    }

    /// Seeks to the given point number, zero-indexed.
    fn seek(&mut self, position: u64) -> Result<()> {
        self.point_reader.seek(position)
    }

    /// Returns an iterator over this reader's points.
    fn points(&mut self) -> PointIterator {
        PointIterator {
            point_reader: &mut *self.point_reader,
        }
    }
}

impl<'a> Reader<'a> {
    /// Creates a new reader from a path.
    ///
    /// The underlying `File` is wrapped in a `BufReader` for performance reasons.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Reader;
    /// let reader = Reader::from_path("tests/data/autzen.las").unwrap();
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Reader<'a>> {
        File::open(path)
            .map_err(::Error::from)
            .and_then(|file| Reader::new(BufReader::new(file)))
    }
}

#[cfg(test)]
mod tests {
    use {Write, Writer};

    use super::*;

    #[test]
    fn seek() {
        let mut writer = Writer::default();
        writer.write(Default::default()).unwrap();
        let point = Point {
            x: 1.,
            y: 2.,
            z: 3.,
            ..Default::default()
        };
        writer.write(point.clone()).unwrap();
        let mut reader = Reader::new(writer.into_inner().unwrap()).unwrap();
        reader.seek(1).unwrap();
        assert_eq!(point, reader.read().unwrap().unwrap());
        assert!(reader.read().is_none());
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use geom::matrix::{Matrix4, identity};
use geom::size::Size2D;
use geom::rect::Rect;
use opengles::gl2::{GLuint, delete_textures};
use std::managed::mut_ptr_eq;

pub enum Format {
    ARGB32Format,
    RGB24Format
}

pub enum Layer {
    ContainerLayerKind(@mut ContainerLayer),
    TextureLayerKind(@mut TextureLayer),
    ImageLayerKind(@mut ImageLayer),
    TiledImageLayerKind(@mut TiledImageLayer)
}

impl Layer {
    fn with_common<T>(&self, f: &fn(&mut CommonLayer) -> T) -> T {
        match *self {
            ContainerLayerKind(container_layer) => f(&mut container_layer.common),
            TextureLayerKind(texture_layer) => f(&mut texture_layer.common),
            ImageLayerKind(image_layer) => f(&mut image_layer.common),
            TiledImageLayerKind(tiled_image_layer) => f(&mut tiled_image_layer.common)
        }
    }
}

pub struct CommonLayer {
    parent: Option<Layer>,
    prev_sibling: Option<Layer>,
    next_sibling: Option<Layer>,

    transform: Matrix4<f32>,
}

impl CommonLayer {
    // FIXME: Workaround for cross-crate bug regarding mutability of class fields
    pub fn set_transform(&mut self, new_transform: Matrix4<f32>) {
        self.transform = new_transform;
    }
}

pub fn CommonLayer() -> CommonLayer {
    CommonLayer {
        parent: None,
        prev_sibling: None,
        next_sibling: None,
        transform: identity(),
    }
}

pub struct ContainerLayer {
    common: CommonLayer,
    first_child: Option<Layer>,
    last_child: Option<Layer>,
    scissor: Option<Rect<f32>>,
}

pub fn ContainerLayer() -> ContainerLayer {
    ContainerLayer {
        common: CommonLayer(),
        first_child: None,
        last_child: None,
        scissor: None,
    }
}

struct ChildIterator {
    priv current: Option<Layer>,
}

impl Iterator<Layer> for ChildIterator {
    fn next(&mut self) -> Option<Layer> {
        match self.current {
            None => None,
            Some(child) => {
                self.current = child.with_common(|x| x.next_sibling);
                Some(child)
            }
        }
    }
}

impl ContainerLayer {
    pub fn children(&self) -> ChildIterator {
        ChildIterator { current: self.first_child }
    }

    /// Only works when the child is disconnected from the layer tree.
    pub fn add_child(@mut self, new_child: Layer) {
        do new_child.with_common |new_child_common| {
            assert!(new_child_common.parent.is_none());
            assert!(new_child_common.prev_sibling.is_none());
            assert!(new_child_common.next_sibling.is_none());

            new_child_common.parent = Some(ContainerLayerKind(self));

            match self.first_child {
                None => {}
                Some(first_child) => {
                    do first_child.with_common |first_child_common| {
                        assert!(first_child_common.prev_sibling.is_none());
                        first_child_common.prev_sibling = Some(new_child);
                        new_child_common.next_sibling = Some(first_child);
                    }
                }
            }

            self.first_child = Some(new_child);

            match self.last_child {
                None => self.last_child = Some(new_child),
                Some(_) => {}
            }
        }
    }

    pub fn remove_child(@mut self, child: Layer) {
        do child.with_common |child_common| {
            assert!(child_common.parent.is_some());
            match child_common.parent.unwrap() {
                ContainerLayerKind(ref container) => {
                    assert!(mut_ptr_eq(*container, self));
                },
                _ => fail!(~"Invalid parent of child in layer tree"),
            }

            match child_common.next_sibling {
                None => { // this is the last child
                    self.last_child = child_common.prev_sibling;
                },
                Some(ref sibling) => {
                    do sibling.with_common |sibling_common| {
                        sibling_common.prev_sibling = child_common.prev_sibling;
                    }
                }
            }
            match child_common.prev_sibling {
                None => { // this is the first child
                    self.first_child = child_common.next_sibling;
                },
                Some(ref sibling) => {
                    do sibling.with_common |sibling_common| {
                        sibling_common.next_sibling = child_common.next_sibling;
                    }
                }
            }
        }
    }
}

trait TextureManager {
    pub fn get_texture(&self) -> GLuint;
}

pub struct TextureLayer {
    common: CommonLayer,
    manager: @TextureManager,
    size: Size2D<uint>
}

impl TextureLayer {
    pub fn new(manager: @TextureManager, size: Size2D<uint>) -> TextureLayer {
        TextureLayer {
            common: CommonLayer(),
            manager: manager,
            size: size,
        }
    }
}

pub type WithDataFn<'self> = &'self fn(&'self [u8]);

pub trait ImageData {
    fn size(&self) -> Size2D<uint>;

    // NB: stride is in pixels, like OpenGL GL_UNPACK_ROW_LENGTH.
    fn stride(&self) -> uint;

    fn format(&self) -> Format;
    fn with_data(&self, WithDataFn);
}

pub struct Image {
    data: @ImageData,
    texture: Option<GLuint>,
}

#[unsafe_destructor]
impl Drop for Image {
    fn drop(&self) {
        match self.texture.clone() {
            None => {
                // Nothing to do.
            }
            Some(texture) => {
                delete_textures(&[texture]);
            }
        }
    }
}

impl Image {
    pub fn new(data: @ImageData) -> Image {
        Image { data: data, texture: None }
    }
}

/// Basic image data is a simple image data store that just owns the pixel data in memory.
pub struct BasicImageData {
    size: Size2D<uint>,
    stride: uint,
    format: Format,
    data: ~[u8]
}

impl BasicImageData {
    pub fn new(size: Size2D<uint>, stride: uint, format: Format, data: ~[u8]) ->
            BasicImageData {
        BasicImageData {
            size: size,
            stride: stride,
            format: format,
            data: data
        }
    }
}

impl ImageData for BasicImageData {
    fn size(&self) -> Size2D<uint> { self.size }
    fn stride(&self) -> uint { self.stride }
    fn format(&self) -> Format { self.format }
    fn with_data(&self, f: WithDataFn) { f(self.data) }
}

pub struct ImageLayer {
    common: CommonLayer,
    image: @mut Image,
}

impl ImageLayer {
    // FIXME: Workaround for cross-crate bug
    pub fn set_image(&mut self, new_image: @mut Image) {
        self.image = new_image;
    }
}

pub fn ImageLayer(image: @mut Image) -> ImageLayer {
    ImageLayer {
        common : CommonLayer(),
        image : image,
    }
}

pub struct TiledImageLayer {
    common: CommonLayer,
    tiles: @mut ~[@mut Image],
    tiles_across: uint,
}

pub fn TiledImageLayer(in_tiles: &[@mut Image], tiles_across: uint) -> TiledImageLayer {
    let tiles = @mut ~[];
    for tile in in_tiles.iter() {
        tiles.push(*tile);
    }

    TiledImageLayer {
        common: CommonLayer(),
        tiles: tiles,
        tiles_across: tiles_across
    }
}

<commit_msg>More Rust version updates<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use geom::matrix::{Matrix4, identity};
use geom::size::Size2D;
use geom::rect::Rect;
use opengles::gl2::{GLuint, delete_textures};
use std::managed::mut_ptr_eq;

pub enum Format {
    ARGB32Format,
    RGB24Format
}

pub enum Layer {
    ContainerLayerKind(@mut ContainerLayer),
    TextureLayerKind(@mut TextureLayer),
    ImageLayerKind(@mut ImageLayer),
    TiledImageLayerKind(@mut TiledImageLayer)
}

impl Layer {
    pub fn with_common<T>(&self, f: &fn(&mut CommonLayer) -> T) -> T {
        match *self {
            ContainerLayerKind(container_layer) => f(&mut container_layer.common),
            TextureLayerKind(texture_layer) => f(&mut texture_layer.common),
            ImageLayerKind(image_layer) => f(&mut image_layer.common),
            TiledImageLayerKind(tiled_image_layer) => f(&mut tiled_image_layer.common)
        }
    }
}

pub struct CommonLayer {
    parent: Option<Layer>,
    prev_sibling: Option<Layer>,
    next_sibling: Option<Layer>,

    transform: Matrix4<f32>,
}

impl CommonLayer {
    // FIXME: Workaround for cross-crate bug regarding mutability of class fields
    pub fn set_transform(&mut self, new_transform: Matrix4<f32>) {
        self.transform = new_transform;
    }
}

pub fn CommonLayer() -> CommonLayer {
    CommonLayer {
        parent: None,
        prev_sibling: None,
        next_sibling: None,
        transform: identity(),
    }
}

pub struct ContainerLayer {
    common: CommonLayer,
    first_child: Option<Layer>,
    last_child: Option<Layer>,
    scissor: Option<Rect<f32>>,
}

pub fn ContainerLayer() -> ContainerLayer {
    ContainerLayer {
        common: CommonLayer(),
        first_child: None,
        last_child: None,
        scissor: None,
    }
}

struct ChildIterator {
    priv current: Option<Layer>,
}

impl Iterator<Layer> for ChildIterator {
    fn next(&mut self) -> Option<Layer> {
        match self.current {
            None => None,
            Some(child) => {
                self.current = child.with_common(|x| x.next_sibling);
                Some(child)
            }
        }
    }
}

impl ContainerLayer {
    pub fn children(&self) -> ChildIterator {
        ChildIterator { current: self.first_child }
    }

    /// Only works when the child is disconnected from the layer tree.
    pub fn add_child(@mut self, new_child: Layer) {
        do new_child.with_common |new_child_common| {
            assert!(new_child_common.parent.is_none());
            assert!(new_child_common.prev_sibling.is_none());
            assert!(new_child_common.next_sibling.is_none());

            new_child_common.parent = Some(ContainerLayerKind(self));

            match self.first_child {
                None => {}
                Some(first_child) => {
                    do first_child.with_common |first_child_common| {
                        assert!(first_child_common.prev_sibling.is_none());
                        first_child_common.prev_sibling = Some(new_child);
                        new_child_common.next_sibling = Some(first_child);
                    }
                }
            }

            self.first_child = Some(new_child);

            match self.last_child {
                None => self.last_child = Some(new_child),
                Some(_) => {}
            }
        }
    }

    pub fn remove_child(@mut self, child: Layer) {
        do child.with_common |child_common| {
            assert!(child_common.parent.is_some());
            match child_common.parent.unwrap() {
                ContainerLayerKind(ref container) => {
                    assert!(mut_ptr_eq(*container, self));
                },
                _ => fail!(~"Invalid parent of child in layer tree"),
            }

            match child_common.next_sibling {
                None => { // this is the last child
                    self.last_child = child_common.prev_sibling;
                },
                Some(ref sibling) => {
                    do sibling.with_common |sibling_common| {
                        sibling_common.prev_sibling = child_common.prev_sibling;
                    }
                }
            }
            match child_common.prev_sibling {
                None => { // this is the first child
                    self.first_child = child_common.next_sibling;
                },
                Some(ref sibling) => {
                    do sibling.with_common |sibling_common| {
                        sibling_common.next_sibling = child_common.next_sibling;
                    }
                }
            }
        }
    }
}

trait TextureManager {
    pub fn get_texture(&self) -> GLuint;
}

pub struct TextureLayer {
    common: CommonLayer,
    manager: @TextureManager,
    size: Size2D<uint>
}

impl TextureLayer {
    pub fn new(manager: @TextureManager, size: Size2D<uint>) -> TextureLayer {
        TextureLayer {
            common: CommonLayer(),
            manager: manager,
            size: size,
        }
    }
}

pub type WithDataFn<'self> = &'self fn(&'self [u8]);

pub trait ImageData {
    fn size(&self) -> Size2D<uint>;

    // NB: stride is in pixels, like OpenGL GL_UNPACK_ROW_LENGTH.
    fn stride(&self) -> uint;

    fn format(&self) -> Format;
    fn with_data(&self, WithDataFn);
}

pub struct Image {
    data: @ImageData,
    texture: Option<GLuint>,
}

#[unsafe_destructor]
impl Drop for Image {
    fn drop(&self) {
        match self.texture.clone() {
            None => {
                // Nothing to do.
            }
            Some(texture) => {
                delete_textures(&[texture]);
            }
        }
    }
}

impl Image {
    pub fn new(data: @ImageData) -> Image {
        Image { data: data, texture: None }
    }
}

/// Basic image data is a simple image data store that just owns the pixel data in memory.
pub struct BasicImageData {
    size: Size2D<uint>,
    stride: uint,
    format: Format,
    data: ~[u8]
}

impl BasicImageData {
    pub fn new(size: Size2D<uint>, stride: uint, format: Format, data: ~[u8]) ->
            BasicImageData {
        BasicImageData {
            size: size,
            stride: stride,
            format: format,
            data: data
        }
    }
}

impl ImageData for BasicImageData {
    fn size(&self) -> Size2D<uint> { self.size }
    fn stride(&self) -> uint { self.stride }
    fn format(&self) -> Format { self.format }
    fn with_data(&self, f: WithDataFn) { f(self.data) }
}

pub struct ImageLayer {
    common: CommonLayer,
    image: @mut Image,
}

impl ImageLayer {
    // FIXME: Workaround for cross-crate bug
    pub fn set_image(&mut self, new_image: @mut Image) {
        self.image = new_image;
    }
}

pub fn ImageLayer(image: @mut Image) -> ImageLayer {
    ImageLayer {
        common : CommonLayer(),
        image : image,
    }
}

pub struct TiledImageLayer {
    common: CommonLayer,
    tiles: @mut ~[@mut Image],
    tiles_across: uint,
}

pub fn TiledImageLayer(in_tiles: &[@mut Image], tiles_across: uint) -> TiledImageLayer {
    let tiles = @mut ~[];
    for tile in in_tiles.iter() {
        tiles.push(*tile);
    }

    TiledImageLayer {
        common: CommonLayer(),
        tiles: tiles,
        tiles_across: tiles_across
    }
}

<|endoftext|>


<commit_before>use glium::backend::glutin_backend::GlutinFacade;
use mesh::{BaseVertex, Mesh};

pub struct Landscape {
    pub model: Mesh,
}

impl Landscape {
    pub fn new(facade: &GlutinFacade) -> Result<Landscape, String>
    {
        let scale = 10.0_f32;
        let vertex0 = BaseVertex { position: [-scale, 0.0, -scale] };
        let vertex1 = BaseVertex { position: [ scale, 0.0, -scale] };
        let vertex2 = BaseVertex { position: [ scale, 0.0,  scale] };
        let vertex3 = BaseVertex { position: [-scale, 0.0,  scale] };

        let mesh = try!(Mesh::new(facade,
                                  &[vertex0, vertex1, vertex2, vertex3],
                                  &[0, 1, 2, 2, 3, 0]));

        Ok(Landscape {
            model: mesh,
        })
    }

}
<commit_msg>landscape with shader<commit_after>use std;
use glium::backend::glutin_backend::GlutinFacade;
use mesh::{VertexTex, Mesh};
use texture;
use shader;

pub struct Landscape {
    pub model: Mesh<VertexTex>,
    pub shader: shader::Shader,
    pub texture: texture::Texture,
}

impl Landscape {
    fn load_shaders(facade: &GlutinFacade) -> Result<shader::Shader, String> {
        let vertex_shader_src = r#"
    #version 140

    in vec3 pos;
    in vec2 tex;

    out vec2 f_tex;

    uniform mat4 proj;
    uniform mat4 view;
    uniform mat4 model;

    void main() {
        f_tex = tex;
        gl_Position = proj * (view * model) * vec4(pos, 1.0);
    }
"#;

        let fragment_shader_src = r#"
    #version 140

    in vec2 f_tex;
    out vec4 color;

    uniform sampler2D tex;

    void main() {
        color = texture(tex, f_tex);
    }
"#;
        Ok(try!(shader::Shader::new(facade, vertex_shader_src, fragment_shader_src)))
    }

    pub fn new(facade: &GlutinFacade) -> Result<Landscape, String>
    {
        let scale = 100.0_f32;
        let tex_scale = 10.0_f32;
        let vertex0 = VertexTex { pos: [-scale, 0.0, -scale], tex: [0.0,       0.0] };
        let vertex1 = VertexTex { pos: [ scale, 0.0, -scale], tex: [tex_scale, 0.0] };
        let vertex2 = VertexTex { pos: [ scale, 0.0,  scale], tex: [tex_scale, tex_scale] };
        let vertex3 = VertexTex { pos: [-scale, 0.0,  scale], tex: [0.0,       tex_scale] };

        let mesh = try!(Mesh::new(facade,
                                  &[vertex0, vertex1, vertex2, vertex3],
                                  &[0, 1, 2, 2, 3, 0]));
        let shader = try!(Landscape::load_shaders(facade));
        let texture = try!(texture::Texture::new(facade, &std::path::Path::new("terrarian.jpg")));

        Ok(Landscape {
            model: mesh,
            shader: shader,
            texture: texture,
        })
    }

}
<|endoftext|>


<commit_before>extern crate parity_wasm;

use std::env::args;

use parity_wasm::{interpreter, ModuleInstanceInterface, RuntimeValue};
use parity_wasm::elements::ExportEntry;
use parity_wasm::elements::ExportSection;
use parity_wasm::elements::FunctionSection;
use parity_wasm::elements::TypeSection;
use parity_wasm::elements::Internal;
use parity_wasm::elements::Type;
use parity_wasm::elements::FunctionType;
use parity_wasm::elements::ValueType;

fn main() {
    let args: Vec<_> = args().collect();
    if args.len() < 3 {
        println!("Usage: {} <wasm file> <exported func> [<arg>...]", args[0]);
        return;
    }
    let func_name = &args[2];
    let (_, program_args) = args.split_at(3);

    let program = parity_wasm::ProgramInstance::with_env_params(
        interpreter::EnvParams {
            total_stack: 128*1024,
            total_memory: 2*1024*1024,
            allow_memory_growth: false,
        }
    ).expect("Failed to load program");

    let module_def = parity_wasm::deserialize_file(&args[1]).expect("Failed to load module");
    let execution_params = {
        let export_section: &ExportSection = module_def.export_section().expect("No export section found");
        let function_section: &FunctionSection = module_def.function_section().expect("No function section found");
        let type_section: &TypeSection = module_def.type_section().expect("No type section found");
        let found_entry: &ExportEntry = export_section.entries().iter()
            .find(|entry| func_name.eq(entry.field())).unwrap();
        let function_index = match found_entry.internal() {
            &Internal::Function(index) => index,
            _ => panic!("Founded export is not a function"),
        };
        let func_type_ref: u32 = function_section.entries()[function_index as usize].type_ref();
        let type_: &Type = &type_section.types()[func_type_ref as usize];
        let function_type: &FunctionType = match type_ {
            &Type::Function(ref func_type) => func_type,
        };

        let args: Vec<RuntimeValue> = function_type.params().iter().enumerate().map(|(i, value)| match value {
            &ValueType::I32 => RuntimeValue::I32(program_args[i].parse::<i32>().unwrap()),
            &ValueType::I64 => RuntimeValue::I64(program_args[i].parse::<i64>().unwrap()),
            &ValueType::F32 => RuntimeValue::F32(program_args[i].parse::<f32>().unwrap()),
            &ValueType::F64 => RuntimeValue::F64(program_args[i].parse::<f64>().unwrap()),
        }).collect();

        interpreter::ExecutionParams::from(args)
    };

    let module_def = program.add_module("main", module_def, None).expect("Failed to initialize module");

    println!("Result: {:?}", module_def.execute_export(func_name, execution_params));
}
<commit_msg>various fixes, code cleanup fix: exclude imports from function index<commit_after>extern crate parity_wasm;

use std::env::args;

use parity_wasm::{interpreter, ModuleInstanceInterface, RuntimeValue};
use parity_wasm::elements::{Internal, Type, FunctionType, ValueType};

fn main() {
    let args: Vec<_> = args().collect();
    if args.len() < 3 {
        println!("Usage: {} <wasm file> <exported func> [<arg>...]", args[0]);
        return;
    }
    let func_name = &args[2];
    let (_, program_args) = args.split_at(3);

    let program = parity_wasm::ProgramInstance::with_env_params(
        interpreter::EnvParams {
            total_stack: 128*1024,
            total_memory: 2*1024*1024,
            allow_memory_growth: false,
        }
    ).expect("Program instance to load");

    let module = parity_wasm::deserialize_file(&args[1]).expect("File to be deserialized");
    let execution_params = {
        let export_section = module.export_section().expect("No export section found");
        let function_section = module.function_section().expect("No function section found");
        let type_section = module.type_section().expect("No type section found");

        let found_entry= export_section.entries().iter()
            .find(|entry| func_name == entry.field()).expect(&format!("No export with name {} found", func_name));

        // Function index with imported functions
        let function_index: usize = match found_entry.internal() {
            &Internal::Function(index) => index as usize,
            _ => panic!("Founded export is not a function"),
        };
        let import_section_len: usize = match module.import_section() {
            Some(import) => import.entries().len(),
            None => 0,
        };

        let function_index_in_section = function_index - import_section_len;
        let func_type_ref: usize = function_section.entries()[function_index_in_section].type_ref() as usize;
        let function_type: &FunctionType = match &type_section.types()[func_type_ref] {
            &Type::Function(ref func_type) => func_type,
        };

        let args: Vec<RuntimeValue> = function_type.params().iter().enumerate().map(|(i, value)| match value {
            &ValueType::I32 => RuntimeValue::I32(program_args[i].parse::<i32>().expect(&format!("Can't parse arg #{} as i32", program_args[i]))),
            &ValueType::I64 => RuntimeValue::I64(program_args[i].parse::<i64>().expect(&format!("Can't parse arg #{} as i64", program_args[i]))),
            &ValueType::F32 => RuntimeValue::F32(program_args[i].parse::<f32>().expect(&format!("Can't parse arg #{} as f32", program_args[i]))),
            &ValueType::F64 => RuntimeValue::F64(program_args[i].parse::<f64>().expect(&format!("Can't parse arg #{} as f64", program_args[i]))),
        }).collect();

        interpreter::ExecutionParams::from(args)
    };

    let module = program.add_module("main", module, None).expect("Failed to initialize module");

    println!("Result: {:?}", module.execute_export(func_name, execution_params).expect(""));
}
<|endoftext|>


<commit_before>// hex encoder and decoder used by rust-protobuf unittests

use std::str;
use std::char;

fn decode_hex_digit(digit: char) -> u8 {
    match char::to_digit(digit, 16) {
        Some(d) => d as u8,
        _ => fail!()
    }
}

pub fn decode_hex(hex: &str) -> ~[u8] {
    let mut r: ~[u8] = ~[];
    let mut pos = 0;
    loop {
        while pos < hex.char_len() && hex[pos] == ' ' as u8 {
            pos += 1;
        }
        if hex.char_len() - pos >= 2 {
            r.push((decode_hex_digit(hex.char_at(pos)) << 4) | decode_hex_digit(hex.char_at(pos + 1)));
            pos += 2;
            loop;
        }
        if pos == hex.char_len() {
            break;
        }
        fail!("pos = %ud", pos);
    }
    r
}

fn encode_hex_digit(digit: u8) -> char {
    match char::from_digit(digit as uint, 16) {
        Some(c) => c,
        _ => fail!()
    }
}

fn encode_hex_byte(byte: u8) -> [char, ..2] {
    [encode_hex_digit(byte >> 4), encode_hex_digit(byte & 0x0Fu8)]
}

pub fn encode_hex(bytes: &[u8]) -> ~str {
    (do bytes.map |byte| {
        str::from_chars(encode_hex_byte(*byte))
    }).connect(" ")
}

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

    #[test]
    fn test_decode_hex() {
        assert_eq!(~[], decode_hex(""));
        assert_eq!(~[0x00], decode_hex("00"));
        assert_eq!(~[0xff], decode_hex("ff"));
        assert_eq!(~[0xab], decode_hex("AB"));
        assert_eq!(~[0xfa, 0x19], decode_hex("fa 19"));
    }

    #[test]
    fn test_encode_hex() {
        assert_eq!(~"", encode_hex([]));
        assert_eq!(~"00", encode_hex([0x00]));
        assert_eq!(~"ab", encode_hex([0xab]));
        assert_eq!(~"01 a2 1a fe", encode_hex([0x01, 0xa2, 0x1a, 0xfe]));
    }
}
<commit_msg>Fix obsolete syntax (loop -> continue)<commit_after>// hex encoder and decoder used by rust-protobuf unittests

use std::str;
use std::char;

fn decode_hex_digit(digit: char) -> u8 {
    match char::to_digit(digit, 16) {
        Some(d) => d as u8,
        _ => fail!()
    }
}

pub fn decode_hex(hex: &str) -> ~[u8] {
    let mut r: ~[u8] = ~[];
    let mut pos = 0;
    loop {
        while pos < hex.char_len() && hex[pos] == ' ' as u8 {
            pos += 1;
        }
        if hex.char_len() - pos >= 2 {
            r.push((decode_hex_digit(hex.char_at(pos)) << 4) | decode_hex_digit(hex.char_at(pos + 1)));
            pos += 2;
            continue;
        }
        if pos == hex.char_len() {
            break;
        }
        fail!("pos = %ud", pos);
    }
    r
}

fn encode_hex_digit(digit: u8) -> char {
    match char::from_digit(digit as uint, 16) {
        Some(c) => c,
        _ => fail!()
    }
}

fn encode_hex_byte(byte: u8) -> [char, ..2] {
    [encode_hex_digit(byte >> 4), encode_hex_digit(byte & 0x0Fu8)]
}

pub fn encode_hex(bytes: &[u8]) -> ~str {
    (do bytes.map |byte| {
        str::from_chars(encode_hex_byte(*byte))
    }).connect(" ")
}

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

    #[test]
    fn test_decode_hex() {
        assert_eq!(~[], decode_hex(""));
        assert_eq!(~[0x00], decode_hex("00"));
        assert_eq!(~[0xff], decode_hex("ff"));
        assert_eq!(~[0xab], decode_hex("AB"));
        assert_eq!(~[0xfa, 0x19], decode_hex("fa 19"));
    }

    #[test]
    fn test_encode_hex() {
        assert_eq!(~"", encode_hex([]));
        assert_eq!(~"00", encode_hex([0x00]));
        assert_eq!(~"ab", encode_hex([0xab]));
        assert_eq!(~"01 a2 1a fe", encode_hex([0x01, 0xa2, 0x1a, 0xfe]));
    }
}
<|endoftext|>


<commit_before>use libc::{
    self,
    c_void,
    c_long,
    size_t,
};
use std::ffi::CString;
use std::num::FromPrimitive;
use {
    std,
    ffi,
    Face,
    FtResult,
};
use std::path::AsPath;

extern "C" fn alloc_library(_memory: ffi::FT_Memory, size: c_long) -> *mut c_void {
    unsafe {
        libc::malloc(size as size_t)
    }
}

extern "C" fn free_library(_memory: ffi::FT_Memory, block: *mut c_void) {
    unsafe {
        libc::free(block)
    }
}

extern "C" fn realloc_library(_memory: ffi::FT_Memory,
                              _cur_size: c_long,
                              new_size: c_long,
                              block: *mut c_void) -> *mut c_void {
    unsafe {
        libc::realloc(block, new_size as size_t)
    }
}

static MEMORY: ffi::FT_MemoryRec = ffi::FT_MemoryRec {
    user: 0 as *mut c_void,
    alloc: alloc_library,
    free: free_library,
    realloc: realloc_library,
};

pub struct Library {
    raw: ffi::FT_Library,
}

impl Library {
    pub fn init() -> FtResult<Library> {
        unsafe {
            let mut raw = std::ptr::null_mut();

            let err = ffi::FT_New_Library(&MEMORY, &mut raw);
            if err == ffi::FT_Err_Ok {
                ffi::FT_Add_Default_Modules(raw);
                Ok(Library {
                    raw: raw,
                })
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn new_face<P: ?Sized>(&self, filepath: &P, face_index: isize) -> FtResult<Face>
        where P: AsPath
    {
        unsafe {
            let mut face = std::ptr::null_mut();

            let path_str = CString::new(filepath.as_path().to_str().unwrap()).unwrap();

            let err = ffi::FT_New_Face(self.raw, path_str.as_ptr(), face_index as ffi::FT_Long, &mut face);
            if err == ffi::FT_Err_Ok {
                Ok(Face::from_raw(self.raw, face))
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn new_memory_face(&self, buffer: &[u8], face_index: isize) -> FtResult<Face> {
        unsafe {
            let mut face = std::ptr::null_mut();
            let err = ffi::FT_New_Memory_Face(self.raw, buffer.as_ptr(),
                buffer.len() as ffi::FT_Long, face_index as ffi::FT_Long, &mut face);
            if err == ffi::FT_Err_Ok {
                Ok(Face::from_raw(self.raw, face))
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn raw(&self) -> ffi::FT_Library {
        self.raw
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        unsafe {
            let err = ffi::FT_Done_Library(self.raw);
            if err != ffi::FT_Err_Ok {
                panic!("Failed to drop freetype library");
            }
        }
    }
}

<commit_msg>Fix `new_face` path type<commit_after>use libc::{
    self,
    c_void,
    c_long,
    size_t,
};
use std::ffi::CString;
use std::num::FromPrimitive;
use {
    std,
    ffi,
    Face,
    FtResult,
};
use std::path::AsPath;

extern "C" fn alloc_library(_memory: ffi::FT_Memory, size: c_long) -> *mut c_void {
    unsafe {
        libc::malloc(size as size_t)
    }
}

extern "C" fn free_library(_memory: ffi::FT_Memory, block: *mut c_void) {
    unsafe {
        libc::free(block)
    }
}

extern "C" fn realloc_library(_memory: ffi::FT_Memory,
                              _cur_size: c_long,
                              new_size: c_long,
                              block: *mut c_void) -> *mut c_void {
    unsafe {
        libc::realloc(block, new_size as size_t)
    }
}

static MEMORY: ffi::FT_MemoryRec = ffi::FT_MemoryRec {
    user: 0 as *mut c_void,
    alloc: alloc_library,
    free: free_library,
    realloc: realloc_library,
};

pub struct Library {
    raw: ffi::FT_Library,
}

impl Library {
    pub fn init() -> FtResult<Library> {
        unsafe {
            let mut raw = std::ptr::null_mut();

            let err = ffi::FT_New_Library(&MEMORY, &mut raw);
            if err == ffi::FT_Err_Ok {
                ffi::FT_Add_Default_Modules(raw);
                Ok(Library {
                    raw: raw,
                })
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn new_face<P: AsPath>(&self, filepath: P, face_index: isize) -> FtResult<Face> {
        unsafe {
            let mut face = std::ptr::null_mut();

            let path_str = CString::new(filepath.as_path().to_str().unwrap()).unwrap();

            let err = ffi::FT_New_Face(self.raw, path_str.as_ptr(), face_index as ffi::FT_Long, &mut face);
            if err == ffi::FT_Err_Ok {
                Ok(Face::from_raw(self.raw, face))
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn new_memory_face(&self, buffer: &[u8], face_index: isize) -> FtResult<Face> {
        unsafe {
            let mut face = std::ptr::null_mut();
            let err = ffi::FT_New_Memory_Face(self.raw, buffer.as_ptr(),
                buffer.len() as ffi::FT_Long, face_index as ffi::FT_Long, &mut face);
            if err == ffi::FT_Err_Ok {
                Ok(Face::from_raw(self.raw, face))
            } else {
                Err(FromPrimitive::from_i32(err).unwrap())
            }
        }
    }

    pub fn raw(&self) -> ffi::FT_Library {
        self.raw
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        unsafe {
            let err = ffi::FT_Done_Library(self.raw);
            if err != ffi::FT_Err_Ok {
                panic!("Failed to drop freetype library");
            }
        }
    }
}

<|endoftext|>


<commit_before>//! Router module

use hyper::Method;
use hyper::method::Method::{Delete, Get, Head, Post, Put};

use std::any::Any;
use std::collections::{BTreeMap, HashMap};
use std::marker::PhantomData;

use request;
use request::Request;
use response::{Result, Response};

use std::result;

pub type TypedCallback<T> = fn(&mut T, &Request, &mut Response) -> Result;
pub type TypedMiddleware<T> = fn(&mut T, &mut Request, &mut Response);
pub type Static = fn(&Request, &mut Response) -> Result;

/// A segment is either a fixed string, or a variable with a name
#[derive(Debug)]
enum Segment {
    Fixed(String),
    Variable(String)
}

impl Segment {
    fn is_empty(&self) -> bool {
        match self {
            &Segment::Fixed(ref fixed) if fixed.len() == 0 => true,
            _ => false
        }
    }
}

/// A route is an absolute URL pattern with a leading slash, and segments separated by slashes.
///
/// A segment that begins with a colon declares a variable, for example "/:user_id".
pub struct Route {
    segments: Vec<Segment>,
    callback: Callback
}

/// Returns a vector of segments from the given string.
fn get_segments(from: &str) -> result::Result<Vec<Segment>, &str> {
    if from.len() == 0 {
        return Err("route must not be empty");
    }
    if &from[0..1] != "/" {
        return Err("route must begin with a slash");
    }

    let stripped = &from[1..];
    Ok(stripped.split('/').map(|segment| if segment.len() > 0 && segment.as_bytes()[0] == b':' {
            Segment::Variable(segment[1..].to_string())
        } else {
            Segment::Fixed(segment.to_string())
        }
    ).collect::<Vec<Segment>>())
}

impl Route {
    fn new(from: &str, callback: Callback) -> result::Result<Route, &str> {
        Ok(Route {
            segments: try!(get_segments(from)),
            callback: callback
        })
    }
}

use std::fmt::{self, Debug, Formatter};

impl Debug for Route {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{:?}", self.segments)
    }
}

/// Router structure
pub struct Router<T> {
    inner: RouterAny,
    _marker: PhantomData<T>
}

impl<T: Default + Any + Send> Router<T> {
    /// wraps the value returned by Default::default into a box
    fn create() -> Box<Any + Send> {
        Box::new(T::default())
    }

    /// Creates a new router.
    pub fn new() -> Router<T> {
        Router {
            inner: RouterAny::new::<T>(),
            _marker: PhantomData
        }
    }

    pub fn add_middleware(&mut self, middleware: TypedMiddleware<T>) {
        self.inner.middleware.push(Box::new(move |any, req, res| {
            if let Some(app) = any.downcast_mut::<T>() {
                middleware(app, req, res);
            }
        }))
    }

    /// Registers a callback for the given path for GET requests.
    #[inline]
    pub fn get(&mut self, path: &str, callback: TypedCallback<T>) {
        self.insert(Get, path, callback)
    }

    /// Registers a callback for the given path for POST requests.
    #[inline]
    pub fn post(&mut self, path: &str, callback: TypedCallback<T>) {
        self.insert(Post, path, callback)
    }

    /// Registers a callback for the given path for PUT requests.
    #[inline]
    pub fn put(&mut self, path: &str, callback: TypedCallback<T>) {
        self.insert(Put, path, callback)
    }

    /// Registers a callback for the given path for DELETE requests.
    #[inline]
    pub fn delete(&mut self, path: &str, callback: TypedCallback<T>) {
        self.insert(Delete, path, callback)
    }

    /// Registers a callback for the given path for HEAD requests.
    #[inline]
    pub fn head(&mut self, path: &str, callback: TypedCallback<T>) {
        self.insert(Head, path, callback)
    }

    /// Registers a static callback for the given path for GET requests.
    #[inline]
    pub fn get_static(&mut self, path: &str, callback: Static) {
        self.insert_static(Get, path, callback)
    }

    /// Inserts the given callback for the given method and given route.
    #[inline]
    pub fn insert(&mut self, method: Method, path: &str, callback: TypedCallback<T>) {
        self.insert_callback(method, path, Callback::Instance(Box::new(move |any, req, res| {
            let app = any.downcast_mut::<T>().unwrap();
            callback(app, req, res)
        })))
    }

    /// Registers a static callback for the given path for GET requests.
    #[inline]
    pub fn insert_static(&mut self, method: Method, path: &str, callback: Static) {
        self.insert_callback(method, path, Callback::Static(callback))
    }

    /// Inserts the given callback for the given method and given route.
    fn insert_callback(&mut self, method: Method, path: &str, callback: Callback) {
        let route = Route::new(path, callback).unwrap();
        info!("registered callback for {} (parsed as {:?})", path, route);

        self.inner.routes.entry(method).or_insert(Vec::new()).push(route)
    }
}

pub fn get_inner<T>(router: Router<T>) -> RouterAny {
    router.inner
}

/// Signature for a callback method
pub enum Callback {
    Instance(Box<Fn(&mut Any, &Request, &mut Response) -> Result>),
    Static(Static)
}

unsafe impl Sync for Callback {}

pub type Middleware = Box<Fn(&mut Any, &mut Request, &mut Response)>;

/// Router structure
pub struct RouterAny {
    init: fn() -> Box<Any + Send>,
    prefix: Vec<Segment>,
    middleware: Vec<Middleware>,
    routes: HashMap<Method, Vec<Route>>
}

unsafe impl Sync for RouterAny {}

impl RouterAny {
    pub fn new<T: Default + Any + Send>() -> RouterAny {
        RouterAny {
            init: Router::<T>::create,
            prefix: Vec::new(),
            middleware: Vec::new(),
            routes: HashMap::new()
        }
    }

    /// Finds the first route (if any) that matches the given path, and returns the associated callback.
    pub fn find_callback(&self, req: &mut Request) -> Option<&Callback> {
        if self.match_prefix(req.path()) {
            debug!("{} {:?} matches prefix {:?}", req.method(), req.path(), self.prefix);
        } else {
            debug!("{} {:?} does not match prefix {:?}, skipping", req.method(), req.path(), self.prefix);
            return None;
        }

        if let Some(routes) = self.routes.get(req.method()) {
            let mut params = BTreeMap::new();
            let prefix_len = self.prefix.len();

            'top: for ref route in routes {
                let mut it_route = route.segments.iter();
                for actual in &req.path()[prefix_len..] {
                    match it_route.next() {
                        Some(&Segment::Fixed(ref fixed)) if fixed != actual => continue 'top,
                        Some(&Segment::Variable(ref name)) => {
                            params.insert(name.to_owned(), actual.to_string());
                        },
                        _ => ()
                    }
                }

                if it_route.next().is_none() {
                    request::set_params(req, params);
                    return Some(&route.callback);
                }

                params.clear();
            }

            warn!("no route matching method {} path {:?}", req.method(), req.path());
        } else {
            warn!("no routes registered for method {}", req.method());
        }

        None
    }

    /// Returns `true` if the given path matches this router's prefix.
    fn match_prefix(&self, path: &[String]) -> bool {
        if path.len() >= self.prefix.len() {
            // path is longer than prefix
            self.prefix.iter().zip(path.iter()).all(|(segment, component)|
                match segment {
                    &Segment::Fixed(ref value) if value == component => true,
                    _ => false
                })
        } else {
            false
        }
    }

    pub fn new_instance(&self) -> Box<Any + Send> {
        (self.init)()
    }

    pub fn run_middleware(&self, app: &mut Any, req: &mut Request, res: &mut Response) {
        for middleware in &self.middleware {
            middleware(app, req, res);
        }
    }

    pub fn set_prefix(&mut self, prefix: &str) {
        let segments = get_segments(prefix).unwrap();
        if !(segments.len() == 1 && segments[0].is_empty()) {
            self.prefix = segments;
        }
    }
}
<commit_msg>removed unsafe impl in router by using proper "+ Sync" constraint<commit_after>//! Router module

use hyper::Method;
use hyper::method::Method::{Delete, Get, Head, Post, Put};

use std::any::Any;
use std::collections::{BTreeMap, HashMap};
use std::marker::PhantomData;

use request;
use request::Request;
use response::{Result, Response};

use std::result;

pub type TypedCallback<T> = fn(&mut T, &Request, &mut Response) -> Result;
pub type TypedMiddleware<T> = fn(&mut T, &mut Request, &mut Response);
pub type Static = fn(&Request, &mut Response) -> Result;

/// A segment is either a fixed string, or a variable with a name
#[derive(Debug)]
enum Segment {
    Fixed(String),
    Variable(String)
}

impl Segment {
    fn is_empty(&self) -> bool {
        match self {
            &Segment::Fixed(ref fixed) if fixed.len() == 0 => true,
            _ => false
        }
    }
}

/// A route is an absolute URL pattern with a leading slash, and segments separated by slashes.
///
/// A segment that begins with a colon declares a variable, for example "/:user_id".
pub struct Route {
    segments: Vec<Segment>,
    callback: Callback
}

/// Returns a vector of segments from the given string.
fn get_segments(from: &str) -> result::Result<Vec<Segment>, &str> {
    if from.len() == 0 {
        return Err("route must not be empty");
    }
    if &from[0..1] != "/" {
        return Err("route must begin with a slash");
    }

    let stripped = &from[1..];
    Ok(stripped.split('/').map(|segment| if segment.len() > 0 && segment.as_bytes()[0] == b':' {
            Segment::Variable(segment[1..].to_string())
        } else {
            Segment::Fixed(segment.to_string())
        }
    ).collect::<Vec<Segment>>())
}

impl Route {
    fn new(from: &str, callback: Callback) -> result::Result<Route, &str> {
        Ok(Route {
            segments: try!(get_segments(from)),
            callback: callback
        })
    }
}

use std::fmt::{self, Debug, Formatter};

impl Debug for Route {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{:?}", self.segments)
    }
}

/// Router structure
pub struct Router<T> {
    inner: RouterAny,
    _marker: PhantomData<T>
}

impl<T: Default + Any + Send> Router<T> {
    /// wraps the value returned by Default::default into a box
    fn create() -> Box<Any + Send> {
        Box::new(T::default())
    }

    /// Creates a new router.
    pub fn new() -> Router<T> {
        Router {
            inner: RouterAny::new::<T>(),
            _marker: PhantomData
        }
    }

    pub fn add_middleware(&mut self, middleware: TypedMiddleware<T>) {
        self.inner.middleware.push(Box::new(move |any, req, res| {
            if let Some(app) = any.downcast_mut::<T>() {
                middleware(app, req, res);
            }
        }))
    }

    /// Registers a callback for the given path for GET requests.
    #[inline]
    pub fn get(&mut self, path: &str, callback: TypedCallback<T>) {
        self.insert(Get, path, callback)
    }

    /// Registers a callback for the given path for POST requests.
    #[inline]
    pub fn post(&mut self, path: &str, callback: TypedCallback<T>) {
        self.insert(Post, path, callback)
    }

    /// Registers a callback for the given path for PUT requests.
    #[inline]
    pub fn put(&mut self, path: &str, callback: TypedCallback<T>) {
        self.insert(Put, path, callback)
    }

    /// Registers a callback for the given path for DELETE requests.
    #[inline]
    pub fn delete(&mut self, path: &str, callback: TypedCallback<T>) {
        self.insert(Delete, path, callback)
    }

    /// Registers a callback for the given path for HEAD requests.
    #[inline]
    pub fn head(&mut self, path: &str, callback: TypedCallback<T>) {
        self.insert(Head, path, callback)
    }

    /// Registers a static callback for the given path for GET requests.
    #[inline]
    pub fn get_static(&mut self, path: &str, callback: Static) {
        self.insert_static(Get, path, callback)
    }

    /// Inserts the given callback for the given method and given route.
    #[inline]
    pub fn insert(&mut self, method: Method, path: &str, callback: TypedCallback<T>) {
        self.insert_callback(method, path, Callback::Instance(Box::new(move |any, req, res| {
            let app = any.downcast_mut::<T>().unwrap();
            callback(app, req, res)
        })))
    }

    /// Registers a static callback for the given path for GET requests.
    #[inline]
    pub fn insert_static(&mut self, method: Method, path: &str, callback: Static) {
        self.insert_callback(method, path, Callback::Static(callback))
    }

    /// Inserts the given callback for the given method and given route.
    fn insert_callback(&mut self, method: Method, path: &str, callback: Callback) {
        let route = Route::new(path, callback).unwrap();
        info!("registered callback for {} (parsed as {:?})", path, route);

        self.inner.routes.entry(method).or_insert(Vec::new()).push(route)
    }
}

pub fn get_inner<T>(router: Router<T>) -> RouterAny {
    router.inner
}

/// Signature for a callback method
pub enum Callback {
    Instance(Box<Fn(&mut Any, &Request, &mut Response) -> Result + Sync>),
    Static(Static)
}

pub type Middleware = Box<Fn(&mut Any, &mut Request, &mut Response) + Sync>;

/// Router structure
pub struct RouterAny {
    init: fn() -> Box<Any + Send>,
    prefix: Vec<Segment>,
    middleware: Vec<Middleware>,
    routes: HashMap<Method, Vec<Route>>
}

impl RouterAny {
    pub fn new<T: Default + Any + Send>() -> RouterAny {
        RouterAny {
            init: Router::<T>::create,
            prefix: Vec::new(),
            middleware: Vec::new(),
            routes: HashMap::new()
        }
    }

    /// Finds the first route (if any) that matches the given path, and returns the associated callback.
    pub fn find_callback(&self, req: &mut Request) -> Option<&Callback> {
        if self.match_prefix(req.path()) {
            debug!("{} {:?} matches prefix {:?}", req.method(), req.path(), self.prefix);
        } else {
            debug!("{} {:?} does not match prefix {:?}, skipping", req.method(), req.path(), self.prefix);
            return None;
        }

        if let Some(routes) = self.routes.get(req.method()) {
            let mut params = BTreeMap::new();
            let prefix_len = self.prefix.len();

            'top: for ref route in routes {
                let mut it_route = route.segments.iter();
                for actual in &req.path()[prefix_len..] {
                    match it_route.next() {
                        Some(&Segment::Fixed(ref fixed)) if fixed != actual => continue 'top,
                        Some(&Segment::Variable(ref name)) => {
                            params.insert(name.to_owned(), actual.to_string());
                        },
                        _ => ()
                    }
                }

                if it_route.next().is_none() {
                    request::set_params(req, params);
                    return Some(&route.callback);
                }

                params.clear();
            }

            warn!("no route matching method {} path {:?}", req.method(), req.path());
        } else {
            warn!("no routes registered for method {}", req.method());
        }

        None
    }

    /// Returns `true` if the given path matches this router's prefix.
    fn match_prefix(&self, path: &[String]) -> bool {
        if path.len() >= self.prefix.len() {
            // path is longer than prefix
            self.prefix.iter().zip(path.iter()).all(|(segment, component)|
                match segment {
                    &Segment::Fixed(ref value) if value == component => true,
                    _ => false
                })
        } else {
            false
        }
    }

    pub fn new_instance(&self) -> Box<Any + Send> {
        (self.init)()
    }

    pub fn run_middleware(&self, app: &mut Any, req: &mut Request, res: &mut Response) {
        for middleware in &self.middleware {
            middleware(app, req, res);
        }
    }

    pub fn set_prefix(&mut self, prefix: &str) {
        let segments = get_segments(prefix).unwrap();
        if !(segments.len() == 1 && segments[0].is_empty()) {
            self.prefix = segments;
        }
    }
}
<|endoftext|>


<commit_before>use std::mem;

use num::bigint::{self, ToBigInt};
use num::traits::{Zero, One};

use encoding::{Encoding, DecoderTrap};
use encoding::all::ISO_8859_1;

use bertterm::BertTerm;
use error::{Result, BertError};

const BERT_MAGIC_NUMBER: u8 = 131;
const SMALL_INTEGER_EXT: u8 = 97;
const INTEGER_EXT: u8 = 98;
const FLOAT_EXT: u8 = 99;
const ATOM_EXT: u8 = 100;
const SMALL_ATOM_EXT: u8 = 115;
const SMALL_TUPLE_EXT: u8 = 104;
const LARGE_TUPLE_EXT: u8 = 105;
const NIL_EXT: u8 = 106;
const STRING_EXT: u8 = 107;
const LIST_EXT: u8 = 108;
const BINARY_EXT: u8 = 109;
const SMALL_BIG_EXT: u8 = 110;
const LARGE_BIG_EXT: u8 = 111;
const ATOM_UTF8_EXT: u8 = 118;
const SMALL_ATOM_UTF8_EXT: u8 = 119;
const NEW_FLOAT_EXT: u8 = 70;
const MAP_EXT: u8 = 116;

#[derive(Debug)]
pub struct Parser {
    contents: Vec<u8>,
    pos: usize,
}

impl Parser {
    pub fn new(contents: Vec<u8>) -> Parser {
        Parser { contents: contents, pos: 0 }
    }

    pub fn parse(&mut self) -> Result<BertTerm> {
        let () = self.magic_number()?;
        let term = self.bert_term()?;
        if self.eof() {
            return Ok(term);
        } else {
            return Err(BertError::ExtraData(self.pos));
        }
    }

    // Parsers
    fn magic_number(&mut self) -> Result<()> {
        let offset = self.pos;
        let magic = self.eat_u8()?;
        if magic != BERT_MAGIC_NUMBER {
            return Err(BertError::InvalidMagicNumber(offset));
        } else {
            return Ok(());
        }
    }

    fn bert_term(&mut self) -> Result<BertTerm> {
        let offset = self.pos;
        match self.eat_u8()? {
            SMALL_INTEGER_EXT => { self.small_integer() }
            INTEGER_EXT => { self.integer() }
            FLOAT_EXT => { self.old_float() }
            NEW_FLOAT_EXT => { self.new_float() }
            ATOM_EXT => {
                let len = self.eat_u16_be()? as usize;
                self.atom(len)
            }
            SMALL_ATOM_EXT => {
                let len = self.eat_u8()? as usize;
                self.atom(len)
            }
            ATOM_UTF8_EXT => {
                let len = self.eat_u16_be()? as usize;
                self.atom_utf8(len)
            }
            SMALL_ATOM_UTF8_EXT => {
                let len = self.eat_u8()? as usize;
                self.atom_utf8(len)
            }
            SMALL_TUPLE_EXT => {
                let len = self.eat_u8()? as usize;
                self.tuple(len)
            }
            LARGE_TUPLE_EXT => {
                let len = self.eat_u32_be()? as usize;
                self.tuple(len)
            }
            NIL_EXT => { Ok(BertTerm::Nil) }
            LIST_EXT => { self.list() }
            STRING_EXT => { self.string() }
            BINARY_EXT => { self.binary() }
            SMALL_BIG_EXT => {
                let len = self.eat_u8()?;
                self.bigint(len as usize)
            }
            LARGE_BIG_EXT => {
                let len = self.eat_u32_be()?;
                self.bigint(len as usize)
            }
            MAP_EXT => {
                self.map()
            }
            tag => { Err(BertError::InvalidTag(offset, tag)) }
        }
    }

    fn small_integer(&mut self) -> Result<BertTerm> {
        let b = self.eat_u8()?;
        Ok(BertTerm::Int(b as i32))
    }

    fn integer(&mut self) -> Result<BertTerm> {
        let n = self.eat_i32_be()?;
        Ok(BertTerm::Int(n))
    }

    fn old_float(&mut self) -> Result<BertTerm> {
        let offset = self.pos;
        let mut s = String::new();
        while !self.eof() && self.peek()? != 0 {
            s.push(self.eat_char()?);
        }

        while !self.eof() && self.peek()? == 0 {
            let _ = self.eat_u8()?;
        }

        s.parse::<f64>()
            .map_err(|_| BertError::InvalidFloat(offset))
            .map(|f| BertTerm::Float(f))
    }

    fn new_float(&mut self) -> Result<BertTerm> {
        let raw_bytes = self.eat_u64_be()?;
        let f: f64 = unsafe { mem::transmute(raw_bytes) };
        Ok(BertTerm::Float(f))
    }

    fn atom(&mut self, len: usize) -> Result<BertTerm> {
        let offset = self.pos;
        let mut buf: Vec<u8> = Vec::with_capacity(len);
        let mut is_ascii = true;
        for _ in 0 .. len {
            let b = self.eat_u8()?;
            is_ascii = is_ascii && (b < 128);
            buf.push(b);
        }

        // Optimization: ASCII atoms represent the overwhelming
        // majority of use cases of atoms. When we read the bytes
        // of the atom, we record whether they are all ASCII
        // (i.e., less than 128); if it's the case, we don't
        // need to bother with latin-1 decoding. We use an unsafe
        // method because ASCII strings are guaranteed to be valid
        // UTF-8 strings.
        if is_ascii {
            let s = unsafe { String::from_utf8_unchecked(buf) };
            Ok(BertTerm::Atom(s))
        } else {
            ISO_8859_1.decode(&buf, DecoderTrap::Strict)
                .map(|s| BertTerm::Atom(s))
                .map_err(|_| BertError::InvalidLatin1Atom(offset))
        }
    }

    fn atom_utf8(&mut self, len: usize) -> Result<BertTerm> {
        let offset = self.pos;
        let mut buf = Vec::with_capacity(len);
        let mut is_ascii = true;
        for _ in 0 .. len {
            let b = self.eat_u8()?;
            is_ascii = is_ascii && (b < 128);
            buf.push(b);
        }

        if is_ascii {
            let s = unsafe { String::from_utf8_unchecked(buf) };
            Ok(BertTerm::Atom(s))
        } else {
            String::from_utf8(buf)
                .map(|s| BertTerm::Atom(s))
                .map_err(|_| BertError::InvalidUTF8Atom(offset))
        }
    }

    fn tuple(&mut self, len: usize) -> Result<BertTerm> {
        let mut terms = Vec::with_capacity(len);
        for _ in 0 .. len {
            terms.push(self.bert_term()?);
        }
        Ok(BertTerm::Tuple(terms))
    }

    fn string(&mut self) -> Result<BertTerm> {
        let len = self.eat_u16_be()?;
        let mut bytes = Vec::with_capacity(len as usize);
        for _ in 0 .. len {
            bytes.push(self.eat_u8()?);
        }
        Ok(BertTerm::String(bytes))
    }

    fn binary(&mut self) -> Result<BertTerm> {
        let len = self.eat_u32_be()?;
        let mut bytes = Vec::with_capacity(len as usize);
        for _ in 0 .. len {
            bytes.push(self.eat_u8()?);
        }
        Ok(BertTerm::Binary(bytes))
    }

    fn list(&mut self) -> Result<BertTerm> {
        let len = self.eat_u32_be()?;
        let mut terms = Vec::with_capacity(len as usize + 1);
        for _ in 0 .. len {
            terms.push(self.bert_term()?);
        }
        let tail = self.bert_term()?;
        match tail {
            BertTerm::Nil => (),
            last_term => { terms.push(last_term); }
        };
        Ok(BertTerm::List(terms))
    }

    fn bigint(&mut self, len: usize) -> Result<BertTerm> {
        let sign = self.eat_u8()?;
        let mut sum: bigint::BigInt = Zero::zero();
        let mut pos: bigint::BigInt = One::one();
        for _ in 0 .. len {
            let d = self.eat_u8()?;
            let t = &pos * &(d.to_bigint().unwrap());
            sum = sum + &t;
            pos = pos * (256).to_bigint().unwrap();
        }
        if sign == 1 {
            sum = -sum;
        }
        Ok(BertTerm::BigInt(sum))
    }

    // TODO(vfoley): ensure no duplicate keys
    fn map(&mut self) -> Result<BertTerm> {
        let len = self.eat_u32_be()? as usize;
        let mut keys = Vec::with_capacity(len);
        let mut vals = Vec::with_capacity(len);
        for _ in 0 .. len {
            keys.push(self.bert_term()?);
            vals.push(self.bert_term()?);
        }
        Ok(BertTerm::Map(keys, vals))
    }

    // Low-level parsing methods
    fn eof(&self) -> bool {
        self.pos >= self.contents.len()
    }

    fn peek(&self) -> Result<u8> {
        if self.eof() {
            return Err(BertError::EOF(self.pos));
        } else {
            return Ok(self.contents[self.pos]);
        }
    }

    fn eat_u8(&mut self) -> Result<u8> {
        let b = self.peek()?;
        self.pos += 1;
        return Ok(b);
    }

    fn eat_char(&mut self) -> Result<char> {
        let b = self.eat_u8()?;
        return Ok(b as char);
    }

    fn eat_u16_be(&mut self) -> Result<u16> {
        let b0 = self.eat_u8()? as u16;
        let b1 = self.eat_u8()? as u16;
        return Ok((b0 << 8) + b1)
    }

    fn eat_i32_be(&mut self) -> Result<i32> {
        let b0 = self.eat_u8()? as i32;
        let b1 = self.eat_u8()? as i32;
        let b2 = self.eat_u8()? as i32;
        let b3 = self.eat_u8()? as i32;
        return Ok((b0 << 24) + (b1 << 16) + (b2 << 8) + b3)
    }

    fn eat_u32_be(&mut self) -> Result<u32> {
        let b0 = self.eat_u8()? as u32;
        let b1 = self.eat_u8()? as u32;
        let b2 = self.eat_u8()? as u32;
        let b3 = self.eat_u8()? as u32;
        return Ok((b0 << 24) + (b1 << 16) + (b2 << 8) + b3)
    }

    fn eat_u64_be(&mut self) -> Result<u64> {
        let mut n: u64 = 0;
        n += (self.eat_u8()? as u64) << 56;
        n += (self.eat_u8()? as u64) << 48;
        n += (self.eat_u8()? as u64) << 40;
        n += (self.eat_u8()? as u64) << 32;
        n += (self.eat_u8()? as u64) << 24;
        n += (self.eat_u8()? as u64) << 16;
        n += (self.eat_u8()? as u64) << 8;
        n += self.eat_u8()? as u64;
        return Ok(n);
    }
}
<commit_msg>Use .iter_mut() to fill atom buffer w/o bounds checking<commit_after>use std::mem;

use num::bigint::{self, ToBigInt};
use num::traits::{Zero, One};

use encoding::{Encoding, DecoderTrap};
use encoding::all::ISO_8859_1;

use bertterm::BertTerm;
use error::{Result, BertError};

const BERT_MAGIC_NUMBER: u8 = 131;
const SMALL_INTEGER_EXT: u8 = 97;
const INTEGER_EXT: u8 = 98;
const FLOAT_EXT: u8 = 99;
const ATOM_EXT: u8 = 100;
const SMALL_ATOM_EXT: u8 = 115;
const SMALL_TUPLE_EXT: u8 = 104;
const LARGE_TUPLE_EXT: u8 = 105;
const NIL_EXT: u8 = 106;
const STRING_EXT: u8 = 107;
const LIST_EXT: u8 = 108;
const BINARY_EXT: u8 = 109;
const SMALL_BIG_EXT: u8 = 110;
const LARGE_BIG_EXT: u8 = 111;
const ATOM_UTF8_EXT: u8 = 118;
const SMALL_ATOM_UTF8_EXT: u8 = 119;
const NEW_FLOAT_EXT: u8 = 70;
const MAP_EXT: u8 = 116;

#[derive(Debug)]
pub struct Parser {
    contents: Vec<u8>,
    pos: usize,
}

impl Parser {
    pub fn new(contents: Vec<u8>) -> Parser {
        Parser { contents: contents, pos: 0 }
    }

    pub fn parse(&mut self) -> Result<BertTerm> {
        let () = self.magic_number()?;
        let term = self.bert_term()?;
        if self.eof() {
            return Ok(term);
        } else {
            return Err(BertError::ExtraData(self.pos));
        }
    }

    // Parsers
    fn magic_number(&mut self) -> Result<()> {
        let offset = self.pos;
        let magic = self.eat_u8()?;
        if magic != BERT_MAGIC_NUMBER {
            return Err(BertError::InvalidMagicNumber(offset));
        } else {
            return Ok(());
        }
    }

    fn bert_term(&mut self) -> Result<BertTerm> {
        let offset = self.pos;
        match self.eat_u8()? {
            SMALL_INTEGER_EXT => { self.small_integer() }
            INTEGER_EXT => { self.integer() }
            FLOAT_EXT => { self.old_float() }
            NEW_FLOAT_EXT => { self.new_float() }
            ATOM_EXT => {
                let len = self.eat_u16_be()? as usize;
                self.atom(len)
            }
            SMALL_ATOM_EXT => {
                let len = self.eat_u8()? as usize;
                self.atom(len)
            }
            ATOM_UTF8_EXT => {
                let len = self.eat_u16_be()? as usize;
                self.atom_utf8(len)
            }
            SMALL_ATOM_UTF8_EXT => {
                let len = self.eat_u8()? as usize;
                self.atom_utf8(len)
            }
            SMALL_TUPLE_EXT => {
                let len = self.eat_u8()? as usize;
                self.tuple(len)
            }
            LARGE_TUPLE_EXT => {
                let len = self.eat_u32_be()? as usize;
                self.tuple(len)
            }
            NIL_EXT => { Ok(BertTerm::Nil) }
            LIST_EXT => { self.list() }
            STRING_EXT => { self.string() }
            BINARY_EXT => { self.binary() }
            SMALL_BIG_EXT => {
                let len = self.eat_u8()?;
                self.bigint(len as usize)
            }
            LARGE_BIG_EXT => {
                let len = self.eat_u32_be()?;
                self.bigint(len as usize)
            }
            MAP_EXT => {
                self.map()
            }
            tag => { Err(BertError::InvalidTag(offset, tag)) }
        }
    }

    fn small_integer(&mut self) -> Result<BertTerm> {
        let b = self.eat_u8()?;
        Ok(BertTerm::Int(b as i32))
    }

    fn integer(&mut self) -> Result<BertTerm> {
        let n = self.eat_i32_be()?;
        Ok(BertTerm::Int(n))
    }

    fn old_float(&mut self) -> Result<BertTerm> {
        let offset = self.pos;
        let mut s = String::new();
        while !self.eof() && self.peek()? != 0 {
            s.push(self.eat_char()?);
        }

        while !self.eof() && self.peek()? == 0 {
            let _ = self.eat_u8()?;
        }

        s.parse::<f64>()
            .map_err(|_| BertError::InvalidFloat(offset))
            .map(|f| BertTerm::Float(f))
    }

    fn new_float(&mut self) -> Result<BertTerm> {
        let raw_bytes = self.eat_u64_be()?;
        let f: f64 = unsafe { mem::transmute(raw_bytes) };
        Ok(BertTerm::Float(f))
    }

    fn atom(&mut self, len: usize) -> Result<BertTerm> {
        let offset = self.pos;
        let mut buf: Vec<u8> = vec![0; len];
        let mut is_ascii = true;
        for p in buf.iter_mut() {
            let b = self.eat_u8()?;
            is_ascii = is_ascii && (b < 128);
            *p = b;
        }

        // Optimization: ASCII atoms represent the overwhelming
        // majority of use cases of atoms. When we read the bytes
        // of the atom, we record whether they are all ASCII
        // (i.e., less than 128); if it's the case, we don't
        // need to bother with latin-1 decoding. We use an unsafe
        // method because ASCII strings are guaranteed to be valid
        // UTF-8 strings.
        if is_ascii {
            let s = unsafe { String::from_utf8_unchecked(buf) };
            Ok(BertTerm::Atom(s))
        } else {
            ISO_8859_1.decode(&buf, DecoderTrap::Strict)
                .map(|s| BertTerm::Atom(s))
                .map_err(|_| BertError::InvalidLatin1Atom(offset))
        }
    }

    fn atom_utf8(&mut self, len: usize) -> Result<BertTerm> {
        let offset = self.pos;
        let mut buf: Vec<u8> = vec![0; len];
        let mut is_ascii = true;
        for p in buf.iter_mut() {
            let b = self.eat_u8()?;
            is_ascii = is_ascii && (b < 128);
            *p = b;
        }

        if is_ascii {
            let s = unsafe { String::from_utf8_unchecked(buf) };
            Ok(BertTerm::Atom(s))
        } else {
            String::from_utf8(buf)
                .map(|s| BertTerm::Atom(s))
                .map_err(|_| BertError::InvalidUTF8Atom(offset))
        }
    }

    fn tuple(&mut self, len: usize) -> Result<BertTerm> {
        let mut terms = Vec::with_capacity(len);
        for _ in 0 .. len {
            terms.push(self.bert_term()?);
        }
        Ok(BertTerm::Tuple(terms))
    }

    fn string(&mut self) -> Result<BertTerm> {
        let len = self.eat_u16_be()?;
        let mut bytes = Vec::with_capacity(len as usize);
        for _ in 0 .. len {
            bytes.push(self.eat_u8()?);
        }
        Ok(BertTerm::String(bytes))
    }

    fn binary(&mut self) -> Result<BertTerm> {
        let len = self.eat_u32_be()?;
        let mut bytes = Vec::with_capacity(len as usize);
        for _ in 0 .. len {
            bytes.push(self.eat_u8()?);
        }
        Ok(BertTerm::Binary(bytes))
    }

    fn list(&mut self) -> Result<BertTerm> {
        let len = self.eat_u32_be()?;
        let mut terms = Vec::with_capacity(len as usize + 1);
        for _ in 0 .. len {
            terms.push(self.bert_term()?);
        }
        let tail = self.bert_term()?;
        match tail {
            BertTerm::Nil => (),
            last_term => { terms.push(last_term); }
        };
        Ok(BertTerm::List(terms))
    }

    fn bigint(&mut self, len: usize) -> Result<BertTerm> {
        let sign = self.eat_u8()?;
        let mut sum: bigint::BigInt = Zero::zero();
        let mut pos: bigint::BigInt = One::one();
        for _ in 0 .. len {
            let d = self.eat_u8()?;
            let t = &pos * &(d.to_bigint().unwrap());
            sum = sum + &t;
            pos = pos * (256).to_bigint().unwrap();
        }
        if sign == 1 {
            sum = -sum;
        }
        Ok(BertTerm::BigInt(sum))
    }

    // TODO(vfoley): ensure no duplicate keys
    fn map(&mut self) -> Result<BertTerm> {
        let len = self.eat_u32_be()? as usize;
        let mut keys = Vec::with_capacity(len);
        let mut vals = Vec::with_capacity(len);
        for _ in 0 .. len {
            keys.push(self.bert_term()?);
            vals.push(self.bert_term()?);
        }
        Ok(BertTerm::Map(keys, vals))
    }

    // Low-level parsing methods
    fn eof(&self) -> bool {
        self.pos >= self.contents.len()
    }

    fn peek(&self) -> Result<u8> {
        if self.eof() {
            return Err(BertError::EOF(self.pos));
        } else {
            return Ok(self.contents[self.pos]);
        }
    }

    fn eat_u8(&mut self) -> Result<u8> {
        let b = self.peek()?;
        self.pos += 1;
        return Ok(b);
    }

    fn eat_char(&mut self) -> Result<char> {
        let b = self.eat_u8()?;
        return Ok(b as char);
    }

    fn eat_u16_be(&mut self) -> Result<u16> {
        let b0 = self.eat_u8()? as u16;
        let b1 = self.eat_u8()? as u16;
        return Ok((b0 << 8) + b1)
    }

    fn eat_i32_be(&mut self) -> Result<i32> {
        let b0 = self.eat_u8()? as i32;
        let b1 = self.eat_u8()? as i32;
        let b2 = self.eat_u8()? as i32;
        let b3 = self.eat_u8()? as i32;
        return Ok((b0 << 24) + (b1 << 16) + (b2 << 8) + b3)
    }

    fn eat_u32_be(&mut self) -> Result<u32> {
        let b0 = self.eat_u8()? as u32;
        let b1 = self.eat_u8()? as u32;
        let b2 = self.eat_u8()? as u32;
        let b3 = self.eat_u8()? as u32;
        return Ok((b0 << 24) + (b1 << 16) + (b2 << 8) + b3)
    }

    fn eat_u64_be(&mut self) -> Result<u64> {
        let mut n: u64 = 0;
        n += (self.eat_u8()? as u64) << 56;
        n += (self.eat_u8()? as u64) << 48;
        n += (self.eat_u8()? as u64) << 40;
        n += (self.eat_u8()? as u64) << 32;
        n += (self.eat_u8()? as u64) << 24;
        n += (self.eat_u8()? as u64) << 16;
        n += (self.eat_u8()? as u64) << 8;
        n += self.eat_u8()? as u64;
        return Ok(n);
    }
}
<|endoftext|>