<commit_before>
// Copyright 2017 The gltf Library Developers
//
// 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 import;
use json;
use root;
use std::{fmt, iter, ops, slice};

use accessor::Accessor;
use animation::Animation;
use buffer::{Buffer, View};
use camera::Camera;
use image::Image;
use material::Material;
use mesh::Mesh;
use scene::{Node, Scene};
use skin::Skin;
use texture::{Sampler, Texture};

/// A loaded glTF complete with its data.
pub struct Gltf {
    /// The glTF buffer data.
    buffer_data: Vec<import::Data>,

    /// The glTF image data.
    image_data: Vec<import::DynamicImage>,

    /// The root glTF struct (and also `Deref` target).
    root: root::Root,
}

/// An `Iterator` that visits every accessor in a glTF asset.
#[derive(Clone, Debug)]
pub struct Accessors<'a> {
    /// Internal accessor iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::accessor::Accessor>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every animation in a glTF asset.
#[derive(Clone, Debug)]
pub struct Animations<'a> {
    /// Internal animation iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::animation::Animation>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every buffer in a glTF asset.
#[derive(Clone, Debug)]
pub struct Buffers<'a> {
    /// Internal buffer iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::buffer::Buffer>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every buffer view in a glTF asset.
#[derive(Clone, Debug)]
pub struct Views<'a> {
    /// Internal buffer view iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::buffer::View>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every camera in a glTF asset.
#[derive(Clone, Debug)]
pub struct Cameras<'a> {
    /// Internal buffer view iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::camera::Camera>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every pre-loaded image in a glTF asset.
#[derive(Clone, Debug)]
pub struct Images<'a> {
    /// Internal image iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::image::Image>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every material in a glTF asset.
#[derive(Clone, Debug)]
pub struct Materials<'a> {
    /// Internal material iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::material::Material>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every mesh in a glTF asset.
#[derive(Clone, Debug)]
pub struct Meshes<'a> {
    /// Internal mesh iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::mesh::Mesh>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every node in a glTF asset.
#[derive(Clone, Debug)]
pub struct Nodes<'a> {
    /// Internal node iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::scene::Node>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every sampler in a glTF asset.
#[derive(Clone, Debug)]
pub struct Samplers<'a> {
    /// Internal sampler iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::texture::Sampler>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every scene in a glTF asset.
#[derive(Clone, Debug)]
pub struct Scenes<'a> {
    /// Internal scene iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::scene::Scene>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every skin in a glTF asset.
#[derive(Clone, Debug)]
pub struct Skins<'a> {
    /// Internal skin iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::skin::Skin>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every texture in a glTF asset.
#[derive(Clone, Debug)]
pub struct Textures<'a> {
    /// Internal texture iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::texture::Texture>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

impl Gltf {
    /// Constructor for a complete lazy-loaded glTF asset.
    pub fn new(
        root: root::Root,
        buffer_data: Vec<import::Data>,
        image_data: Vec<import::DynamicImage>,
    ) -> Self {
        Self {
            buffer_data: buffer_data,
            image_data: image_data,
            root: root,
        }
    }

    /// Returns preloaded buffer data.
    ///
    /// # Panics
    ///
    /// Panics if the index is out of range.
    pub fn buffer_data(&self, index: usize) -> import::Data {
        self.buffer_data[index].clone()
    }

    /// Returns preloaded image data.
    ///
    /// # Panics
    ///
    /// Panics if the index is out of range.
    pub fn image_data<'a>(&'a self, index: usize) -> &'a import::DynamicImage {
        &self.image_data[index]
    }

    /// Returns an `Iterator` that visits the accessors of the glTF asset.
    pub fn accessors<'a>(&'a self) -> Accessors<'a> {
        Accessors {
            iter: self.as_json().accessors.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the animations of the glTF asset.
    pub fn animations<'a>(&'a self) -> Animations<'a> {
        Animations {
            iter: self.as_json().animations.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the pre-loaded buffers of the glTF asset.
    pub fn buffers<'a>(&'a self) -> Buffers<'a> {
        Buffers {
            iter: self.as_json().buffers.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the pre-loaded buffer views of the glTF
    /// asset.
    pub fn views<'a>(&'a self) -> Views<'a> {
        Views {
            iter: self.as_json().buffer_views.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the cameras of the glTF asset.
    pub fn cameras<'a>(&'a self) -> Cameras<'a> {
        Cameras {
            iter: self.as_json().cameras.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the pre-loaded images of the glTF asset.
    pub fn images<'a>(&'a self) -> Images<'a> {
        Images {
            iter: self.as_json().images.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the materials of the glTF asset.
    pub fn materials<'a>(&'a self) -> Materials<'a> {
        Materials {
            iter: self.as_json().materials.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the meshes of the glTF asset.
    pub fn meshes<'a>(&'a self) -> Meshes<'a> {
        Meshes {
            iter: self.as_json().meshes.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the nodes of the glTF asset.
    pub fn nodes<'a>(&'a self) -> Nodes<'a> {
        Nodes {
            iter: self.as_json().nodes.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the scenes of the glTF asset.
    pub fn samplers<'a>(&'a self) -> Samplers<'a> {
        Samplers {
            iter: self.as_json().samplers.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the samplers of the glTF asset.
    pub fn scenes<'a>(&'a self) -> Scenes<'a> {
        Scenes {
            iter: self.as_json().scenes.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the skins of the glTF asset.
    pub fn skins<'a>(&'a self) -> Skins<'a> {
        Skins {
            iter: self.as_json().skins.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the textures of the glTF asset.
    pub fn textures<'a>(&'a self) -> Textures<'a> {
        Textures {
            iter: self.as_json().textures.iter().enumerate(),
            gltf: self,
        }
    }
}

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

impl ops::Deref for Gltf {
    type Target = root::Root;
    fn deref(&self) -> &Self::Target {
        &self.root
    }
}

impl<'a> Iterator for Accessors<'a> {
    type Item = Accessor<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Accessor::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Animations<'a> {
    type Item = Animation<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Animation::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Buffers<'a> {
    type Item = Buffer<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Buffer::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Views<'a> {
    type Item = View<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| View::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Cameras<'a> {
    type Item = Camera<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Camera::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Images<'a> {
    type Item = Image<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Image::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Materials<'a> {
    type Item = Material<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Material::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Meshes<'a> {
    type Item = Mesh<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Mesh::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Nodes<'a> {
    type Item = Node<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Node::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Samplers<'a> {
    type Item = Sampler<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Sampler::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Scenes<'a> {
    type Item = Scene<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Scene::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Skins<'a> {
    type Item = Skin<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Skin::new(self.gltf, index, json))
    }
}

impl<'a> Iterator for Textures<'a> {
    type Item = Texture<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Texture::new(self.gltf, index, json))
    }
}
<commit_msg>Implement ExactSizeIterator for top-level iterators<commit_after>
// Copyright 2017 The gltf Library Developers
//
// 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 import;
use json;
use root;
use std::{fmt, iter, ops, slice};

use accessor::Accessor;
use animation::Animation;
use buffer::{Buffer, View};
use camera::Camera;
use image::Image;
use material::Material;
use mesh::Mesh;
use scene::{Node, Scene};
use skin::Skin;
use texture::{Sampler, Texture};

/// A loaded glTF complete with its data.
pub struct Gltf {
    /// The glTF buffer data.
    buffer_data: Vec<import::Data>,

    /// The glTF image data.
    image_data: Vec<import::DynamicImage>,

    /// The root glTF struct (and also `Deref` target).
    root: root::Root,
}

/// An `Iterator` that visits every accessor in a glTF asset.
#[derive(Clone, Debug)]
pub struct Accessors<'a> {
    /// Internal accessor iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::accessor::Accessor>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every animation in a glTF asset.
#[derive(Clone, Debug)]
pub struct Animations<'a> {
    /// Internal animation iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::animation::Animation>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every buffer in a glTF asset.
#[derive(Clone, Debug)]
pub struct Buffers<'a> {
    /// Internal buffer iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::buffer::Buffer>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every buffer view in a glTF asset.
#[derive(Clone, Debug)]
pub struct Views<'a> {
    /// Internal buffer view iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::buffer::View>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every camera in a glTF asset.
#[derive(Clone, Debug)]
pub struct Cameras<'a> {
    /// Internal buffer view iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::camera::Camera>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every pre-loaded image in a glTF asset.
#[derive(Clone, Debug)]
pub struct Images<'a> {
    /// Internal image iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::image::Image>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every material in a glTF asset.
#[derive(Clone, Debug)]
pub struct Materials<'a> {
    /// Internal material iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::material::Material>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every mesh in a glTF asset.
#[derive(Clone, Debug)]
pub struct Meshes<'a> {
    /// Internal mesh iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::mesh::Mesh>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every node in a glTF asset.
#[derive(Clone, Debug)]
pub struct Nodes<'a> {
    /// Internal node iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::scene::Node>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every sampler in a glTF asset.
#[derive(Clone, Debug)]
pub struct Samplers<'a> {
    /// Internal sampler iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::texture::Sampler>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every scene in a glTF asset.
#[derive(Clone, Debug)]
pub struct Scenes<'a> {
    /// Internal scene iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::scene::Scene>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every skin in a glTF asset.
#[derive(Clone, Debug)]
pub struct Skins<'a> {
    /// Internal skin iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::skin::Skin>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

/// An `Iterator` that visits every texture in a glTF asset.
#[derive(Clone, Debug)]
pub struct Textures<'a> {
    /// Internal texture iterator.
    iter: iter::Enumerate<slice::Iter<'a, json::texture::Texture>>,

    /// The internal root glTF object.
    gltf: &'a Gltf,
}

impl Gltf {
    /// Constructor for a complete lazy-loaded glTF asset.
    pub fn new(
        root: root::Root,
        buffer_data: Vec<import::Data>,
        image_data: Vec<import::DynamicImage>,
    ) -> Self {
        Self {
            buffer_data: buffer_data,
            image_data: image_data,
            root: root,
        }
    }

    /// Returns preloaded buffer data.
    ///
    /// # Panics
    ///
    /// Panics if the index is out of range.
    pub fn buffer_data(&self, index: usize) -> import::Data {
        self.buffer_data[index].clone()
    }

    /// Returns preloaded image data.
    ///
    /// # Panics
    ///
    /// Panics if the index is out of range.
    pub fn image_data<'a>(&'a self, index: usize) -> &'a import::DynamicImage {
        &self.image_data[index]
    }

    /// Returns an `Iterator` that visits the accessors of the glTF asset.
    pub fn accessors<'a>(&'a self) -> Accessors<'a> {
        Accessors {
            iter: self.as_json().accessors.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the animations of the glTF asset.
    pub fn animations<'a>(&'a self) -> Animations<'a> {
        Animations {
            iter: self.as_json().animations.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the pre-loaded buffers of the glTF asset.
    pub fn buffers<'a>(&'a self) -> Buffers<'a> {
        Buffers {
            iter: self.as_json().buffers.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the pre-loaded buffer views of the glTF
    /// asset.
    pub fn views<'a>(&'a self) -> Views<'a> {
        Views {
            iter: self.as_json().buffer_views.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the cameras of the glTF asset.
    pub fn cameras<'a>(&'a self) -> Cameras<'a> {
        Cameras {
            iter: self.as_json().cameras.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the pre-loaded images of the glTF asset.
    pub fn images<'a>(&'a self) -> Images<'a> {
        Images {
            iter: self.as_json().images.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the materials of the glTF asset.
    pub fn materials<'a>(&'a self) -> Materials<'a> {
        Materials {
            iter: self.as_json().materials.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the meshes of the glTF asset.
    pub fn meshes<'a>(&'a self) -> Meshes<'a> {
        Meshes {
            iter: self.as_json().meshes.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the nodes of the glTF asset.
    pub fn nodes<'a>(&'a self) -> Nodes<'a> {
        Nodes {
            iter: self.as_json().nodes.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the scenes of the glTF asset.
    pub fn samplers<'a>(&'a self) -> Samplers<'a> {
        Samplers {
            iter: self.as_json().samplers.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the samplers of the glTF asset.
    pub fn scenes<'a>(&'a self) -> Scenes<'a> {
        Scenes {
            iter: self.as_json().scenes.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the skins of the glTF asset.
    pub fn skins<'a>(&'a self) -> Skins<'a> {
        Skins {
            iter: self.as_json().skins.iter().enumerate(),
            gltf: self,
        }
    }

    /// Returns an `Iterator` that visits the textures of the glTF asset.
    pub fn textures<'a>(&'a self) -> Textures<'a> {
        Textures {
            iter: self.as_json().textures.iter().enumerate(),
            gltf: self,
        }
    }
}

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

impl ops::Deref for Gltf {
    type Target = root::Root;
    fn deref(&self) -> &Self::Target {
        &self.root
    }
}

impl<'a> ExactSizeIterator for Accessors<'a> {}
impl<'a> Iterator for Accessors<'a> {
    type Item = Accessor<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Accessor::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Animations<'a> {}
impl<'a> Iterator for Animations<'a> {
    type Item = Animation<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Animation::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Buffers<'a> {}
impl<'a> Iterator for Buffers<'a> {
    type Item = Buffer<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Buffer::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Views<'a> {}
impl<'a> Iterator for Views<'a> {
    type Item = View<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| View::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Cameras<'a> {}
impl<'a> Iterator for Cameras<'a> {
    type Item = Camera<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Camera::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Images<'a> {}
impl<'a> Iterator for Images<'a> {
    type Item = Image<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Image::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Materials<'a> {}
impl<'a> Iterator for Materials<'a> {
    type Item = Material<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Material::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Meshes<'a> {}
impl<'a> Iterator for Meshes<'a> {
    type Item = Mesh<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Mesh::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Nodes<'a> {}
impl<'a> Iterator for Nodes<'a> {
    type Item = Node<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Node::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Samplers<'a> {}
impl<'a> Iterator for Samplers<'a> {
    type Item = Sampler<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Sampler::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Scenes<'a> {}
impl<'a> Iterator for Scenes<'a> {
    type Item = Scene<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Scene::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Skins<'a> {}
impl<'a> Iterator for Skins<'a> {
    type Item = Skin<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Skin::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> ExactSizeIterator for Textures<'a> {}
impl<'a> Iterator for Textures<'a> {
    type Item = Texture<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(index, json)| Texture::new(self.gltf, index, json))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
// Copyright 2013-2015 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
pub fn get_nstime() -> u64 {
    use std::time::{SystemTime, UNIX_EPOCH};

    let dur = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
    // The correct way to calculate the current time is
    // `dur.as_secs() * 1_000_000_000 + dur.subsec_nanos() as u64`
    // But this is faster, and the difference in terms of entropy is
    // negligible (log2(10^9) == 29.9).
    dur.as_secs() << 30 | dur.subsec_nanos() as u64
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub fn get_nstime() -> u64 {
    use libc;

    // On Mac OS and iOS std::time::SystemTime only has 1000ns resolution.
    // We use `mach_absolute_time` instead. This provides a CPU dependent
    // unit, to get real nanoseconds the result should by multiplied by
    // numer/denom from `mach_timebase_info`.
    // But we are not interested in the exact nanoseconds, just entropy. So
    // we use the raw result.
    unsafe { libc::mach_absolute_time() }
}

#[cfg(target_os = "windows")]
pub fn get_nstime() -> u64 {
    unsafe {
        let mut t = super::mem::zeroed();
        winapi::um::profileapi::QueryPerformanceCounter(&mut t);
        *t.QuadPart() as u64
    }
}
<commit_msg>Fix rand_jitter on windows for older rust versions<commit_after>// Copyright 2018 Developers of the Rand project.
// Copyright 2013-2015 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
pub fn get_nstime() -> u64 {
    use std::time::{SystemTime, UNIX_EPOCH};

    let dur = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
    // The correct way to calculate the current time is
    // `dur.as_secs() * 1_000_000_000 + dur.subsec_nanos() as u64`
    // But this is faster, and the difference in terms of entropy is
    // negligible (log2(10^9) == 29.9).
    dur.as_secs() << 30 | dur.subsec_nanos() as u64
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub fn get_nstime() -> u64 {
    use libc;

    // On Mac OS and iOS std::time::SystemTime only has 1000ns resolution.
    // We use `mach_absolute_time` instead. This provides a CPU dependent
    // unit, to get real nanoseconds the result should by multiplied by
    // numer/denom from `mach_timebase_info`.
    // But we are not interested in the exact nanoseconds, just entropy. So
    // we use the raw result.
    unsafe { libc::mach_absolute_time() }
}

#[cfg(target_os = "windows")]
pub fn get_nstime() -> u64 {
    use winapi;

    unsafe {
        let mut t = super::mem::zeroed();
        winapi::um::profileapi::QueryPerformanceCounter(&mut t);
        *t.QuadPart() as u64
    }
}
<|endoftext|>


<commit_before>use pulldown_cmark::{Event, Tag};

#[derive(Debug)]
struct Consumer<'a, I> {
    iter: I,
    buffer: String,
    current: Option<Tag<'a>>,
}

impl<'a, I: Iterator<Item = Event<'a>>> Consumer<'a, I> {
    fn consume(&mut self) -> String {
        while let Some(event) = self.iter.next() {
            debug!("{:?}", event);
            match event {
                Event::Start(tag) => {
                    self.buffer.push_str(&print_start_elem(&tag));
                    self.current = Some(tag);
                }
                Event::End(tag) => self.buffer.push_str(&print_end_elem(&tag)),
                Event::Text(text) => {
                    if let Some(tag) = self.current.clone() {
                        match tag {
                            Tag::Header(_) => {
                                let to_add =
                                    format!("{}\"> {}", name_to_id(&text.to_string()), text);
                                self.buffer.push_str(&to_add)
                            }
                            Tag::Image(_, _) => self.buffer.push_str(&format!(" alt=\"{}\"", text)),
                            _ => self.buffer.push_str(&text),
                        }
                    } else {
                        self.buffer.push_str(&text)
                    }
                }
                Event::Html(content) => self.buffer.push_str(&content.to_string()),
                elem => warn!("Unhandled type: {:?}", elem),
            }
        }
        self.buffer.clone()
    }
}

fn print_start_elem(tag: &Tag) -> String {
    let result = match tag {
        &Tag::Header(int) => format!("<h{} id=\"", int),
        &Tag::Strong => "".to_string(),
        &Tag::Emphasis => "".to_string(),
        &Tag::Item => "
".to_string(),
        &Tag::List(_) => "
".to_string(),
        &Tag::Paragraph => "
".to_string(),
        &Tag::Image(ref src, _) => format!(" "".to_string(),
        &Tag::CodeBlock(ref lang) => format!("
", lang),
        &Tag::Link(ref href, _) => format!("", href),
        // TODO Handle alignment
        &Tag::Table(_) => "
".to_string(),
        &Tag::TableHead => "
".to_string(),
        &Tag::TableCell => "".to_string(),
        &Tag::TableRow => "
".to_string(),
        tag => {
            warn!("{:?} tag is unimplemented", tag);
            unimplemented!();
        }
    };

    debug!("{:?}", result);
    result
}

fn print_end_elem(tag: &Tag) -> String {
    let result = match tag {
        &Tag::Header(int) => format!("</h{}>\n", int),
        &Tag::Strong => "\n".to_string(),
        &Tag::Emphasis => "\n".to_string(),
        &Tag::Item => "
\n".to_string(),
        &Tag::List(_) => "
\n".to_string(),
        &Tag::Paragraph => "
\n".to_string(),
        &Tag::Image(_, _) => "/>\n".to_string(),
        &Tag::Code => "\n".to_string(),
        &Tag::CodeBlock(_) => "
\n".to_string(),
        &Tag::Link(_, _) => "\n".to_string(),
        // TODO Handle alignment
        &Tag::Table(_) => "
\n".to_string(),
        &Tag::TableHead => "
\n".to_string(),
        &Tag::TableCell => "	\n".to_string(),
        &Tag::TableRow => "
\n".to_string(),
        tag => {
            warn!("{:?} tag is unimplemented", tag);
            unimplemented!();
        }
    };

    debug!("{:?}", result);
    result
}

fn name_to_id(name: &str) -> String {
    name.to_lowercase().replace(" ", "-")
}

pub fn consume<'a, I: Iterator<Item = Event<'a>>>(iter: I) -> String {
    let mut consumer = Consumer {
        iter: iter,
        buffer: String::new(),
        current: None,
    };
    consumer.consume()
}

#[cfg(test)]
mod tests {
    use test_utils;
    #[test]
    fn test_name_to_id() {
        let actual = super::name_to_id("A very lOng name or Heading");
        assert_eq!("a-very-long-name-or-heading", actual);
    }

    #[test]
    fn test_consume() {
        use pulldown_cmark::Parser;
        use pulldown_cmark::OPTION_ENABLE_TABLES;
        use std::fs::File;
        use std::io::Read;

        let mut content = String::new();
        File::open("resources/all_test.md")
            .and_then(|mut x| x.read_to_string(&mut content))
            .unwrap();
        let parser = Parser::new_ext(&content, OPTION_ENABLE_TABLES);

        let actual = super::consume(parser);
        let expected = include_str!("../tests/resources/all_test_raw_good.html");
        test_utils::compare_string_content(expected, &actual);
    }
}
<commit_msg>Added soft break handling.<commit_after>use pulldown_cmark::{Event, Tag};

#[derive(Debug)]
struct Consumer<'a, I> {
    iter: I,
    buffer: String,
    current: Option<Tag<'a>>,
}

impl<'a, I: Iterator<Item = Event<'a>>> Consumer<'a, I> {
    fn consume(&mut self) -> String {
        while let Some(event) = self.iter.next() {
            debug!("{:?}", event);
            match event {
                Event::Start(tag) => {
                    self.buffer.push_str(&print_start_elem(&tag));
                    self.current = Some(tag);
                }
                Event::End(tag) => self.buffer.push_str(&print_end_elem(&tag)),
                Event::Text(text) => {
                    if let Some(tag) = self.current.clone() {
                        match tag {
                            Tag::Header(_) => {
                                let to_add =
                                    format!("{}\"> {}", name_to_id(&text.to_string()), text);
                                self.buffer.push_str(&to_add)
                            }
                            Tag::Image(_, _) => self.buffer.push_str(&format!(" alt=\"{}\"", text)),
                            _ => self.buffer.push_str(&text),
                        }
                    } else {
                        self.buffer.push_str(&text)
                    }
                }
                Event::Html(content) => self.buffer.push_str(&content.to_string()),
                Event::SoftBreak => self.buffer.push_str(" "),
                elem => warn!("Unhandled type: {:?}", elem),
            }
        }
        self.buffer.clone()
    }
}

fn print_start_elem(tag: &Tag) -> String {
    let result = match tag {
        &Tag::Header(int) => format!("<h{} id=\"", int),
        &Tag::Strong => "".to_string(),
        &Tag::Emphasis => "".to_string(),
        &Tag::Item => "
".to_string(),
        &Tag::List(_) => "
".to_string(),
        &Tag::Paragraph => "
".to_string(),
        &Tag::Image(ref src, _) => format!(" "".to_string(),
        &Tag::CodeBlock(ref lang) => format!("
", lang),
        &Tag::Link(ref href, _) => format!("", href),
        // TODO Handle alignment
        &Tag::Table(_) => "
".to_string(),
        &Tag::TableHead => "
".to_string(),
        &Tag::TableCell => "".to_string(),
        &Tag::TableRow => "
".to_string(),
        tag => {
            warn!("{:?} tag is unimplemented", tag);
            unimplemented!();
        }
    };

    debug!("{:?}", result);
    result
}

fn print_end_elem(tag: &Tag) -> String {
    let result = match tag {
        &Tag::Header(int) => format!("</h{}>\n", int),
        &Tag::Strong => "\n".to_string(),
        &Tag::Emphasis => "\n".to_string(),
        &Tag::Item => "
\n".to_string(),
        &Tag::List(_) => "
\n".to_string(),
        &Tag::Paragraph => "
\n".to_string(),
        &Tag::Image(_, _) => "/>\n".to_string(),
        &Tag::Code => "\n".to_string(),
        &Tag::CodeBlock(_) => "
\n".to_string(),
        &Tag::Link(_, _) => "\n".to_string(),
        // TODO Handle alignment
        &Tag::Table(_) => "
\n".to_string(),
        &Tag::TableHead => "
\n".to_string(),
        &Tag::TableCell => "	\n".to_string(),
        &Tag::TableRow => "
\n".to_string(),
        tag => {
            warn!("{:?} tag is unimplemented", tag);
            unimplemented!();
        }
    };

    debug!("{:?}", result);
    result
}

fn name_to_id(name: &str) -> String {
    name.to_lowercase().replace(" ", "-")
}

pub fn consume<'a, I: Iterator<Item = Event<'a>>>(iter: I) -> String {
    let mut consumer = Consumer {
        iter: iter,
        buffer: String::new(),
        current: None,
    };
    consumer.consume()
}

#[cfg(test)]
mod tests {
    use test_utils;
    #[test]
    fn test_name_to_id() {
        let actual = super::name_to_id("A very lOng name or Heading");
        assert_eq!("a-very-long-name-or-heading", actual);
    }

    #[test]
    fn test_consume() {
        use pulldown_cmark::Parser;
        use pulldown_cmark::OPTION_ENABLE_TABLES;
        use std::fs::File;
        use std::io::Read;

        let mut content = String::new();
        File::open("resources/all_test.md")
            .and_then(|mut x| x.read_to_string(&mut content))
            .unwrap();
        let parser = Parser::new_ext(&content, OPTION_ENABLE_TABLES);

        let actual = super::consume(parser);
        let expected = include_str!("../tests/resources/all_test_raw_good.html");
        test_utils::compare_string_content(expected, &actual);
    }
}
<|endoftext|>


<commit_before>use std::{
    convert::TryFrom,
    fmt,
    hash::{Hash, Hasher},
    iter::FromIterator,
    ops::{Deref, DerefMut},
};

use crate::Arc;

const CUTOFF: usize = 22;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

impl Default for IVec {
    fn default() -> Self {
        Self::from(&[])
    }
}

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
    Subslice { base: Arc<[u8]>, offset: usize, len: usize },
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    /// Create a subslice of this `IVec` that shares
    /// the same backing data and reference counter.
    ///
    /// # Panics
    ///
    /// Panics if `self.len() - offset >= len`.
    ///
    /// # Examples
    /// ```
    /// let iv = IVec::from(vec![1]);
    /// let subslice = iv.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = subslice.subslice(0, 0);
    /// assert_eq!(&subslice, &[]);
    ///
    /// let iv2 = IVec::from(vec![1, 2, 3]);
    /// let subslice = iv2.subslice(3, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = iv2.subslice(2, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = iv2.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = iv2.subslice(0, 3);
    /// assert_eq!(&subslice, &[1, 2, 3]);
    /// let subslice = subslice.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = subslice.subslice(1, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// ```
    pub fn subslice(&self, slice_offset: usize, len: usize) -> Self {
        assert!(self.len().checked_sub(slice_offset).unwrap() >= len);

        let inner = match self.0 {
            IVecInner::Remote(ref base) => IVecInner::Subslice {
                base: base.clone(),
                offset: slice_offset,
                len,
            },
            IVecInner::Inline(_, old_inner) => {
                // old length already checked above in assertion
                let mut new_inner = Inner::default();
                new_inner[..len].copy_from_slice(
                    &old_inner[slice_offset..slice_offset + len],
                );

                IVecInner::Inline(u8::try_from(len).unwrap(), new_inner)
            }
            IVecInner::Subslice { ref base, ref offset, .. } => {
                IVecInner::Subslice {
                    base: base.clone(),
                    offset: offset + slice_offset,
                    len,
                }
            }
        };

        IVec(inner)
    }

    fn inline(slice: &[u8]) -> Self {
        assert!(is_inline_candidate(slice.len()));

        let mut data = Inner::default();

        #[allow(unsafe_code)]
        unsafe {
            std::ptr::copy_nonoverlapping(
                slice.as_ptr(),
                data.as_mut_ptr(),
                slice.len(),
            );
        }

        Self(IVecInner::Inline(u8::try_from(slice.len()).unwrap(), data))
    }

    fn remote(arc: Arc<[u8]>) -> Self {
        Self(IVecInner::Remote(arc))
    }

    fn make_mut(&mut self) {
        match self.0 {
            IVecInner::Remote(ref mut buf) if Arc::strong_count(buf) != 1 => {
                self.0 = IVecInner::Remote(buf.to_vec().into());
            }
            IVecInner::Subslice { ref mut base, offset, len }
                if Arc::strong_count(base) != 1 =>
            {
                self.0 = IVecInner::Remote(
                    base[offset..offset + len].to_vec().into(),
                );
            }
            _ => {}
        }
    }
}

impl FromIterator<u8> for IVec {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = u8>,
    {
        let bs: Vec<u8> = iter.into_iter().collect();
        bs.into()
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> Self {
        if is_inline_candidate(b.len()) {
            Self::inline(&b)
        } else {
            Self::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> Self {
        if is_inline_candidate(slice.len()) {
            Self::inline(slice)
        } else {
            Self::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> Self {
        if is_inline_candidate(arc.len()) {
            Self::inline(&arc)
        } else {
            Self::remote(arc)
        }
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> Self {
        Self::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &Self) -> Self {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> Self {
        if is_inline_candidate(v.len()) {
            Self::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            Self::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> Self {
                    Self::from(&v[..])
                }
            }
        )*
    }
}

from_array!(
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
);

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
            IVecInner::Subslice { .. } => self.deref().into(),
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
            IVecInner::Subslice { base, offset, len } => {
                &base[*offset..*offset + *len]
            }
        }
    }
}

impl DerefMut for IVec {
    #[inline]
    fn deref_mut(&mut self) -> &mut [u8] {
        self.as_mut()
    }
}

impl AsMut<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_mut(&mut self) -> &mut [u8] {
        self.make_mut();

        match self.0 {
            IVecInner::Inline(ref sz, mut buf) => unsafe {
                std::slice::from_raw_parts_mut(buf.as_mut_ptr(), *sz as usize)
            },
            IVecInner::Remote(ref mut buf) => Arc::get_mut(buf).unwrap(),
            IVecInner::Subslice { ref mut base, offset, len } => {
                &mut Arc::get_mut(base).unwrap()[offset..offset + len]
            }
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
fn boxed_slice_conversion() {
    let boite1: Box<[u8]> = Box::new([1, 2, 3]);
    let iv1: IVec = boite1.into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let boite2: Box<[u8]> = Box::new([4; 128]);
    let iv2: IVec = boite2.into();
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
#[should_panic]
fn subslice_usage_00() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(0, 4);
}

#[test]
#[should_panic]
fn subslice_usage_01() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(3, 1);
}
<commit_msg>Fix doctest<commit_after>use std::{
    convert::TryFrom,
    fmt,
    hash::{Hash, Hasher},
    iter::FromIterator,
    ops::{Deref, DerefMut},
};

use crate::Arc;

const CUTOFF: usize = 22;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

impl Default for IVec {
    fn default() -> Self {
        Self::from(&[])
    }
}

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
    Subslice { base: Arc<[u8]>, offset: usize, len: usize },
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    /// Create a subslice of this `IVec` that shares
    /// the same backing data and reference counter.
    ///
    /// # Panics
    ///
    /// Panics if `self.len() - offset >= len`.
    ///
    /// # Examples
    /// ```
    /// # use sled::IVec;
    /// let iv = IVec::from(vec![1]);
    /// let subslice = iv.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = subslice.subslice(0, 0);
    /// assert_eq!(&subslice, &[]);
    ///
    /// let iv2 = IVec::from(vec![1, 2, 3]);
    /// let subslice = iv2.subslice(3, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = iv2.subslice(2, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = iv2.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = iv2.subslice(0, 3);
    /// assert_eq!(&subslice, &[1, 2, 3]);
    /// let subslice = subslice.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = subslice.subslice(1, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// ```
    pub fn subslice(&self, slice_offset: usize, len: usize) -> Self {
        assert!(self.len().checked_sub(slice_offset).unwrap() >= len);

        let inner = match self.0 {
            IVecInner::Remote(ref base) => IVecInner::Subslice {
                base: base.clone(),
                offset: slice_offset,
                len,
            },
            IVecInner::Inline(_, old_inner) => {
                // old length already checked above in assertion
                let mut new_inner = Inner::default();
                new_inner[..len].copy_from_slice(
                    &old_inner[slice_offset..slice_offset + len],
                );

                IVecInner::Inline(u8::try_from(len).unwrap(), new_inner)
            }
            IVecInner::Subslice { ref base, ref offset, .. } => {
                IVecInner::Subslice {
                    base: base.clone(),
                    offset: offset + slice_offset,
                    len,
                }
            }
        };

        IVec(inner)
    }

    fn inline(slice: &[u8]) -> Self {
        assert!(is_inline_candidate(slice.len()));

        let mut data = Inner::default();

        #[allow(unsafe_code)]
        unsafe {
            std::ptr::copy_nonoverlapping(
                slice.as_ptr(),
                data.as_mut_ptr(),
                slice.len(),
            );
        }

        Self(IVecInner::Inline(u8::try_from(slice.len()).unwrap(), data))
    }

    fn remote(arc: Arc<[u8]>) -> Self {
        Self(IVecInner::Remote(arc))
    }

    fn make_mut(&mut self) {
        match self.0 {
            IVecInner::Remote(ref mut buf) if Arc::strong_count(buf) != 1 => {
                self.0 = IVecInner::Remote(buf.to_vec().into());
            }
            IVecInner::Subslice { ref mut base, offset, len }
                if Arc::strong_count(base) != 1 =>
            {
                self.0 = IVecInner::Remote(
                    base[offset..offset + len].to_vec().into(),
                );
            }
            _ => {}
        }
    }
}

impl FromIterator<u8> for IVec {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = u8>,
    {
        let bs: Vec<u8> = iter.into_iter().collect();
        bs.into()
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> Self {
        if is_inline_candidate(b.len()) {
            Self::inline(&b)
        } else {
            Self::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> Self {
        if is_inline_candidate(slice.len()) {
            Self::inline(slice)
        } else {
            Self::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> Self {
        if is_inline_candidate(arc.len()) {
            Self::inline(&arc)
        } else {
            Self::remote(arc)
        }
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> Self {
        Self::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &Self) -> Self {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> Self {
        if is_inline_candidate(v.len()) {
            Self::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            Self::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> Self {
                    Self::from(&v[..])
                }
            }
        )*
    }
}

from_array!(
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
);

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
            IVecInner::Subslice { .. } => self.deref().into(),
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
            IVecInner::Subslice { base, offset, len } => {
                &base[*offset..*offset + *len]
            }
        }
    }
}

impl DerefMut for IVec {
    #[inline]
    fn deref_mut(&mut self) -> &mut [u8] {
        self.as_mut()
    }
}

impl AsMut<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_mut(&mut self) -> &mut [u8] {
        self.make_mut();

        match self.0 {
            IVecInner::Inline(ref sz, mut buf) => unsafe {
                std::slice::from_raw_parts_mut(buf.as_mut_ptr(), *sz as usize)
            },
            IVecInner::Remote(ref mut buf) => Arc::get_mut(buf).unwrap(),
            IVecInner::Subslice { ref mut base, offset, len } => {
                &mut Arc::get_mut(base).unwrap()[offset..offset + len]
            }
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
fn boxed_slice_conversion() {
    let boite1: Box<[u8]> = Box::new([1, 2, 3]);
    let iv1: IVec = boite1.into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let boite2: Box<[u8]> = Box::new([4; 128]);
    let iv2: IVec = boite2.into();
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
#[should_panic]
fn subslice_usage_00() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(0, 4);
}

#[test]
#[should_panic]
fn subslice_usage_01() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(3, 1);
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#![allow(missing_copy_implementations)]

use io::{self, Read, Write, ErrorKind, BufRead};

/// Copies the entire contents of a reader into a writer.
///
/// This function will continuously read data from `reader` and then
/// write it into `writer` in a streaming fashion until `reader`
/// returns EOF.
///
/// On success, the total number of bytes that were copied from
/// `reader` to `writer` is returned.
///
/// # Errors
///
/// This function will return an error immediately if any call to `read` or
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
/// handled by this function and the underlying operation is retried.
///
/// # Examples
///
/// ```
/// use std::io;
///
/// # fn foo() -> io::Result<()> {
/// let mut reader: &[u8] = b"hello";
/// let mut writer: Vec<u8> = vec![];
///
/// try!(io::copy(&mut reader, &mut writer));
///
/// assert_eq!(reader, &writer[..]);
/// # Ok(())
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
    where R: Read, W: Write
{
    let mut buf = [0; super::DEFAULT_BUF_SIZE];
    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

/// A reader which is always at EOF.
///
/// This struct is generally created by calling [`empty()`][empty]. Please see
/// the documentation of `empty()` for more details.
///
/// [empty]: fn.empty.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () }

/// Constructs a new handle to an empty reader.
///
/// All reads from the returned reader will return `Ok(0)`.
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
///
/// ```
/// use std::io;
/// use std::io::Read;
///
/// # fn foo() -> io::Result<String> {
/// let mut buffer = String::new();
/// try!(io::empty().read_to_string(&mut buffer));
/// # Ok(buffer)
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty {
    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty {
    fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
    fn consume(&mut self, _n: usize) {}
}

/// A reader which yields one byte over and over and over and over and over and...
///
/// This struct is generally created by calling [`repeat()`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// [repeat]: fn.repeat.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 }

/// Creates an instance of a reader that infinitely repeats one byte.
///
/// All reads from this reader will succeed by filling the specified buffer with
/// the given byte.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        for slot in &mut *buf {
            *slot = self.byte;
        }
        Ok(buf.len())
    }
}

/// A writer which will move data into the void.
///
/// This struct is generally created by calling [`sink()`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// [sink]: fn.sink.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () }

/// Creates an instance of a writer which will successfully consume all data.
///
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
/// and the contents of the buffer will not be inspected.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

#[cfg(test)]
mod tests {
    use prelude::v1::*;

    use io::prelude::*;
    use io::{copy, sink, empty, repeat};

    #[test]
    fn copy_copies() {
        let mut r = repeat(0).take(4);
        let mut w = sink();
        assert_eq!(copy(&mut r, &mut w).unwrap(), 4);

        let mut r = repeat(0).take(1 << 17);
        assert_eq!(copy(&mut r as &mut Read, &mut w as &mut Write).unwrap(), 1 << 17);
    }

    #[test]
    fn sink_sinks() {
        let mut s = sink();
        assert_eq!(s.write(&[]).unwrap(), 0);
        assert_eq!(s.write(&[0]).unwrap(), 1);
        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
    }

    #[test]
    fn empty_reads() {
        let mut e = empty();
        assert_eq!(e.read(&mut []).unwrap(), 0);
        assert_eq!(e.read(&mut [0]).unwrap(), 0);
        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
    }

    #[test]
    fn repeat_repeats() {
        let mut r = repeat(4);
        let mut b = [0; 1024];
        assert_eq!(r.read(&mut b).unwrap(), 1024);
        assert!(b.iter().all(|b| *b == 4));
    }

    #[test]
    fn take_some_bytes() {
        assert_eq!(repeat(4).take(100).bytes().count(), 100);
        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
        assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
    }
}
<commit_msg>Minor rewrite of `std::io::empty` doc example.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#![allow(missing_copy_implementations)]

use io::{self, Read, Write, ErrorKind, BufRead};

/// Copies the entire contents of a reader into a writer.
///
/// This function will continuously read data from `reader` and then
/// write it into `writer` in a streaming fashion until `reader`
/// returns EOF.
///
/// On success, the total number of bytes that were copied from
/// `reader` to `writer` is returned.
///
/// # Errors
///
/// This function will return an error immediately if any call to `read` or
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
/// handled by this function and the underlying operation is retried.
///
/// # Examples
///
/// ```
/// use std::io;
///
/// # fn foo() -> io::Result<()> {
/// let mut reader: &[u8] = b"hello";
/// let mut writer: Vec<u8> = vec![];
///
/// try!(io::copy(&mut reader, &mut writer));
///
/// assert_eq!(reader, &writer[..]);
/// # Ok(())
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
    where R: Read, W: Write
{
    let mut buf = [0; super::DEFAULT_BUF_SIZE];
    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

/// A reader which is always at EOF.
///
/// This struct is generally created by calling [`empty()`][empty]. Please see
/// the documentation of `empty()` for more details.
///
/// [empty]: fn.empty.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () }

/// Constructs a new handle to an empty reader.
///
/// All reads from the returned reader will return `Ok(0)`.
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
///
/// ```
/// use std::io::{self, Read};
///
/// let mut buffer = String::new();
/// io::empty().read_to_string(&mut buffer).unwrap();
/// assert!(buffer.is_empty());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty {
    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty {
    fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
    fn consume(&mut self, _n: usize) {}
}

/// A reader which yields one byte over and over and over and over and over and...
///
/// This struct is generally created by calling [`repeat()`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// [repeat]: fn.repeat.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 }

/// Creates an instance of a reader that infinitely repeats one byte.
///
/// All reads from this reader will succeed by filling the specified buffer with
/// the given byte.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        for slot in &mut *buf {
            *slot = self.byte;
        }
        Ok(buf.len())
    }
}

/// A writer which will move data into the void.
///
/// This struct is generally created by calling [`sink()`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// [sink]: fn.sink.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () }

/// Creates an instance of a writer which will successfully consume all data.
///
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
/// and the contents of the buffer will not be inspected.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

#[cfg(test)]
mod tests {
    use prelude::v1::*;

    use io::prelude::*;
    use io::{copy, sink, empty, repeat};

    #[test]
    fn copy_copies() {
        let mut r = repeat(0).take(4);
        let mut w = sink();
        assert_eq!(copy(&mut r, &mut w).unwrap(), 4);

        let mut r = repeat(0).take(1 << 17);
        assert_eq!(copy(&mut r as &mut Read, &mut w as &mut Write).unwrap(), 1 << 17);
    }

    #[test]
    fn sink_sinks() {
        let mut s = sink();
        assert_eq!(s.write(&[]).unwrap(), 0);
        assert_eq!(s.write(&[0]).unwrap(), 1);
        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
    }

    #[test]
    fn empty_reads() {
        let mut e = empty();
        assert_eq!(e.read(&mut []).unwrap(), 0);
        assert_eq!(e.read(&mut [0]).unwrap(), 0);
        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
    }

    #[test]
    fn repeat_repeats() {
        let mut r = repeat(4);
        let mut b = [0; 1024];
        assert_eq!(r.read(&mut b).unwrap(), 1024);
        assert!(b.iter().all(|b| *b == 4));
    }

    #[test]
    fn take_some_bytes() {
        assert_eq!(repeat(4).take(100).bytes().count(), 100);
        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
        assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
    }
}
<|endoftext|>


<commit_before>#![feature(alloc)]
#![feature(fnbox)]
#![feature(unique)]
#![feature(const_fn)]
#![feature(lang_items)]
#![feature(collections)]
#![no_std]

#[macro_use]
extern crate collections;

pub use collections::*;

#[cfg(test)]
extern crate std;

extern crate spin;
extern crate intrusive;
extern crate alloc_uni;
extern crate alloc;

extern crate xen;

pub mod allocator {
    pub use alloc_uni;
    pub unsafe fn init(region_start: usize, region_size: usize) {
        alloc_uni::init(region_start, region_size);
    }
}

#[macro_use]
pub mod console;

pub mod thread;
pub mod sync;
pub mod utils;
<commit_msg>doc: Hide uni::utils and uni::alloctor<commit_after>#![feature(alloc)]
#![feature(fnbox)]
#![feature(unique)]
#![feature(const_fn)]
#![feature(lang_items)]
#![feature(collections)]
#![no_std]

#[macro_use]
extern crate collections;

pub use collections::*;

#[cfg(test)]
extern crate std;

extern crate spin;
extern crate intrusive;
extern crate alloc_uni;
extern crate alloc;

extern crate xen;

#[doc(hidden)]
pub mod allocator {
    pub use alloc_uni;
    pub unsafe fn init(region_start: usize, region_size: usize) {
        alloc_uni::init(region_start, region_size);
    }
}

#[macro_use]
pub mod console;

pub mod thread;
pub mod sync;

#[doc(hidden)]
pub mod utils;
<|endoftext|>


<commit_before>#![crate_id = "hashsum#1.0.0"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 * (c) Vsevolod Velichko <torkvemada@sorokdva.net>
 * (c) Gil Cottle <gcottle@redtown.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#![feature(macro_rules)]

extern crate regex;

extern crate crypto = "rust-crypto";
extern crate getopts;

use std::io::fs::File;
use std::io::stdio::stdin_raw;
use std::io::BufferedReader;
use std::os;
use regex::Regex;
use crypto::digest::Digest;
use crypto::md5::Md5;
use crypto::sha1::Sha1;
use crypto::sha2::{Sha224, Sha256, Sha384, Sha512};

#[path = "../common/util.rs"]
mod util;

static NAME: &'static str = "hashsum";
static VERSION: &'static str = "1.0.0";

fn is_custom_binary(program: &str) -> bool {
    match program {
        "md5sum" | "sha1sum"
            | "sha224sum" | "sha256sum"
            | "sha384sum" | "sha512sum" => true,
        _ => false
    }
}

fn get_algo_opts(program: &str) -> Vec<getopts::OptGroup> {
    if is_custom_binary(program) {
        Vec::new()
    } else {
        vec!(
            getopts::optflag("", "md5", "work with MD5"),
            getopts::optflag("", "sha1", "work with SHA1"),
            getopts::optflag("", "sha224", "work with SHA224"),
            getopts::optflag("", "sha256", "work with SHA256"),
            getopts::optflag("", "sha384", "work with SHA384"),
            getopts::optflag("", "sha512", "work with SHA512")
        )
    }
}

fn detect_algo(program: &str, matches: &getopts::Matches) -> (&str, Box<Digest>) {
    let mut alg: Option<Box<Digest>> = None;
    let mut name: &'static str = "";
    match program {
        "md5sum" => ("MD5", box Md5::new() as Box<Digest>),
        "sha1sum" => ("SHA1", box Sha1::new() as Box<Digest>),
        "sha224sum" => ("SHA224", box Sha224::new() as Box<Digest>),
        "sha256sum" => ("SHA256", box Sha256::new() as Box<Digest>),
        "sha384sum" => ("SHA384", box Sha384::new() as Box<Digest>),
        "sha512sum" => ("SHA512", box Sha512::new() as Box<Digest>),
        _ => {
            {
                let set_or_crash = |n: &'static str, val: Box<Digest>| -> () {
                    if alg.is_some() { crash!(1, "You cannot combine multiple hash algorithms!") };
                    name = n;
                    alg = Some(val);
                };
                if matches.opt_present("md5") { set_or_crash("MD5", box Md5::new()) };
                if matches.opt_present("sha1") { set_or_crash("SHA1", box Sha1::new()) };
                if matches.opt_present("sha224") { set_or_crash("SHA224", box Sha224::new()) };
                if matches.opt_present("sha256") { set_or_crash("SHA256", box Sha256::new()) };
                if matches.opt_present("sha384") { set_or_crash("SHA384", box Sha384::new()) };
                if matches.opt_present("sha512") { set_or_crash("SHA512", box Sha512::new()) };
            }
            if alg.is_none() { crash!(1, "You must specify hash algorithm!") };
            (name, alg.unwrap())
        }
    }
}

#[allow(dead_code)]
fn main() { os::set_exit_status(uumain(os::args())); }

pub fn uumain(args: Vec<String>) -> int {
    let program = args.get(0).clone();
    let binary = Path::new(program.as_slice());
    let binary_name = binary.filename_str().unwrap();

    let mut opts: Vec<getopts::OptGroup> = vec!(
        getopts::optflag("b", "binary", "read in binary mode"),
        getopts::optflag("c", "check", "read hashsums from the FILEs and check them"),
        getopts::optflag("", "tag", "create a BSD-style checksum"),
        getopts::optflag("t", "text", "read in text mode (default)"),
        getopts::optflag("q", "quiet", "don't print OK for each successfully verified file"),
        getopts::optflag("s", "status", "don't output anything, status code shows success"),
        getopts::optflag("", "strict", "exit non-zero for improperly formatted checksum lines"),
        getopts::optflag("w", "warn", "warn about improperly formatted checksum lines"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    );

    opts.push_all_move(get_algo_opts(binary_name.as_slice()));

    let matches = match getopts::getopts(args.tail(), opts.as_slice()) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f)
    };

    if matches.opt_present("help") {
        usage(program.as_slice(), binary_name.as_slice(), opts.as_slice());
    } else if matches.opt_present("version") {
        version();
    } else {
        let (name, algo) = detect_algo(binary_name.as_slice(), &matches);

        let binary = matches.opt_present("binary");
        let check = matches.opt_present("check");
        let tag = matches.opt_present("tag");
        let status = matches.opt_present("status");
        let quiet = matches.opt_present("quiet") || status;
        let strict = matches.opt_present("strict");
        let warn = matches.opt_present("warn") && !status;
        let files = if matches.free.is_empty() {
            vec!("-".to_string())
        } else {
            matches.free
        };
        match hashsum(name, algo, files, binary, check, tag, status, quiet, strict, warn) {
            Ok(()) => return 0,
            Err(e) => return e
        }
    }

    0
}

fn version() {
    println!("{} v{}", NAME, VERSION);
}

fn usage(program: &str, binary_name: &str, opts: &[getopts::OptGroup]) {
    version();
    println!("");
    println!("Usage:");
    if is_custom_binary(binary_name) {
        println!("  {} [OPTION]... [FILE]...", program);
    } else {
        println!("  {} {{--md5|--sha1|--sha224|--sha256|--sha384|--sha512}} [OPTION]... [FILE]...", program);
    }
    println!("");
    print!("{}", getopts::usage("Compute and check message digests.", opts));
}

fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary: bool, check: bool, tag: bool, status: bool, quiet: bool, strict: bool, warn: bool) -> Result<(), int> {
    let mut bad_format = 0;
    let mut failed = 0;
    let binary_marker = if binary {
        "*"
    } else {
        " "
    };
    for filename in files.iter() {
        let filename: &str = filename.as_slice();
        let mut file = BufferedReader::new(
            if filename == "-" {
                box stdin_raw() as Box<Reader>
            } else {
                box safe_unwrap!(File::open(&Path::new(filename))) as Box<Reader>
            }
        );
        if check {

            // Set up Regexs for line validation and parsing
            let bytes = digest.output_bits() / 4;
            let gnu_re = safe_unwrap!(Regex::new(format!(
                        r"^(?P<digest>[a-fA-F0-9]{{{}}}) (?P<binary>[ \*])(?P<fileName>.*)",
                        bytes
                        ).as_slice()));
            let bsd_re = safe_unwrap!(Regex::new(format!(
                        r"^{algorithm} \((?P<fileName>.*)\) = (?P<digest>[a-fA-F0-9]{{{digest_size}}})",
                        algorithm = algoname,
                        digest_size = bytes
                        ).as_slice()));

            let mut buffer = file;
            for (i, line) in buffer.lines().enumerate() {
                let line = safe_unwrap!(line);
                let (ck_filename, sum, binary_check) = match gnu_re.captures(line.as_slice()) {
                    Some(caps) => (caps.name("fileName"), caps.name("digest").to_ascii().to_lower(), caps.name("binary") == "*"),
                    None => match bsd_re.captures(line.as_slice()) {
                        Some(caps) => (caps.name("fileName"), caps.name("digest").to_ascii().to_lower(), true),
                        None => {
                            bad_format += 1;
                            if strict {
                                return Err(1);
                            }
                            if warn {
                                show_warning!("{}: {}: improperly formatted {} checksum line", filename, i + 1, algoname);
                            }
                            continue;
                        }
                    }
                };
                let real_sum = calc_sum(&mut digest, &mut safe_unwrap!(File::open(&Path::new(ck_filename))), binary_check)
                    .as_slice().to_ascii().to_lower();
                if sum.as_slice() == real_sum.as_slice() {
                    if !quiet {
                        println!("{}: OK", ck_filename);
                    }
                } else {
                    if !status {
                        println!("{}: FAILED", ck_filename);
                    }
                    failed += 1;
                }
            }
        } else {
            let sum = calc_sum(&mut digest, &mut file, binary);
            if tag {
                println!("{} ({}) = {}", algoname, filename, sum);
            } else {
                println!("{} {}{}", sum, binary_marker, filename);
            }
        }
    }
    if !status {
        if bad_format == 1 {
            show_warning!("{} line is improperly formatted", bad_format);
        } else if bad_format > 1 {
            show_warning!("{} lines are improperly formatted", bad_format);
        }
        if failed > 0 {
            show_warning!("{} computed checksum did NOT match", failed);
        }
    }

    Ok(())
}

fn calc_sum(digest: &mut Box<Digest>, file: &mut Reader, binary: bool) -> String {
    let data =
        if binary {
            (safe_unwrap!(file.read_to_end()))
        } else {
            (safe_unwrap!(file.read_to_str())).into_bytes()
        };
    digest.reset();
    digest.input(data.as_slice());
    digest.result_str()
}

<commit_msg>Fix typo and code formatting<commit_after>#![crate_id = "hashsum#1.0.0"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 * (c) Vsevolod Velichko <torkvemada@sorokdva.net>
 * (c) Gil Cottle <gcottle@redtown.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#![feature(macro_rules)]

extern crate regex;

extern crate crypto = "rust-crypto";
extern crate getopts;

use std::io::fs::File;
use std::io::stdio::stdin_raw;
use std::io::BufferedReader;
use std::os;
use regex::Regex;
use crypto::digest::Digest;
use crypto::md5::Md5;
use crypto::sha1::Sha1;
use crypto::sha2::{Sha224, Sha256, Sha384, Sha512};

#[path = "../common/util.rs"]
mod util;

static NAME: &'static str = "hashsum";
static VERSION: &'static str = "1.0.0";

fn is_custom_binary(program: &str) -> bool {
    match program {
        "md5sum" | "sha1sum"
            | "sha224sum" | "sha256sum"
            | "sha384sum" | "sha512sum" => true,
        _ => false
    }
}

fn get_algo_opts(program: &str) -> Vec<getopts::OptGroup> {
    if is_custom_binary(program) {
        Vec::new()
    } else {
        vec!(
            getopts::optflag("", "md5", "work with MD5"),
            getopts::optflag("", "sha1", "work with SHA1"),
            getopts::optflag("", "sha224", "work with SHA224"),
            getopts::optflag("", "sha256", "work with SHA256"),
            getopts::optflag("", "sha384", "work with SHA384"),
            getopts::optflag("", "sha512", "work with SHA512")
        )
    }
}

fn detect_algo(program: &str, matches: &getopts::Matches) -> (&str, Box<Digest>) {
    let mut alg: Option<Box<Digest>> = None;
    let mut name: &'static str = "";
    match program {
        "md5sum" => ("MD5", box Md5::new() as Box<Digest>),
        "sha1sum" => ("SHA1", box Sha1::new() as Box<Digest>),
        "sha224sum" => ("SHA224", box Sha224::new() as Box<Digest>),
        "sha256sum" => ("SHA256", box Sha256::new() as Box<Digest>),
        "sha384sum" => ("SHA384", box Sha384::new() as Box<Digest>),
        "sha512sum" => ("SHA512", box Sha512::new() as Box<Digest>),
        _ => {
            {
                let set_or_crash = |n: &'static str, val: Box<Digest>| -> () {
                    if alg.is_some() { crash!(1, "You cannot combine multiple hash algorithms!") };
                    name = n;
                    alg = Some(val);
                };
                if matches.opt_present("md5") { set_or_crash("MD5", box Md5::new()) };
                if matches.opt_present("sha1") { set_or_crash("SHA1", box Sha1::new()) };
                if matches.opt_present("sha224") { set_or_crash("SHA224", box Sha224::new()) };
                if matches.opt_present("sha256") { set_or_crash("SHA256", box Sha256::new()) };
                if matches.opt_present("sha384") { set_or_crash("SHA384", box Sha384::new()) };
                if matches.opt_present("sha512") { set_or_crash("SHA512", box Sha512::new()) };
            }
            if alg.is_none() { crash!(1, "You must specify hash algorithm!") };
            (name, alg.unwrap())
        }
    }
}

#[allow(dead_code)]
fn main() { os::set_exit_status(uumain(os::args())); }

pub fn uumain(args: Vec<String>) -> int {
    let program = args.get(0).clone();
    let binary = Path::new(program.as_slice());
    let binary_name = binary.filename_str().unwrap();

    let mut opts: Vec<getopts::OptGroup> = vec!(
        getopts::optflag("b", "binary", "read in binary mode"),
        getopts::optflag("c", "check", "read hashsums from the FILEs and check them"),
        getopts::optflag("", "tag", "create a BSD-style checksum"),
        getopts::optflag("t", "text", "read in text mode (default)"),
        getopts::optflag("q", "quiet", "don't print OK for each successfully verified file"),
        getopts::optflag("s", "status", "don't output anything, status code shows success"),
        getopts::optflag("", "strict", "exit non-zero for improperly formatted checksum lines"),
        getopts::optflag("w", "warn", "warn about improperly formatted checksum lines"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    );

    opts.push_all_move(get_algo_opts(binary_name.as_slice()));

    let matches = match getopts::getopts(args.tail(), opts.as_slice()) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f)
    };

    if matches.opt_present("help") {
        usage(program.as_slice(), binary_name.as_slice(), opts.as_slice());
    } else if matches.opt_present("version") {
        version();
    } else {
        let (name, algo) = detect_algo(binary_name.as_slice(), &matches);

        let binary = matches.opt_present("binary");
        let check = matches.opt_present("check");
        let tag = matches.opt_present("tag");
        let status = matches.opt_present("status");
        let quiet = matches.opt_present("quiet") || status;
        let strict = matches.opt_present("strict");
        let warn = matches.opt_present("warn") && !status;
        let files = if matches.free.is_empty() {
            vec!("-".to_string())
        } else {
            matches.free
        };
        match hashsum(name, algo, files, binary, check, tag, status, quiet, strict, warn) {
            Ok(()) => return 0,
            Err(e) => return e
        }
    }

    0
}

fn version() {
    println!("{} v{}", NAME, VERSION);
}

fn usage(program: &str, binary_name: &str, opts: &[getopts::OptGroup]) {
    version();
    println!("");
    println!("Usage:");
    if is_custom_binary(binary_name) {
        println!("  {} [OPTION]... [FILE]...", program);
    } else {
        println!("  {} {{--md5|--sha1|--sha224|--sha256|--sha384|--sha512}} [OPTION]... [FILE]...", program);
    }
    println!("");
    print!("{}", getopts::usage("Compute and check message digests.", opts));
}

fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary: bool, check: bool, tag: bool, status: bool, quiet: bool, strict: bool, warn: bool) -> Result<(), int> {
    let mut bad_format = 0;
    let mut failed = 0;
    let binary_marker = if binary {
        "*"
    } else {
        " "
    };
    for filename in files.iter() {
        let filename: &str = filename.as_slice();
        let mut file = BufferedReader::new(
            if filename == "-" {
                box stdin_raw() as Box<Reader>
            } else {
                box safe_unwrap!(File::open(&Path::new(filename))) as Box<Reader>
            }
        );
        if check {

            // Set up Regexes for line validation and parsing
            let bytes = digest.output_bits() / 4;
            let gnu_re = safe_unwrap!(
                Regex::new(
                    format!(
                        r"^(?P<digest>[a-fA-F0-9]{{{}}}) (?P<binary>[ \*])(?P<fileName>.*)",
                        bytes
                    ).as_slice()
                )
            );
            let bsd_re = safe_unwrap!(
                Regex::new(
                    format!(
                        r"^{algorithm} \((?P<fileName>.*)\) = (?P<digest>[a-fA-F0-9]{{{digest_size}}})",
                        algorithm = algoname,
                        digest_size = bytes
                    ).as_slice()
                )
            );

            let mut buffer = file;
            for (i, line) in buffer.lines().enumerate() {
                let line = safe_unwrap!(line);
                let (ck_filename, sum, binary_check) = match gnu_re.captures(line.as_slice()) {
                    Some(caps) => (caps.name("fileName"), caps.name("digest").to_ascii().to_lower(), caps.name("binary") == "*"),
                    None => match bsd_re.captures(line.as_slice()) {
                        Some(caps) => (caps.name("fileName"), caps.name("digest").to_ascii().to_lower(), true),
                        None => {
                            bad_format += 1;
                            if strict {
                                return Err(1);
                            }
                            if warn {
                                show_warning!("{}: {}: improperly formatted {} checksum line", filename, i + 1, algoname);
                            }
                            continue;
                        }
                    }
                };
                let real_sum = calc_sum(&mut digest, &mut safe_unwrap!(File::open(&Path::new(ck_filename))), binary_check)
                    .as_slice().to_ascii().to_lower();
                if sum.as_slice() == real_sum.as_slice() {
                    if !quiet {
                        println!("{}: OK", ck_filename);
                    }
                } else {
                    if !status {
                        println!("{}: FAILED", ck_filename);
                    }
                    failed += 1;
                }
            }
        } else {
            let sum = calc_sum(&mut digest, &mut file, binary);
            if tag {
                println!("{} ({}) = {}", algoname, filename, sum);
            } else {
                println!("{} {}{}", sum, binary_marker, filename);
            }
        }
    }
    if !status {
        if bad_format == 1 {
            show_warning!("{} line is improperly formatted", bad_format);
        } else if bad_format > 1 {
            show_warning!("{} lines are improperly formatted", bad_format);
        }
        if failed > 0 {
            show_warning!("{} computed checksum did NOT match", failed);
        }
    }

    Ok(())
}

fn calc_sum(digest: &mut Box<Digest>, file: &mut Reader, binary: bool) -> String {
    let data =
        if binary {
            (safe_unwrap!(file.read_to_end()))
        } else {
            (safe_unwrap!(file.read_to_str())).into_bytes()
        };
    digest.reset();
    digest.input(data.as_slice());
    digest.result_str()
}

<|endoftext|>