<commit_before>/*!
A texture is an image loaded in video memory, which can be sampled in your shaders.

Textures come in ten different dimensions:

 - Textures with one dimension.
 - Textures with two dimensions.
 - Textures with two dimensions and multisampling enabled.
 - Textures with three dimensions.
 - Cube textures, which are arrays of six two-dimensional textures
   corresponding to the six faces of a cube.
 - Arrays of one-dimensional textures.
 - Arrays of two-dimensional textures.
 - Arrays of two-dimensional textures with multisampling enabled.
 - Arrays of cube textures.
 - Buffer textures, which are one-dimensional textures that are mapped to a buffer.

In addition to this, there are six kinds of texture formats:

 - The texture contains floating-point data,
   with either the `Compressed` prefix or no prefix at all.
 - The texture contains signed integers, with the `Integral` prefix.
 - The texture contains unsigned integers, with the `Unsigned` prefix.
 - The texture contains depth information, with the `Depth` prefix.
 - The texture contains stencil information, with the `Stencil` prefix.
 - The texture contains depth and stencil information, with the `DepthStencil` prefix.

Each combination of dimensions and format corresponds to a sampler type in GLSL. For example,
an `IntegralTexture3d` can only be bound to an `isampler3D` uniform in GLSL. Some combinations
don't exist, like `DepthBufferTexture`.

The difference between compressed textures and uncompressed textures is that you can't do
render-to-texture on the former.

The most common types of textures are `CompressedTexture2d` and `Texture2d` (the two dimensions
being the width and height). These are what you will use most of the time.

*/
use {gl, framebuffer};

#[cfg(feature = "image")]
use image;

use pixel_buffer::PixelBuffer;
use uniforms::{UniformValue, IntoUniformValue, Sampler};
use {Surface, GlObject, ToGlEnum};

use self::tex_impl::TextureImplementation;

pub use self::format::{ClientFormat, TextureFormat};
pub use self::format::{UncompressedFloatFormat, UncompressedIntFormat, UncompressedUintFormat};
pub use self::format::{CompressedFormat, DepthFormat, DepthStencilFormat, StencilFormat};
pub use self::pixel::PixelValue;

mod format;
mod pixel;
mod tex_impl;

include!(concat!(env!("OUT_DIR"), "/textures.rs"));

/// Trait that describes a texture.
pub trait Texture {
    /// Returns the width in pixels of the texture.
    fn get_width(&self) -> u32;

    /// Returns the height in pixels of the texture, or `None` for one dimensional textures.
    fn get_height(&self) -> Option<u32>;

    /// Returns the depth in pixels of the texture, or `None` for one or two dimensional textures.
    fn get_depth(&self) -> Option<u32>;

    /// Returns the number of textures in the array, or `None` for non-arrays.
    fn get_array_size(&self) -> Option<u32>;
}

/// Trait that describes data for a one-dimensional texture.
pub trait Texture1dData {
    type Data: Send + Copy;

    /// Returns the format of the pixels.
    fn get_format() -> ClientFormat;

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<Self::Data>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<Self::Data>) -> Self;
}

impl<P: PixelValue> Texture1dData for Vec<P> {
    type Data = P;

    fn get_format() -> ClientFormat {
        <P as PixelValue>::get_format()
    }

    fn into_vec(self) -> Vec<P> {
        self
    }

    fn from_vec(data: Vec<P>) -> Vec<P> {
        data
    }
}

impl<'a, P: PixelValue + Clone> Texture1dData for &'a [P] {
    type Data = P;

    fn get_format() -> ClientFormat {
        <P as PixelValue>::get_format()
    }

    fn into_vec(self) -> Vec<P> {
        self.to_vec()
    }

    fn from_vec(_: Vec<P>) -> &'a [P] {
        panic!()        // TODO: what to do here?
    }
}

/// Trait that describes data for a two-dimensional texture.
pub trait Texture2dData {
    type Data: Send + Copy;

    /// Returns the format of the pixels.
    fn get_format() -> ClientFormat;

    /// Returns the dimensions of the texture.
    fn get_dimensions(&self) -> (u32, u32);

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<Self::Data>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<Self::Data>, width: u32) -> Self;
}

impl<P: PixelValue + Clone> Texture2dData for Vec<Vec<P>> {      // TODO: remove Clone
    type Data = P;

    fn get_format() -> ClientFormat {
        <P as PixelValue>::get_format()
    }

    fn get_dimensions(&self) -> (u32, u32) {
        (self.iter().next().map(|e| e.len()).unwrap_or(0) as u32, self.len() as u32)
    }

    fn into_vec(self) -> Vec<P> {
        self.into_iter().flat_map(|e| e.into_iter()).collect()
    }

    fn from_vec(data: Vec<P>, width: u32) -> Vec<Vec<P>> {
        data.as_slice().chunks(width as usize).map(|e| e.to_vec()).collect()
    }
}

#[cfg(feature = "image")]
impl<T, P> Texture2dData for image::ImageBuffer<P, Vec<T>> where T: image::Primitive + Send,
    P: PixelValue + image::Pixel<Subpixel = T> + Clone + Copy
{
    type Data = T;

    fn get_format() -> ClientFormat {
        <P as PixelValue>::get_format()
    }

    fn get_dimensions(&self) -> (u32, u32) {
        use image::GenericImage;
        self.dimensions()
    }

    fn into_vec(self) -> Vec<T> {
        use image::GenericImage;
        let (width, _) = self.dimensions();

        let raw_data = self.into_vec();

        // the image library gives us rows from bottom to top, so we need to flip them
        raw_data
            .as_slice()
            .chunks(width as usize * <P as image::Pixel>::channel_count() as usize)
            .rev()
            .flat_map(|row| row.iter())
            .map(|p| p.clone())
            .collect()
    }

    fn from_vec(data: Vec<T>, width: u32) -> image::ImageBuffer<P, Vec<T>> {
        let pixels_size = <P as image::Pixel>::channel_count();
        let height = data.len() as u32 / (width * pixels_size as u32);

        // opengl gives us rows from bottom to top, so we need to flip them
        let data = data
            .as_slice()
            .chunks(width as usize * <P as image::Pixel>::channel_count() as usize)
            .rev()
            .flat_map(|row| row.iter())
            .map(|p| p.clone())
            .collect();

        image::ImageBuffer::from_raw(width, height, data).unwrap()
    }
}

#[cfg(feature = "image")]
impl Texture2dData for image::DynamicImage {
    type Data = u8;

    fn get_format() -> ClientFormat {
        ClientFormat::U8U8U8U8
    }

    fn get_dimensions(&self) -> (u32, u32) {
        use image::GenericImage;
        self.dimensions()
    }

    fn into_vec(self) -> Vec<u8> {
        Texture2dData::into_vec(self.to_rgba())
    }

    fn from_vec(data: Vec<u8>, width: u32) -> image::DynamicImage {
        image::DynamicImage::ImageRgba8(Texture2dData::from_vec(data, width))
    }
}

/// Trait that describes data for a three-dimensional texture.
pub trait Texture3dData {
    type Data: Send + Copy;

    /// Returns the format of the pixels.
    fn get_format() -> ClientFormat;

    /// Returns the dimensions of the texture.
    fn get_dimensions(&self) -> (u32, u32, u32);

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<Self::Data>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<Self::Data>, width: u32, height: u32) -> Self;
}

impl<P: PixelValue> Texture3dData for Vec<Vec<Vec<P>>> {
    type Data = P;

    fn get_format() -> ClientFormat {
        <P as PixelValue>::get_format()
    }

    fn get_dimensions(&self) -> (u32, u32, u32) {
        (self.iter().next().and_then(|e| e.iter().next()).map(|e| e.len()).unwrap_or(0) as u32,
            self.iter().next().map(|e| e.len()).unwrap_or(0) as u32, self.len() as u32)
    }

    fn into_vec(self) -> Vec<P> {
        self.into_iter().flat_map(|e| e.into_iter()).flat_map(|e| e.into_iter()).collect()
    }

    fn from_vec(data: Vec<P>, width: u32, height: u32) -> Vec<Vec<Vec<P>>> {
        unimplemented!()        // TODO:
    }
}

/// Struct that allows you to draw on a texture.
///
/// To obtain such an object, call `texture.as_surface()`.
pub struct TextureSurface<'a>(framebuffer::SimpleFrameBuffer<'a>);

impl<'a> Surface for TextureSurface<'a> {
    fn clear(&mut self, color: Option<(f32, f32, f32, f32)>, depth: Option<f32>,
             stencil: Option<i32>)
    {
        self.0.clear(color, depth, stencil)
    }

    fn get_dimensions(&self) -> (u32, u32) {
        self.0.get_dimensions()
    }

    fn get_depth_buffer_bits(&self) -> Option<u16> {
        self.0.get_depth_buffer_bits()
    }

    fn get_stencil_buffer_bits(&self) -> Option<u16> {
        self.0.get_stencil_buffer_bits()
    }

    fn draw<'b, 'v, V, I, U>(&mut self, vb: V, ib: &I, program: &::Program,
        uniforms: U, draw_parameters: &::DrawParameters) -> Result<(), ::DrawError>
        where I: ::index_buffer::ToIndicesSource,
        U: ::uniforms::Uniforms, V: ::vertex::MultiVerticesSource<'v>
    {
        self.0.draw(vb, ib, program, uniforms, draw_parameters)
    }

    fn get_blit_helper(&self) -> ::BlitHelper {
        self.0.get_blit_helper()
    }
}
<commit_msg>Fix for image function behind renamed<commit_after>/*!
A texture is an image loaded in video memory, which can be sampled in your shaders.

Textures come in ten different dimensions:

 - Textures with one dimension.
 - Textures with two dimensions.
 - Textures with two dimensions and multisampling enabled.
 - Textures with three dimensions.
 - Cube textures, which are arrays of six two-dimensional textures
   corresponding to the six faces of a cube.
 - Arrays of one-dimensional textures.
 - Arrays of two-dimensional textures.
 - Arrays of two-dimensional textures with multisampling enabled.
 - Arrays of cube textures.
 - Buffer textures, which are one-dimensional textures that are mapped to a buffer.

In addition to this, there are six kinds of texture formats:

 - The texture contains floating-point data,
   with either the `Compressed` prefix or no prefix at all.
 - The texture contains signed integers, with the `Integral` prefix.
 - The texture contains unsigned integers, with the `Unsigned` prefix.
 - The texture contains depth information, with the `Depth` prefix.
 - The texture contains stencil information, with the `Stencil` prefix.
 - The texture contains depth and stencil information, with the `DepthStencil` prefix.

Each combination of dimensions and format corresponds to a sampler type in GLSL. For example,
an `IntegralTexture3d` can only be bound to an `isampler3D` uniform in GLSL. Some combinations
don't exist, like `DepthBufferTexture`.

The difference between compressed textures and uncompressed textures is that you can't do
render-to-texture on the former.

The most common types of textures are `CompressedTexture2d` and `Texture2d` (the two dimensions
being the width and height). These are what you will use most of the time.

*/
use {gl, framebuffer};

#[cfg(feature = "image")]
use image;

use pixel_buffer::PixelBuffer;
use uniforms::{UniformValue, IntoUniformValue, Sampler};
use {Surface, GlObject, ToGlEnum};

use self::tex_impl::TextureImplementation;

pub use self::format::{ClientFormat, TextureFormat};
pub use self::format::{UncompressedFloatFormat, UncompressedIntFormat, UncompressedUintFormat};
pub use self::format::{CompressedFormat, DepthFormat, DepthStencilFormat, StencilFormat};
pub use self::pixel::PixelValue;

mod format;
mod pixel;
mod tex_impl;

include!(concat!(env!("OUT_DIR"), "/textures.rs"));

/// Trait that describes a texture.
pub trait Texture {
    /// Returns the width in pixels of the texture.
    fn get_width(&self) -> u32;

    /// Returns the height in pixels of the texture, or `None` for one dimensional textures.
    fn get_height(&self) -> Option<u32>;

    /// Returns the depth in pixels of the texture, or `None` for one or two dimensional textures.
    fn get_depth(&self) -> Option<u32>;

    /// Returns the number of textures in the array, or `None` for non-arrays.
    fn get_array_size(&self) -> Option<u32>;
}

/// Trait that describes data for a one-dimensional texture.
pub trait Texture1dData {
    type Data: Send + Copy;

    /// Returns the format of the pixels.
    fn get_format() -> ClientFormat;

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<Self::Data>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<Self::Data>) -> Self;
}

impl<P: PixelValue> Texture1dData for Vec<P> {
    type Data = P;

    fn get_format() -> ClientFormat {
        <P as PixelValue>::get_format()
    }

    fn into_vec(self) -> Vec<P> {
        self
    }

    fn from_vec(data: Vec<P>) -> Vec<P> {
        data
    }
}

impl<'a, P: PixelValue + Clone> Texture1dData for &'a [P] {
    type Data = P;

    fn get_format() -> ClientFormat {
        <P as PixelValue>::get_format()
    }

    fn into_vec(self) -> Vec<P> {
        self.to_vec()
    }

    fn from_vec(_: Vec<P>) -> &'a [P] {
        panic!()        // TODO: what to do here?
    }
}

/// Trait that describes data for a two-dimensional texture.
pub trait Texture2dData {
    type Data: Send + Copy;

    /// Returns the format of the pixels.
    fn get_format() -> ClientFormat;

    /// Returns the dimensions of the texture.
    fn get_dimensions(&self) -> (u32, u32);

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<Self::Data>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<Self::Data>, width: u32) -> Self;
}

impl<P: PixelValue + Clone> Texture2dData for Vec<Vec<P>> {      // TODO: remove Clone
    type Data = P;

    fn get_format() -> ClientFormat {
        <P as PixelValue>::get_format()
    }

    fn get_dimensions(&self) -> (u32, u32) {
        (self.iter().next().map(|e| e.len()).unwrap_or(0) as u32, self.len() as u32)
    }

    fn into_vec(self) -> Vec<P> {
        self.into_iter().flat_map(|e| e.into_iter()).collect()
    }

    fn from_vec(data: Vec<P>, width: u32) -> Vec<Vec<P>> {
        data.as_slice().chunks(width as usize).map(|e| e.to_vec()).collect()
    }
}

#[cfg(feature = "image")]
impl<T, P> Texture2dData for image::ImageBuffer<P, Vec<T>> where T: image::Primitive + Send,
    P: PixelValue + image::Pixel<Subpixel = T> + Clone + Copy
{
    type Data = T;

    fn get_format() -> ClientFormat {
        <P as PixelValue>::get_format()
    }

    fn get_dimensions(&self) -> (u32, u32) {
        use image::GenericImage;
        self.dimensions()
    }

    fn into_vec(self) -> Vec<T> {
        use image::GenericImage;
        let (width, _) = self.dimensions();

        let raw_data = self.into_raw();

        // the image library gives us rows from bottom to top, so we need to flip them
        raw_data
            .as_slice()
            .chunks(width as usize * <P as image::Pixel>::channel_count() as usize)
            .rev()
            .flat_map(|row| row.iter())
            .map(|p| p.clone())
            .collect()
    }

    fn from_vec(data: Vec<T>, width: u32) -> image::ImageBuffer<P, Vec<T>> {
        let pixels_size = <P as image::Pixel>::channel_count();
        let height = data.len() as u32 / (width * pixels_size as u32);

        // opengl gives us rows from bottom to top, so we need to flip them
        let data = data
            .as_slice()
            .chunks(width as usize * <P as image::Pixel>::channel_count() as usize)
            .rev()
            .flat_map(|row| row.iter())
            .map(|p| p.clone())
            .collect();

        image::ImageBuffer::from_raw(width, height, data).unwrap()
    }
}

#[cfg(feature = "image")]
impl Texture2dData for image::DynamicImage {
    type Data = u8;

    fn get_format() -> ClientFormat {
        ClientFormat::U8U8U8U8
    }

    fn get_dimensions(&self) -> (u32, u32) {
        use image::GenericImage;
        self.dimensions()
    }

    fn into_vec(self) -> Vec<u8> {
        Texture2dData::into_vec(self.to_rgba())
    }

    fn from_vec(data: Vec<u8>, width: u32) -> image::DynamicImage {
        image::DynamicImage::ImageRgba8(Texture2dData::from_vec(data, width))
    }
}

/// Trait that describes data for a three-dimensional texture.
pub trait Texture3dData {
    type Data: Send + Copy;

    /// Returns the format of the pixels.
    fn get_format() -> ClientFormat;

    /// Returns the dimensions of the texture.
    fn get_dimensions(&self) -> (u32, u32, u32);

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<Self::Data>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<Self::Data>, width: u32, height: u32) -> Self;
}

impl<P: PixelValue> Texture3dData for Vec<Vec<Vec<P>>> {
    type Data = P;

    fn get_format() -> ClientFormat {
        <P as PixelValue>::get_format()
    }

    fn get_dimensions(&self) -> (u32, u32, u32) {
        (self.iter().next().and_then(|e| e.iter().next()).map(|e| e.len()).unwrap_or(0) as u32,
            self.iter().next().map(|e| e.len()).unwrap_or(0) as u32, self.len() as u32)
    }

    fn into_vec(self) -> Vec<P> {
        self.into_iter().flat_map(|e| e.into_iter()).flat_map(|e| e.into_iter()).collect()
    }

    fn from_vec(data: Vec<P>, width: u32, height: u32) -> Vec<Vec<Vec<P>>> {
        unimplemented!()        // TODO:
    }
}

/// Struct that allows you to draw on a texture.
///
/// To obtain such an object, call `texture.as_surface()`.
pub struct TextureSurface<'a>(framebuffer::SimpleFrameBuffer<'a>);

impl<'a> Surface for TextureSurface<'a> {
    fn clear(&mut self, color: Option<(f32, f32, f32, f32)>, depth: Option<f32>,
             stencil: Option<i32>)
    {
        self.0.clear(color, depth, stencil)
    }

    fn get_dimensions(&self) -> (u32, u32) {
        self.0.get_dimensions()
    }

    fn get_depth_buffer_bits(&self) -> Option<u16> {
        self.0.get_depth_buffer_bits()
    }

    fn get_stencil_buffer_bits(&self) -> Option<u16> {
        self.0.get_stencil_buffer_bits()
    }

    fn draw<'b, 'v, V, I, U>(&mut self, vb: V, ib: &I, program: &::Program,
        uniforms: U, draw_parameters: &::DrawParameters) -> Result<(), ::DrawError>
        where I: ::index_buffer::ToIndicesSource,
        U: ::uniforms::Uniforms, V: ::vertex::MultiVerticesSource<'v>
    {
        self.0.draw(vb, ib, program, uniforms, draw_parameters)
    }

    fn get_blit_helper(&self) -> ::BlitHelper {
        self.0.get_blit_helper()
    }
}
<|endoftext|>


<commit_before>use super::{ColorStyle, Effect};
use enumset::EnumSet;

/// Combine a color and an effect.
///
/// Represents any transformation that can be applied to text.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Style {
    /// Effect to apply.
    ///
    /// `None` to keep using previous effects.
    pub effects: EnumSet<Effect>,

    /// Color style to apply.
    ///
    /// `None` to keep using the previous colors.
    pub color: Option<ColorStyle>,
}

impl Default for Style {
    fn default() -> Self {
        Self::none()
    }
}

impl Style {
    /// Returns a new `Style` that doesn't apply anything.
    pub fn none() -> Self {
        Style {
            effects: EnumSet::new(),
            color: None,
        }
    }

    /// Returns a new `Style` by merging all given styles.
    ///
    /// Will use the last non-`None` color, and will combine all effects.
    pub fn merge(styles: &[Style]) -> Self {
        let mut color = None;
        let mut effects = EnumSet::new();

        for style in styles {
            if style.color.is_some() {
                color = style.color;
            }

            effects.insert_all(style.effects);
        }

        Style { color, effects }
    }
}

impl From<Effect> for Style {
    fn from(effect: Effect) -> Self {
        Style {
            effects: enum_set!(Effect, effect),
            color: None,
        }
    }
}

impl From<ColorStyle> for Style {
    fn from(color: ColorStyle) -> Self {
        Style {
            effects: EnumSet::new(),
            color: Some(color),
        }
    }
}
<commit_msg>Add Style::add<commit_after>use super::{ColorStyle, Effect, Color};
use enumset::EnumSet;

/// Combine a color and an effect.
///
/// Represents any transformation that can be applied to text.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Style {
    /// Effect to apply.
    ///
    /// `None` to keep using previous effects.
    pub effects: EnumSet<Effect>,

    /// Color style to apply.
    ///
    /// `None` to keep using the previous colors.
    pub color: Option<ColorStyle>,
}

impl Default for Style {
    fn default() -> Self {
        Self::none()
    }
}

impl Style {
    /// Returns a new `Style` that doesn't apply anything.
    pub fn none() -> Self {
        Style {
            effects: EnumSet::new(),
            color: None,
        }
    }

    /// Returns a new `Style` by merging all given styles.
    ///
    /// Will use the last non-`None` color, and will combine all effects.
    pub fn merge(styles: &[Style]) -> Self {
        let mut color = None;
        let mut effects = EnumSet::new();

        for style in styles {
            if style.color.is_some() {
                color = style.color;
            }

            effects.insert_all(style.effects);
        }

        Style { color, effects }
    }

    /// Returns a combination of `self` and `other`.
    pub fn add<S>(self, other: S) -> Self where S: Into<Style> {
        Self::merge(&[self, other.into()])
    }
}

impl From<Effect> for Style {
    fn from(effect: Effect) -> Self {
        Style {
            effects: enum_set!(Effect, effect),
            color: None,
        }
    }
}

impl From<ColorStyle> for Style {
    fn from(color: ColorStyle) -> Self {
        Style {
            effects: EnumSet::new(),
            color: Some(color),
        }
    }
}
<|endoftext|>


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

use super::address::*;
use super::treenode::*;
use super::basictree::*;

///
/// Represents which of the root's references have changed
///
pub enum TreeChangeType {
    /// The node's child reference has been replaced
    Child,

    /// The node's sibling reference has been replaced
    Sibling
}

///
/// A change represents an alteration to the tree
///
pub struct TreeChange {
    /// The address of the node matching the root of the change
    ///
    /// The address is relative to an imaginary node that is the parent of the real root node. This makes it possible to
    /// replace the entire tree by setting this to `TreeAddress::Here` and the change_type to `TreeChangeType::Child`.
    /// The real root node can be addressed at `TreeAddress::ChildAtIndex(0)`
    root: TreeAddress,

    /// Which of the root's references have changed
    change_type: TreeChangeType,

    /// The tree that should replace the changed reference. The last node in this tree (depth-first) will be given the same sibling as the last node in the replacement range
    replacement_tree: Option<TreeRef>
}

impl TreeChange {
    ///
    /// Creates a new tree change
    ///
    pub fn new<TAddress: ToTreeAddress, TNode: ToTreeNode>(root: &TAddress, change_type: TreeChangeType, replacement_tree: Option<&TNode>) -> TreeChange {
        TreeChange { root: root.to_tree_address(), change_type: change_type, replacement_tree: replacement_tree.map(|x| x.to_tree_node()) }
    }

    ///
    /// Performs a replacement on a basic tree node
    ///
    #[inline]
    fn perform_replacement(node: &BasicTree, change_type: &TreeChangeType, replacement_tree: &Option<TreeRef>) {
        match *change_type {
            TreeChangeType::Child => {
                match *replacement_tree {
                    Some(ref new_child)     => node.set_child_ref(new_child.clone()),
                    None                    => node.clear_child()
                }
            },

            TreeChangeType::Sibling => {
                match *replacement_tree {
                    Some(ref new_sibling)   => node.set_sibling_ref(new_sibling.clone()),
                    None                    => node.clear_child()
                }
            }
        }
    }

    ///
    /// Applies a change to a tree, generating a new tree
    ///
    fn perform_apply(original_tree: &TreeRef, address: &TreeAddress, change_type: &TreeChangeType, replacement_tree: &Option<TreeRef>) -> TreeRef {
        match *address {
            TreeAddress::Here => {
                let new_node = BasicTree::from(original_tree);
                TreeChange::perform_replacement(&new_node, change_type, replacement_tree);

                Rc::new(new_node)
            },

            TreeAddress::ChildAtIndex(child_index, ref child_address) => {
                // Copy the siblings into a stack
                let mut siblings    = vec![];
                let mut current     = original_tree.get_child_ref();

                for _ in 0..child_index {
                    siblings.push(current.clone());

                    current = current.and_then(|x| x.get_sibling_ref());
                }

                // Replace the child matching this item
                let new_child = current.clone().map(|child_tree| TreeChange::perform_apply(&child_tree, &*child_address, change_type, replacement_tree));
                siblings.push(new_child);

                current = current.and_then(|x| x.get_sibling_ref());

                // Pop siblings to generate the new child item
                while let Some(sibling) = siblings.pop() {
                    match current {
                        Some(next_sibling)  => current = Some(Rc::new(BasicTree::from_with_sibling(sibling.unwrap(), next_sibling))),
                        None                => current = sibling,
                    }
                }

                Rc::new(BasicTree::from_with_child(original_tree, current.unwrap()))
            },

            TreeAddress::ChildWithTag(ref child_tag, ref child_address) => {
                let child_tree  = original_tree.get_child_at(&**child_tag);
                let new_child   = TreeChange::perform_apply(&child_tree, &*child_address, change_type, replacement_tree);

                Rc::new(BasicTree::from_with_child(original_tree, new_child))
            }
        }
    }

    ///
    /// Creates a new tree from an old tree with this change added to it
    ///
    #[inline]
    pub fn apply(&self, original_tree: &TreeRef) -> TreeRef {
        // For simplicity, we actualise the 'imaginary' root
        let imaginary_root      = tree!("", original_tree).to_tree_node();
        let new_imaginary_root  = TreeChange::perform_apply(&imaginary_root, &self.root, &self.change_type, &self.replacement_tree);

        // Result is the child of the imaginary node (or an empty node if the entire tree is deleted)
        new_imaginary_root.get_child_ref().unwrap_or_else(|| "".to_tree_node())
    }
}

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

    #[test]
    fn can_apply_simple_change_tagged() {
        let initial_tree    = tree!("test", ("one", 1), ("two", 2), ("three", 3));
        let change_two      = TreeChange::new(&("test", "one"), TreeChangeType::Sibling, Some(&("replaced", 4)));
        let changed_tree    = change_two.apply(&initial_tree);

        assert!(changed_tree.get_child_ref_at("one").unwrap().get_value().to_int(0) == 1);
        assert!(changed_tree.get_child_ref_at("replaced").unwrap().get_value().to_int(0) == 4);
        assert!(changed_tree.get_child_ref_at("replaced").unwrap().get_sibling_ref().is_none());
        assert!(changed_tree.get_child_ref_at("two").is_none());
        assert!(changed_tree.get_child_ref_at("three").is_none());
    }

    #[test]
    fn can_apply_simple_change_indexed() {
        let initial_tree    = tree!("test", ("one", 1), ("two", 2), ("three", 3));
        let change_two      = TreeChange::new(&(0, 0), TreeChangeType::Sibling, Some(&("replaced", 4)));
        let changed_tree    = change_two.apply(&initial_tree);

        assert!(changed_tree.get_child_ref_at(0).unwrap().get_value().to_int(0) == 1);
        assert!(changed_tree.get_child_ref_at(1).unwrap().get_value().to_int(0) == 4);
        assert!(changed_tree.get_child_ref_at(1).unwrap().get_sibling_ref().is_none());
        assert!(changed_tree.get_child_ref_at(2).is_none());
        assert!(changed_tree.get_child_ref_at(3).is_none());
    }

    #[test]
    fn can_apply_child_change_tagged() {
        let initial_tree    = tree!("test", ("one", 1), ("two", 2), ("three", 3));
        let change_two      = TreeChange::new(&("test", "two").to_tree_address(), TreeChangeType::Child, Some(&("new_child", 4)));
        let changed_tree    = change_two.apply(&initial_tree);

        assert!(!changed_tree.get_child_ref_at(("two", "new_child").to_tree_address()).is_none());

        assert!(changed_tree.get_child_ref_at(("two", "new_child").to_tree_address()).unwrap().get_value().to_int(0) == 4);
        assert!(changed_tree.get_child_ref_at(("two", "new_child").to_tree_address()).unwrap().get_sibling_ref().is_none());

        assert!(!changed_tree.get_child_ref_at("one").is_none());
        assert!(!changed_tree.get_child_ref_at("two").is_none());
        assert!(!changed_tree.get_child_ref_at("three").is_none());
        assert!(changed_tree.get_child_ref_at("two").unwrap().get_value().to_int(0) == 2);
    }

    #[test]
    fn can_apply_child_change_indexed() {
        let initial_tree    = tree!("test", ("one", 1), ("two", 2), ("three", 3));
        let change_two      = TreeChange::new(&(0, 1).to_tree_address(), TreeChangeType::Child, Some(&("new_child", 4)));
        let changed_tree    = change_two.apply(&initial_tree);

        assert!(!changed_tree.get_child_ref_at((1, 0).to_tree_address()).is_none());

        assert!(changed_tree.get_child_ref_at((1, 0).to_tree_address()).unwrap().get_value().to_int(0) == 4);
        assert!(changed_tree.get_child_ref_at((1, 0).to_tree_address()).unwrap().get_sibling_ref().is_none());

        assert!(!changed_tree.get_child_ref_at(0).is_none());
        assert!(!changed_tree.get_child_ref_at(1).is_none());
        assert!(!changed_tree.get_child_ref_at(2).is_none());
        assert!(changed_tree.get_child_ref_at(1).unwrap().get_value().to_int(0) == 2);
    }
}
<commit_msg>Change to making sure that siblings are always present when applying changes (by bringing them into being if necessary): ie, a change for a non-existent node will create extra nodes in order to be applied<commit_after>use std::rc::*;

use super::address::*;
use super::treenode::*;
use super::basictree::*;

///
/// Represents which of the root's references have changed
///
pub enum TreeChangeType {
    /// The node's child reference has been replaced
    Child,

    /// The node's sibling reference has been replaced
    Sibling
}

///
/// A change represents an alteration to the tree
///
pub struct TreeChange {
    /// The address of the node matching the root of the change
    ///
    /// The address is relative to an imaginary node that is the parent of the real root node. This makes it possible to
    /// replace the entire tree by setting this to `TreeAddress::Here` and the change_type to `TreeChangeType::Child`.
    /// The real root node can be addressed at `TreeAddress::ChildAtIndex(0)`
    root: TreeAddress,

    /// Which of the root's references have changed
    change_type: TreeChangeType,

    /// The tree that should replace the changed reference. The last node in this tree (depth-first) will be given the same sibling as the last node in the replacement range
    replacement_tree: Option<TreeRef>
}

impl TreeChange {
    ///
    /// Creates a new tree change
    ///
    pub fn new<TAddress: ToTreeAddress, TNode: ToTreeNode>(root: &TAddress, change_type: TreeChangeType, replacement_tree: Option<&TNode>) -> TreeChange {
        TreeChange { root: root.to_tree_address(), change_type: change_type, replacement_tree: replacement_tree.map(|x| x.to_tree_node()) }
    }

    ///
    /// Performs a replacement on a basic tree node
    ///
    #[inline]
    fn perform_replacement(node: &BasicTree, change_type: &TreeChangeType, replacement_tree: &Option<TreeRef>) {
        match *change_type {
            TreeChangeType::Child => {
                match *replacement_tree {
                    Some(ref new_child)     => node.set_child_ref(new_child.clone()),
                    None                    => node.clear_child()
                }
            },

            TreeChangeType::Sibling => {
                match *replacement_tree {
                    Some(ref new_sibling)   => node.set_sibling_ref(new_sibling.clone()),
                    None                    => node.clear_child()
                }
            }
        }
    }

    ///
    /// Applies a change to a tree, generating a new tree
    ///
    fn perform_apply(original_tree: &TreeRef, address: &TreeAddress, change_type: &TreeChangeType, replacement_tree: &Option<TreeRef>) -> TreeRef {
        match *address {
            TreeAddress::Here => {
                let new_node = BasicTree::from(original_tree);
                TreeChange::perform_replacement(&new_node, change_type, replacement_tree);

                Rc::new(new_node)
            },

            TreeAddress::ChildAtIndex(child_index, ref child_address) => {
                // Copy the siblings into a stack
                let mut siblings    = vec![];
                let mut current     = original_tree.get_child_ref();

                for _ in 0..child_index {
                    siblings.push(current.clone().unwrap_or_else(|| Rc::new(BasicTree::new("", ()))));

                    current = current.and_then(|x| x.get_sibling_ref());
                }

                // Replace the child matching this item
                let child_tree  = current.clone().unwrap_or_else(|| Rc::new(BasicTree::new("", ())));
                let new_child   = TreeChange::perform_apply(&child_tree, &*child_address, change_type, replacement_tree);
                siblings.push(new_child);

                current = current.and_then(|x| x.get_sibling_ref());

                // Pop siblings to generate the new child item
                while let Some(sibling) = siblings.pop() {
                    match current {
                        Some(next_sibling)  => current = Some(Rc::new(BasicTree::from_with_sibling(sibling, next_sibling))),
                        None                => current = Some(sibling),
                    }
                }

                Rc::new(BasicTree::from_with_child(original_tree, current.unwrap()))
            },

            TreeAddress::ChildWithTag(ref child_tag, ref child_address) => {
                let child_tree  = original_tree.get_child_at(&**child_tag);
                let new_child   = TreeChange::perform_apply(&child_tree, &*child_address, change_type, replacement_tree);

                Rc::new(BasicTree::from_with_child(original_tree, new_child))
            }
        }
    }

    ///
    /// Creates a new tree from an old tree with this change added to it
    ///
    #[inline]
    pub fn apply(&self, original_tree: &TreeRef) -> TreeRef {
        // For simplicity, we actualise the 'imaginary' root
        let imaginary_root      = tree!("", original_tree).to_tree_node();
        let new_imaginary_root  = TreeChange::perform_apply(&imaginary_root, &self.root, &self.change_type, &self.replacement_tree);

        // Result is the child of the imaginary node (or an empty node if the entire tree is deleted)
        new_imaginary_root.get_child_ref().unwrap_or_else(|| "".to_tree_node())
    }
}

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

    #[test]
    fn can_apply_simple_change_tagged() {
        let initial_tree    = tree!("test", ("one", 1), ("two", 2), ("three", 3));
        let change_two      = TreeChange::new(&("test", "one"), TreeChangeType::Sibling, Some(&("replaced", 4)));
        let changed_tree    = change_two.apply(&initial_tree);

        assert!(changed_tree.get_child_ref_at("one").unwrap().get_value().to_int(0) == 1);
        assert!(changed_tree.get_child_ref_at("replaced").unwrap().get_value().to_int(0) == 4);
        assert!(changed_tree.get_child_ref_at("replaced").unwrap().get_sibling_ref().is_none());
        assert!(changed_tree.get_child_ref_at("two").is_none());
        assert!(changed_tree.get_child_ref_at("three").is_none());
    }

    #[test]
    fn can_apply_simple_change_indexed() {
        let initial_tree    = tree!("test", ("one", 1), ("two", 2), ("three", 3));
        let change_two      = TreeChange::new(&(0, 0), TreeChangeType::Sibling, Some(&("replaced", 4)));
        let changed_tree    = change_two.apply(&initial_tree);

        assert!(changed_tree.get_child_ref_at(0).unwrap().get_value().to_int(0) == 1);
        assert!(changed_tree.get_child_ref_at(1).unwrap().get_value().to_int(0) == 4);
        assert!(changed_tree.get_child_ref_at(1).unwrap().get_sibling_ref().is_none());
        assert!(changed_tree.get_child_ref_at(2).is_none());
        assert!(changed_tree.get_child_ref_at(3).is_none());
    }

    #[test]
    fn can_apply_child_change_tagged() {
        let initial_tree    = tree!("test", ("one", 1), ("two", 2), ("three", 3));
        let change_two      = TreeChange::new(&("test", "two").to_tree_address(), TreeChangeType::Child, Some(&("new_child", 4)));
        let changed_tree    = change_two.apply(&initial_tree);

        assert!(!changed_tree.get_child_ref_at(("two", "new_child").to_tree_address()).is_none());

        assert!(changed_tree.get_child_ref_at(("two", "new_child").to_tree_address()).unwrap().get_value().to_int(0) == 4);
        assert!(changed_tree.get_child_ref_at(("two", "new_child").to_tree_address()).unwrap().get_sibling_ref().is_none());

        assert!(!changed_tree.get_child_ref_at("one").is_none());
        assert!(!changed_tree.get_child_ref_at("two").is_none());
        assert!(!changed_tree.get_child_ref_at("three").is_none());
        assert!(changed_tree.get_child_ref_at("two").unwrap().get_value().to_int(0) == 2);
    }

    #[test]
    fn can_apply_child_change_indexed() {
        let initial_tree    = tree!("test", ("one", 1), ("two", 2), ("three", 3));
        let change_two      = TreeChange::new(&(0, 1).to_tree_address(), TreeChangeType::Child, Some(&("new_child", 4)));
        let changed_tree    = change_two.apply(&initial_tree);

        assert!(!changed_tree.get_child_ref_at((1, 0).to_tree_address()).is_none());

        assert!(changed_tree.get_child_ref_at((1, 0).to_tree_address()).unwrap().get_value().to_int(0) == 4);
        assert!(changed_tree.get_child_ref_at((1, 0).to_tree_address()).unwrap().get_sibling_ref().is_none());

        assert!(!changed_tree.get_child_ref_at(0).is_none());
        assert!(!changed_tree.get_child_ref_at(1).is_none());
        assert!(!changed_tree.get_child_ref_at(2).is_none());
        assert!(changed_tree.get_child_ref_at(1).unwrap().get_value().to_int(0) == 2);
    }
}
<|endoftext|>


<commit_before>use std::any::Any;
use std::error::Error;
use std::fmt;

use conduit::Response;
use diesel::result::Error as DieselError;

use util::json_response;

#[derive(Serialize)]
struct StringError {
    detail: String,
}
#[derive(Serialize)]
struct Bad {
    errors: Vec<StringError>,
}

// =============================================================================
// CargoError trait

pub trait CargoError: Send + fmt::Display + 'static {
    fn description(&self) -> &str;
    fn cause(&self) -> Option<&(dyn CargoError)> {
        None
    }

    fn response(&self) -> Option<Response> {
        if self.human() {
            Some(json_response(&Bad {
                errors: vec![StringError {
                    detail: self.description().to_string(),
                }],
            }))
        } else {
            self.cause().and_then(|cause| cause.response())
        }
    }
    fn human(&self) -> bool {
        false
    }
}

impl fmt::Debug for Box<dyn CargoError> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}

impl CargoError for Box<dyn CargoError> {
    fn description(&self) -> &str {
        (**self).description()
    }
    fn cause(&self) -> Option<&dyn CargoError> {
        (**self).cause()
    }
    fn human(&self) -> bool {
        (**self).human()
    }
    fn response(&self) -> Option<Response> {
        (**self).response()
    }
}
impl<T: CargoError> CargoError for Box<T> {
    fn description(&self) -> &str {
        (**self).description()
    }
    fn cause(&self) -> Option<&dyn CargoError> {
        (**self).cause()
    }
    fn human(&self) -> bool {
        (**self).human()
    }
    fn response(&self) -> Option<Response> {
        (**self).response()
    }
}

pub type CargoResult<T> = Result<T, Box<dyn CargoError>>;

// =============================================================================
// Chaining errors

pub trait ChainError<T> {
    fn chain_error<E, F>(self, callback: F) -> CargoResult<T>
    where
        E: CargoError,
        F: FnOnce() -> E;
}

struct ChainedError<E> {
    error: E,
    cause: Box<dyn CargoError>,
}

impl<T, F> ChainError<T> for F
where
    F: FnOnce() -> CargoResult<T>,
{
    fn chain_error<E, C>(self, callback: C) -> CargoResult<T>
    where
        E: CargoError,
        C: FnOnce() -> E,
    {
        self().chain_error(callback)
    }
}

impl<T, E: CargoError> ChainError<T> for Result<T, E> {
    fn chain_error<E2, C>(self, callback: C) -> CargoResult<T>
    where
        E2: CargoError,
        C: FnOnce() -> E2,
    {
        self.map_err(move |err| {
            Box::new(ChainedError {
                error: callback(),
                cause: Box::new(err),
            }) as Box<dyn CargoError>
        })
    }
}

impl<T> ChainError<T> for Option<T> {
    fn chain_error<E, C>(self, callback: C) -> CargoResult<T>
    where
        E: CargoError,
        C: FnOnce() -> E,
    {
        match self {
            Some(t) => Ok(t),
            None => Err(Box::new(callback())),
        }
    }
}

impl<E: CargoError> CargoError for ChainedError<E> {
    fn description(&self) -> &str {
        self.error.description()
    }
    fn cause(&self) -> Option<&dyn CargoError> {
        Some(&*self.cause)
    }
    fn response(&self) -> Option<Response> {
        self.error.response()
    }
    fn human(&self) -> bool {
        self.error.human()
    }
}

impl<E: CargoError> fmt::Display for ChainedError<E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} caused by {}", self.error, self.cause)
    }
}

// =============================================================================
// Error impls

impl<E: Any + Error + Send + 'static> From<E> for Box<dyn CargoError> {
    fn from(err: E) -> Box<dyn CargoError> {
        if let Some(err) = Any::downcast_ref::<DieselError>(&err) {
            if let DieselError::NotFound = *err {
                return Box::new(NotFound);
            }
        }

        struct Shim<E>(E);
        impl<E: Error + Send + 'static> CargoError for Shim<E> {
            fn description(&self) -> &str {
                Error::description(&self.0)
            }
        }
        impl<E: fmt::Display> fmt::Display for Shim<E> {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                self.0.fmt(f)
            }
        }
        Box::new(Shim(err))
    }
}

impl CargoError for ::curl::Error {
    fn description(&self) -> &str {
        Error::description(self)
    }
}

impl CargoError for ::serde_json::Error {
    fn description(&self) -> &str {
        Error::description(self)
    }
}

impl CargoError for ::std::io::Error {
    fn description(&self) -> &str {
        Error::description(self)
    }
}

// =============================================================================
// Concrete errors

struct ConcreteCargoError {
    description: String,
    detail: Option<String>,
    cause: Option<Box<dyn CargoError>>,
    human: bool,
}

impl fmt::Display for ConcreteCargoError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.description)?;
        if let Some(ref s) = self.detail {
            write!(f, " ({})", s)?;
        }
        Ok(())
    }
}

impl CargoError for ConcreteCargoError {
    fn description(&self) -> &str {
        &self.description
    }
    fn cause(&self) -> Option<&dyn CargoError> {
        self.cause.as_ref().map(|c| &**c)
    }
    fn human(&self) -> bool {
        self.human
    }
}

#[derive(Debug, Clone, Copy)]
pub struct NotFound;

impl CargoError for NotFound {
    fn description(&self) -> &str {
        "not found"
    }

    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: "Not Found".to_string(),
            }],
        });
        response.status = (404, "Not Found");
        Some(response)
    }
}

impl fmt::Display for NotFound {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Not Found".fmt(f)
    }
}

#[derive(Debug, Clone, Copy)]
pub struct Unauthorized;

impl CargoError for Unauthorized {
    fn description(&self) -> &str {
        "unauthorized"
    }

    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: "must be logged in to perform that action".to_string(),
            }],
        });
        response.status = (403, "Forbidden");
        Some(response)
    }
}

impl fmt::Display for Unauthorized {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "must be logged in to perform that action".fmt(f)
    }
}

struct BadRequest(String);

impl CargoError for BadRequest {
    fn description(&self) -> &str {
        self.0.as_ref()
    }

    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: self.0.clone(),
            }],
        });
        response.status = (400, "Bad Request");
        Some(response)
    }
}

impl fmt::Display for BadRequest {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

pub fn internal_error(error: &str, detail: &str) -> Box<dyn CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: Some(detail.to_string()),
        cause: None,
        human: false,
    })
}

pub fn internal<S: ToString + ?Sized>(error: &S) -> Box<dyn CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        human: false,
    })
}

pub fn human<S: ToString + ?Sized>(error: &S) -> Box<dyn CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        human: true,
    })
}

/// This is intended to be used for errors being sent back to the Ember
/// frontend, not to cargo as cargo does not handle non-200 response codes well
/// (see <https://github.com/rust-lang/cargo/issues/3995>), but Ember requires
/// non-200 response codes for its stores to work properly.
///
/// Since this is going back to the UI these errors are treated the same as
/// `human` errors, other than the HTTP status code.
pub fn bad_request<S: ToString + ?Sized>(error: &S) -> Box<dyn CargoError> {
    Box::new(BadRequest(error.to_string()))
}

pub fn std_error(e: Box<dyn CargoError>) -> Box<dyn Error + Send> {
    #[derive(Debug)]
    struct E(Box<dyn CargoError>);
    impl Error for E {
        fn description(&self) -> &str {
            self.0.description()
        }
    }
    impl fmt::Display for E {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            write!(f, "{}", self.0)?;

            let mut err = &*self.0;
            while let Some(cause) = err.cause() {
                err = cause;
                write!(f, "\nCaused by: {}", err)?;
            }

            Ok(())
        }
    }
    Box::new(E(e))
}
<commit_msg>Make `CargoError` implement debug<commit_after>use std::any::Any;
use std::error::Error;
use std::fmt;

use conduit::Response;
use diesel::result::Error as DieselError;

use util::json_response;

#[derive(Serialize)]
struct StringError {
    detail: String,
}
#[derive(Serialize)]
struct Bad {
    errors: Vec<StringError>,
}

// =============================================================================
// CargoError trait

pub trait CargoError: Send + fmt::Display + fmt::Debug + 'static {
    fn description(&self) -> &str;
    fn cause(&self) -> Option<&(dyn CargoError)> {
        None
    }

    fn response(&self) -> Option<Response> {
        if self.human() {
            Some(json_response(&Bad {
                errors: vec![StringError {
                    detail: self.description().to_string(),
                }],
            }))
        } else {
            self.cause().and_then(|cause| cause.response())
        }
    }
    fn human(&self) -> bool {
        false
    }
}

impl CargoError for Box<dyn CargoError> {
    fn description(&self) -> &str {
        (**self).description()
    }
    fn cause(&self) -> Option<&dyn CargoError> {
        (**self).cause()
    }
    fn human(&self) -> bool {
        (**self).human()
    }
    fn response(&self) -> Option<Response> {
        (**self).response()
    }
}
impl<T: CargoError> CargoError for Box<T> {
    fn description(&self) -> &str {
        (**self).description()
    }
    fn cause(&self) -> Option<&dyn CargoError> {
        (**self).cause()
    }
    fn human(&self) -> bool {
        (**self).human()
    }
    fn response(&self) -> Option<Response> {
        (**self).response()
    }
}

pub type CargoResult<T> = Result<T, Box<dyn CargoError>>;

// =============================================================================
// Chaining errors

pub trait ChainError<T> {
    fn chain_error<E, F>(self, callback: F) -> CargoResult<T>
    where
        E: CargoError,
        F: FnOnce() -> E;
}

#[derive(Debug)]
struct ChainedError<E> {
    error: E,
    cause: Box<dyn CargoError>,
}

impl<T, F> ChainError<T> for F
where
    F: FnOnce() -> CargoResult<T>,
{
    fn chain_error<E, C>(self, callback: C) -> CargoResult<T>
    where
        E: CargoError,
        C: FnOnce() -> E,
    {
        self().chain_error(callback)
    }
}

impl<T, E: CargoError> ChainError<T> for Result<T, E> {
    fn chain_error<E2, C>(self, callback: C) -> CargoResult<T>
    where
        E2: CargoError,
        C: FnOnce() -> E2,
    {
        self.map_err(move |err| {
            Box::new(ChainedError {
                error: callback(),
                cause: Box::new(err),
            }) as Box<dyn CargoError>
        })
    }
}

impl<T> ChainError<T> for Option<T> {
    fn chain_error<E, C>(self, callback: C) -> CargoResult<T>
    where
        E: CargoError,
        C: FnOnce() -> E,
    {
        match self {
            Some(t) => Ok(t),
            None => Err(Box::new(callback())),
        }
    }
}

impl<E: CargoError> CargoError for ChainedError<E> {
    fn description(&self) -> &str {
        self.error.description()
    }
    fn cause(&self) -> Option<&dyn CargoError> {
        Some(&*self.cause)
    }
    fn response(&self) -> Option<Response> {
        self.error.response()
    }
    fn human(&self) -> bool {
        self.error.human()
    }
}

impl<E: CargoError> fmt::Display for ChainedError<E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} caused by {}", self.error, self.cause)
    }
}

// =============================================================================
// Error impls

impl<E: Any + Error + Send + 'static> From<E> for Box<dyn CargoError> {
    fn from(err: E) -> Box<dyn CargoError> {
        if let Some(err) = Any::downcast_ref::<DieselError>(&err) {
            if let DieselError::NotFound = *err {
                return Box::new(NotFound);
            }
        }

        #[derive(Debug)]
        struct Shim<E>(E);
        impl<E: Error + Send + 'static> CargoError for Shim<E> {
            fn description(&self) -> &str {
                Error::description(&self.0)
            }
        }
        impl<E: fmt::Display> fmt::Display for Shim<E> {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                self.0.fmt(f)
            }
        }
        Box::new(Shim(err))
    }
}

impl CargoError for ::curl::Error {
    fn description(&self) -> &str {
        Error::description(self)
    }
}

impl CargoError for ::serde_json::Error {
    fn description(&self) -> &str {
        Error::description(self)
    }
}

impl CargoError for ::std::io::Error {
    fn description(&self) -> &str {
        Error::description(self)
    }
}

// =============================================================================
// Concrete errors

#[derive(Debug)]
struct ConcreteCargoError {
    description: String,
    detail: Option<String>,
    cause: Option<Box<dyn CargoError>>,
    human: bool,
}

impl fmt::Display for ConcreteCargoError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.description)?;
        if let Some(ref s) = self.detail {
            write!(f, " ({})", s)?;
        }
        Ok(())
    }
}

impl CargoError for ConcreteCargoError {
    fn description(&self) -> &str {
        &self.description
    }
    fn cause(&self) -> Option<&dyn CargoError> {
        self.cause.as_ref().map(|c| &**c)
    }
    fn human(&self) -> bool {
        self.human
    }
}

#[derive(Debug, Clone, Copy)]
pub struct NotFound;

impl CargoError for NotFound {
    fn description(&self) -> &str {
        "not found"
    }

    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: "Not Found".to_string(),
            }],
        });
        response.status = (404, "Not Found");
        Some(response)
    }
}

impl fmt::Display for NotFound {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "Not Found".fmt(f)
    }
}

#[derive(Debug, Clone, Copy)]
pub struct Unauthorized;

impl CargoError for Unauthorized {
    fn description(&self) -> &str {
        "unauthorized"
    }

    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: "must be logged in to perform that action".to_string(),
            }],
        });
        response.status = (403, "Forbidden");
        Some(response)
    }
}

impl fmt::Display for Unauthorized {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "must be logged in to perform that action".fmt(f)
    }
}

#[derive(Debug)]
struct BadRequest(String);

impl CargoError for BadRequest {
    fn description(&self) -> &str {
        self.0.as_ref()
    }

    fn response(&self) -> Option<Response> {
        let mut response = json_response(&Bad {
            errors: vec![StringError {
                detail: self.0.clone(),
            }],
        });
        response.status = (400, "Bad Request");
        Some(response)
    }
}

impl fmt::Display for BadRequest {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

pub fn internal_error(error: &str, detail: &str) -> Box<dyn CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: Some(detail.to_string()),
        cause: None,
        human: false,
    })
}

pub fn internal<S: ToString + ?Sized>(error: &S) -> Box<dyn CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        human: false,
    })
}

pub fn human<S: ToString + ?Sized>(error: &S) -> Box<dyn CargoError> {
    Box::new(ConcreteCargoError {
        description: error.to_string(),
        detail: None,
        cause: None,
        human: true,
    })
}

/// This is intended to be used for errors being sent back to the Ember
/// frontend, not to cargo as cargo does not handle non-200 response codes well
/// (see <https://github.com/rust-lang/cargo/issues/3995>), but Ember requires
/// non-200 response codes for its stores to work properly.
///
/// Since this is going back to the UI these errors are treated the same as
/// `human` errors, other than the HTTP status code.
pub fn bad_request<S: ToString + ?Sized>(error: &S) -> Box<dyn CargoError> {
    Box::new(BadRequest(error.to_string()))
}

pub fn std_error(e: Box<dyn CargoError>) -> Box<dyn Error + Send> {
    #[derive(Debug)]
    struct E(Box<dyn CargoError>);
    impl Error for E {
        fn description(&self) -> &str {
            self.0.description()
        }
    }
    impl fmt::Display for E {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            write!(f, "{}", self.0)?;

            let mut err = &*self.0;
            while let Some(cause) = err.cause() {
                err = cause;
                write!(f, "\nCaused by: {}", err)?;
            }

            Ok(())
        }
    }
    Box::new(E(e))
}
<|endoftext|>


<commit_before>#[allow(deprecated)]
use tokio_timer::Deadline;
use tokio_timer::Timeout;

use futures::Future;

use std::time::{Instant, Duration};

/// An extension trait for `Future` that provides a variety of convenient
/// combinator functions.
///
/// Currently, there only is a [`timeout`] function, but this will increase
/// over time.
///
/// Users are not expected to implement this trait. All types that implement
/// `Future` already implement `FutureExt`.
///
/// This trait can be imported directly or via the Tokio prelude: `use
/// tokio::prelude::*`.
///
/// [`timeout`]: #method.timeout
pub trait FutureExt: Future {

    /// Creates a new future which allows `self` until `timeout`.
    ///
    /// This combinator creates a new future which wraps the receiving future
    /// with a timeout. The returned future is allowed to execute until it
    /// completes or `timeout` has elapsed, whichever happens first.
    ///
    /// If the future completes before `timeout` then the future will resolve
    /// with that item. Otherwise the future will resolve to an error.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// # extern crate futures;
    /// use tokio::prelude::*;
    /// use std::time::Duration;
    /// # use futures::future::{self, FutureResult};
    ///
    /// # fn long_future() -> FutureResult<(), ()> {
    /// #   future::ok(())
    /// # }
    /// #
    /// # fn main() {
    /// let future = long_future()
    ///     .timeout(Duration::from_secs(1))
    ///     .map_err(|e| println!("error = {:?}", e));
    ///
    /// tokio::run(future);
    /// # }
    /// ```
    fn timeout(self, timeout: Duration) -> Timeout<Self>
    where Self: Sized,
    {
        Timeout::new(self, timeout)
    }

    #[deprecated(since = "0.1.8", note = "use `timeout` instead")]
    #[allow(deprecated)]
    #[doc(hidden)]
    fn deadline(self, deadline: Instant) -> Deadline<Self>
    where Self: Sized,
    {
        Deadline::new(self, deadline)
    }
}

impl<T: ?Sized> FutureExt for T where T: Future {}
<commit_msg>Document that timeout-ed futures will be polled at least once (#603)<commit_after>#[allow(deprecated)]
use tokio_timer::Deadline;
use tokio_timer::Timeout;

use futures::Future;

use std::time::{Instant, Duration};

/// An extension trait for `Future` that provides a variety of convenient
/// combinator functions.
///
/// Currently, there only is a [`timeout`] function, but this will increase
/// over time.
///
/// Users are not expected to implement this trait. All types that implement
/// `Future` already implement `FutureExt`.
///
/// This trait can be imported directly or via the Tokio prelude: `use
/// tokio::prelude::*`.
///
/// [`timeout`]: #method.timeout
pub trait FutureExt: Future {

    /// Creates a new future which allows `self` until `timeout`.
    ///
    /// This combinator creates a new future which wraps the receiving future
    /// with a timeout. The returned future is allowed to execute until it
    /// completes or `timeout` has elapsed, whichever happens first.
    ///
    /// If the future completes before `timeout` then the future will resolve
    /// with that item. Otherwise the future will resolve to an error.
    ///
    /// The future is guaranteed to be polled at least once, even if `timeout`
    /// is set to zero.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// # extern crate futures;
    /// use tokio::prelude::*;
    /// use std::time::Duration;
    /// # use futures::future::{self, FutureResult};
    ///
    /// # fn long_future() -> FutureResult<(), ()> {
    /// #   future::ok(())
    /// # }
    /// #
    /// # fn main() {
    /// let future = long_future()
    ///     .timeout(Duration::from_secs(1))
    ///     .map_err(|e| println!("error = {:?}", e));
    ///
    /// tokio::run(future);
    /// # }
    /// ```
    fn timeout(self, timeout: Duration) -> Timeout<Self>
    where Self: Sized,
    {
        Timeout::new(self, timeout)
    }

    #[deprecated(since = "0.1.8", note = "use `timeout` instead")]
    #[allow(deprecated)]
    #[doc(hidden)]
    fn deadline(self, deadline: Instant) -> Deadline<Self>
    where Self: Sized,
    {
        Deadline::new(self, deadline)
    }
}

impl<T: ?Sized> FutureExt for T where T: Future {}

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

    #[test]
    fn timeout_polls_at_least_once() {
        let base_future = future::result::<(), ()>(Ok(()));
        let timeouted_future = base_future.timeout(Duration::new(0, 0));
        assert!(timeouted_future.wait().is_ok());
    }
}
<|endoftext|>


<commit_before>use std::result::Result;

use serde::de::{Deserialize, Deserializer, Error};
use serde::ser::{Serialize, Serializer};

pub const MAC_ADDR_LEN: usize = 6;

#[derive(Clone, Debug, PartialEq)]
pub struct MacAddr {
    bytes: [u8; MAC_ADDR_LEN],
}

impl MacAddr {
    // The error contains the str that failed to be parsed, for nicer error message generation.
    pub fn parse_str<'a, S>(s: &'a S) -> Result<MacAddr, &'a str>
    where
        S: AsRef<str> + ?Sized,
    {
        let v: Vec<&str> = s.as_ref().split(':').collect();
        let mut bytes = [0u8; MAC_ADDR_LEN];

        if v.len() != MAC_ADDR_LEN {
            return Err(s.as_ref());
        }

        for i in 0..MAC_ADDR_LEN {
            if v[i].len() != 2 {
                return Err(s.as_ref());
            }
            bytes[i] = u8::from_str_radix(v[i], 16).map_err(|_| s.as_ref())?;
        }

        Ok(MacAddr { bytes })
    }

    pub fn get_bytes(&self) -> &[u8] {
        &self.bytes
    }

    pub fn to_string(&self) -> String {
        let b = &self.bytes;
        format!(
            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
            b[0], b[1], b[2], b[3], b[4], b[5]
        )
    }
}

impl Serialize for MacAddr {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.to_string().serialize(serializer)
    }
}

impl<'de> Deserialize<'de> for MacAddr {
    fn deserialize<D>(deserializer: D) -> Result<MacAddr, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        MacAddr::parse_str(&s).map_err(|_| D::Error::custom("The provided MAC address is invalid."))
    }
}

#[cfg(test)]
mod tests {
    extern crate serde_json;

    use super::*;

    #[test]
    fn test_mac_addr() {
        // too long
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:aa:aa").is_err());

        // invalid hex
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:ax").is_err());

        // single digit mac address component should be invalid
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:b").is_err());

        // components with more than two digits should also be invalid
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:bbb").is_err());

        let mac = MacAddr::parse_str("12:34:56:78:9a:BC").unwrap();

        println!("parsed MAC address: {}", mac.to_string());

        let bytes = mac.get_bytes();
        assert_eq!(bytes, [0x12u8, 0x34, 0x56, 0x78, 0x9a, 0xbc]);
    }

    #[test]
    fn test_mac_addr_serialization_and_deserialization() {
        let mac: MacAddr =
            serde_json::from_str("\"12:34:56:78:9a:bc\"").expect("MacAddr deserialization failed.");

        let bytes = mac.get_bytes();
        assert_eq!(bytes, [0x12u8, 0x34, 0x56, 0x78, 0x9a, 0xbc]);

        let s = serde_json::to_string(&mac).expect("MacAddr serialization failed.");
        assert_eq!(s, "\"12:34:56:78:9a:bc\"");
    }
}
<commit_msg>net_util: added from_bytes() to MacAddr<commit_after>use std::result::Result;

use serde::de::{Deserialize, Deserializer, Error};
use serde::ser::{Serialize, Serializer};

pub const MAC_ADDR_LEN: usize = 6;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct MacAddr {
    bytes: [u8; MAC_ADDR_LEN],
}

impl MacAddr {
    // The error contains the str that failed to be parsed, for nicer error message generation.
    pub fn parse_str<S>(s: &S) -> Result<MacAddr, &str>
    where
        S: AsRef<str> + ?Sized,
    {
        let v: Vec<&str> = s.as_ref().split(':').collect();
        let mut bytes = [0u8; MAC_ADDR_LEN];

        if v.len() != MAC_ADDR_LEN {
            return Err(s.as_ref());
        }

        for i in 0..MAC_ADDR_LEN {
            if v[i].len() != 2 {
                return Err(s.as_ref());
            }
            bytes[i] = u8::from_str_radix(v[i], 16).map_err(|_| s.as_ref())?;
        }

        Ok(MacAddr { bytes })
    }

    // Does not check whether src.len() == MAC_ADDR_LEN.
    #[inline]
    pub fn from_bytes_unchecked(src: &[u8]) -> MacAddr {
        // TODO: using something like std::mem::uninitialized could avoid the extra initialization,
        // if this ever becomes a performance bottleneck.
        let mut bytes = [0u8; MAC_ADDR_LEN];
        &bytes[..].copy_from_slice(&src[..]);

        MacAddr { bytes }
    }

    // An error can only occur if the slice length is different from MAC_ADDR_LEN.
    #[inline]
    pub fn from_bytes(src: &[u8]) -> Result<MacAddr, ()> {
        if src.len() != MAC_ADDR_LEN {
            return Err(());
        }
        Ok(MacAddr::from_bytes_unchecked(src))
    }

    #[inline]
    pub fn get_bytes(&self) -> &[u8] {
        &self.bytes
    }

    pub fn to_string(&self) -> String {
        let b = &self.bytes;
        format!(
            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
            b[0], b[1], b[2], b[3], b[4], b[5]
        )
    }
}

impl Serialize for MacAddr {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.to_string().serialize(serializer)
    }
}

impl<'de> Deserialize<'de> for MacAddr {
    fn deserialize<D>(deserializer: D) -> Result<MacAddr, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        MacAddr::parse_str(&s).map_err(|_| D::Error::custom("The provided MAC address is invalid."))
    }
}

#[cfg(test)]
mod tests {
    extern crate serde_json;

    use super::*;

    #[test]
    fn test_mac_addr() {
        // too long
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:aa:aa").is_err());

        // invalid hex
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:ax").is_err());

        // single digit mac address component should be invalid
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:b").is_err());

        // components with more than two digits should also be invalid
        assert!(MacAddr::parse_str("aa:aa:aa:aa:aa:bbb").is_err());

        let mac = MacAddr::parse_str("12:34:56:78:9a:BC").unwrap();

        println!("parsed MAC address: {}", mac.to_string());

        let bytes = mac.get_bytes();
        assert_eq!(bytes, [0x12u8, 0x34, 0x56, 0x78, 0x9a, 0xbc]);
    }

    #[test]
    fn test_from_bytes() {
        let src1 = [0x01, 0x02, 0x03, 0x04, 0x05];
        let src2 = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
        let src3 = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];

        assert!(MacAddr::from_bytes(&src1[..]).is_err());

        let x = MacAddr::from_bytes(&src2[..]).unwrap();
        assert_eq!(x.to_string(), String::from("01:02:03:04:05:06"));

        assert!(MacAddr::from_bytes(&src3[..]).is_err());
    }

    #[test]
    fn test_mac_addr_serialization_and_deserialization() {
        let mac: MacAddr =
            serde_json::from_str("\"12:34:56:78:9a:bc\"").expect("MacAddr deserialization failed.");

        let bytes = mac.get_bytes();
        assert_eq!(bytes, [0x12u8, 0x34, 0x56, 0x78, 0x9a, 0xbc]);

        let s = serde_json::to_string(&mac).expect("MacAddr serialization failed.");
        assert_eq!(s, "\"12:34:56:78:9a:bc\"");
    }
}
<|endoftext|>


<commit_before>use vector::Geometry;

#[derive(Clone, Copy, PartialEq, Show)]
pub enum Geom {
    Point(Point),
}

#[derive(Clone, Copy, PartialEq, Show)]
pub struct Point {
    pub x: f64,
    pub y: f64,
}
<commit_msg>remove leftover import<commit_after>#[derive(Clone, Copy, PartialEq, Show)]
pub enum Geom {
    Point(Point),
}

#[derive(Clone, Copy, PartialEq, Show)]
pub struct Point {
    pub x: f64,
    pub y: f64,
}
<|endoftext|>


<commit_before>use webcore::value::Reference;
use webcore::try_from::TryInto;
use webcore::reference_type::ReferenceType;

/// A blob object represents a file-like object of immutable, raw data.
/// Blobs represent data that isn't necessarily in a JavaScript-native format.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
// https://w3c.github.io/FileAPI/#dfn-Blob
pub trait IBlob: ReferenceType {
    /// The size, in bytes, of the data contained in the Blob object.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/size)
    // https://w3c.github.io/FileAPI/#ref-for-dfn-size%E2%91%A0
    fn len( &self ) -> u64 {
        let reference = self.as_ref();
        let length: u64 = js!( return @{reference}.size; ).try_into().unwrap();
        length
    }

    /// A string indicating the MIME type of the data contained in the `Blob`.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/type)
    // https://w3c.github.io/FileAPI/#ref-for-dfn-type%E2%91%A0
    fn mime( &self ) -> Option< String > {
        let reference = self.as_ref();
        let mime: String = js!( return @{reference}.type; ).try_into().unwrap();
        if mime.is_empty() {
            None
        } else {
            Some( mime )
        }
    }
}

/// A reference to a JavaScript object which implements the [IBlob](trait.IBlob.html)
/// interface.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
// https://w3c.github.io/FileAPI/#dfn-Blob
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Blob")]
pub struct Blob( Reference );

impl IBlob for Blob {}
<commit_msg>Implements Blob empty constructor<commit_after>use webcore::value::Reference;
use webcore::try_from::TryInto;
use webcore::reference_type::ReferenceType;

/// A blob object represents a file-like object of immutable, raw data.
/// Blobs represent data that isn't necessarily in a JavaScript-native format.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
// https://w3c.github.io/FileAPI/#dfn-Blob
pub trait IBlob: ReferenceType {
    /// The size, in bytes, of the data contained in the Blob object.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/size)
    // https://w3c.github.io/FileAPI/#ref-for-dfn-size%E2%91%A0
    fn len( &self ) -> u64 {
        let reference = self.as_ref();
        let length: u64 = js!( return @{reference}.size; ).try_into().unwrap();
        length
    }

    /// A string indicating the MIME type of the data contained in the `Blob`.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/type)
    // https://w3c.github.io/FileAPI/#ref-for-dfn-type%E2%91%A0
    fn mime( &self ) -> Option< String > {
        let reference = self.as_ref();
        let mime: String = js!( return @{reference}.type; ).try_into().unwrap();
        if mime.is_empty() {
            None
        } else {
            Some( mime )
        }
    }
}

/// A reference to a JavaScript object which implements the [IBlob](trait.IBlob.html)
/// interface.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
// https://w3c.github.io/FileAPI/#dfn-Blob
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Blob")]
pub struct Blob( Reference );

impl IBlob for Blob {}

impl Blob {
    /// Creates a new `Blob`.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob)
    // https://w3c.github.io/FileAPI/#constructorBlob
    pub fn new() -> Self {
        js! (
            return new Blob();
        ).try_into().unwrap()
    }
}
<|endoftext|>


<commit_before>extern crate procrs;
extern crate argparse;
#[macro_use]
extern crate prettytable;
use prettytable::Table;
use prettytable::format::FormatBuilder;
use std::collections::HashMap;
use std::iter::repeat;
use procrs::pid::*;
use procrs::TaskId;
use argparse::{ArgumentParser, StoreTrue, Store};

fn main() {
    let opts = parse_args();
    let (query, long, perf, verbose, tree) =
        (opts.query, opts.long, opts.perf, opts.verbose, opts.tree);

    let mut pids = PidIter::new_query(query).unwrap()
        .collect::<Result<Vec<_>, _>>().unwrap();

    let mut name_indent = HashMap::new();

    if verbose {
        for pid in pids {
            println!("{:?}", pid);
        }
        return
    }

    if opts.tree {
        pids = treeify_names(pids, &mut name_indent);
    } else {
        pids.sort_by(|p1, p2| p1.stat.pid.cmp(&p2.stat.pid));
    };
    // Assume hertz is 100.
    // TODO: Look this up via syscall (no /proc value for it)
    let hertz = 100;
    // let minute_hertz = hertz * 60;
    // let hour_hertz = minute_hertz * 60;

    let mut table = Table::init(
        pids.iter().map(|p| {
            // When we have a tree, the name is prepended with an indent.
            let mut name = match tree {
                false => String::new(),
                true => name_indent.remove(&p.stat.pid).unwrap()
            };

            // For long output, try using the cmdline first.
            // FIXME: Sometimes prog_name != cmdline[0].
            if !long {
                name.push_str(&p.stat.comm);
            } else {
                let cmdline = p.cmdline.join(" ");
                name.push_str(
                    match cmdline {
                         ref s if s.len() > 0 => s,
                        _ => &p.stat.comm
                    }
                );
            }

            match (long, perf) {
                (_, false) => {
                    row![p.stat.pid, p.stat.ppid, name]
                },
                (_, true) => {
                    let rss = p.status.vmrss.map(|m| (m / 1024).to_string()).unwrap_or("".to_owned());
                    // FIXME: This algorithm is definitely wrong
                    let _second_utime = p.stat.utime / hertz;
                    let second_utime = _second_utime % 60;
                    let _minute_utime = _second_utime / 60;
                    let minute_utime = _minute_utime % 60;
                    let hour_utime = _minute_utime / 60;
                    let utime = format!(
                        "{:02}:{:02}:{:02}",
                        hour_utime,
                        minute_utime,
                        second_utime
                    );
                    row![p.stat.pid, p.stat.ppid, rss, utime, name]
                }
            }
        }).collect::<Vec<_>>()
    );

    table.set_titles(
        match (long, perf) {
            (false, false) =>
                row!["Pid", "Ppid", "Cmd"],
            (true, false) =>
                row!["Pid", "Ppid", "Cmd"],
            (false, true) =>
                row!["Pid", "Ppid", "RSS", "Time", "Cmd"],
            (true, true) =>
                row!["Pid", "Ppid", "RSS", "Time", "Cmd"]
        }
    );
    table.set_format(
        FormatBuilder::new()
            .column_separator(' ')
            .build()
    );
    table.printstd();
}

// Given a vector of Pid structs, treeify their names, and return them in the right order.
// This is similar to ps -AH.
fn treeify_names(pids: Vec<Pid>, name_indents: &mut HashMap<TaskId, String>) -> Vec<Pid> {
    let mut child_pids = HashMap::new();
    for pid in pids {
        let ppid = pid.stat.ppid;
        child_pids.entry(ppid)
            .or_insert(Vec::new())
            .push(pid);
    }
    enumerate_children(0, &mut child_pids, name_indents, -1)
}

// Enumerate children pids, and return them.
fn enumerate_children(pid: TaskId, child_pids: &mut HashMap<TaskId, Vec<Pid>>,
    name_indents: &mut HashMap<TaskId, String>, indent: i32) -> Vec<Pid> {
    name_indents.insert(pid,
        match indent {
            i if i >= 0 =>
                repeat("  ").take(i as usize).collect::<String>(),
            _ => "".to_owned()
        }
    );
    let mut pids = Vec::new();
    let ppids = match child_pids.remove(&pid) {
        Some(v) => v,
        None => { return pids; }
    };
    for pid in ppids {
        let pid_num = pid.stat.pid;
        pids.push(pid);
        pids.append(
            &mut enumerate_children(pid_num, child_pids, name_indents, indent + 1)
        );
    }
    pids
}

struct ProgOpts {
    query: PidQuery,
    tree: bool,
    perf: bool,
    long: bool,
    verbose: bool
}

fn parse_args() -> ProgOpts {
    let mut opts = ProgOpts {
        query: PidQuery::NoneQuery,
        tree: false,
        perf: false,
        long: false,
        verbose: false
    };

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Query linux processes");
        ap.refer(&mut opts.tree)
            .add_option(&["-t", "--tree"], StoreTrue, "Display process tree");
        ap.refer(&mut opts.perf)
            .add_option(&["-p", "--perf"], StoreTrue, "Display performance information");
        ap.refer(&mut opts.long)
            .add_option(&["-l", "--long"], StoreTrue, "Display more information");
        ap.refer(&mut opts.verbose)
            .add_option(&["-v", "--verbose"], StoreTrue, "Verbose output");
        ap.refer(&mut opts.query)
            .add_argument("query", Store, "Optional query to search by, pid or string");
        ap.parse_args_or_exit();
    }

    opts
}
<commit_msg>Legit fix for cputime (including stime)<commit_after>extern crate procrs;
extern crate argparse;
#[macro_use]
extern crate prettytable;
use prettytable::Table;
use prettytable::format::FormatBuilder;
use std::collections::HashMap;
use std::iter::repeat;
use procrs::pid::*;
use procrs::TaskId;
use argparse::{ArgumentParser, StoreTrue, Store};

fn main() {
    let opts = parse_args();
    let (query, long, perf, verbose, tree) =
        (opts.query, opts.long, opts.perf, opts.verbose, opts.tree);

    let mut pids = PidIter::new_query(query).unwrap()
        .collect::<Result<Vec<_>, _>>().unwrap();

    let mut name_indent = HashMap::new();

    if verbose {
        for pid in pids {
            println!("{:?}", pid);
        }
        return
    }

    if opts.tree {
        pids = treeify_names(pids, &mut name_indent);
    } else {
        pids.sort_by(|p1, p2| p1.stat.pid.cmp(&p2.stat.pid));
    };
    // Assume hertz is 100.
    // TODO: Look this up via syscall (no /proc value for it)
    let hertz = 100;
    let minute_hertz = hertz * 60;
    let hour_hertz = minute_hertz * 60;

    let mut table = Table::init(
        pids.iter().map(|p| {
            // When we have a tree, the name is prepended with an indent.
            let mut name = match tree {
                false => String::new(),
                true => name_indent.remove(&p.stat.pid).unwrap()
            };

            // For long output, try using the cmdline first.
            // FIXME: Sometimes prog_name != cmdline[0].
            if !long {
                name.push_str(&p.stat.comm);
            } else {
                let cmdline = p.cmdline.join(" ");
                name.push_str(
                    match cmdline {
                         ref s if s.len() > 0 => s,
                        _ => &p.stat.comm
                    }
                );
            }

            match (long, perf) {
                (_, false) => {
                    row![p.stat.pid, p.stat.ppid, name]
                },
                (_, true) => {
                    let rss = p.status.vmrss.map(|m| (m / 1024).to_string()).unwrap_or("".to_owned());
                    let raw_time = p.stat.utime + p.stat.stime;
                    let second_utime = raw_time / hertz % 60;
                    let minute_utime = raw_time / minute_hertz % 60;
                    let hour_utime = raw_time / hour_hertz % 60;
                    let cputime = format!(
                        "{:02}:{:02}:{:02}",
                        hour_utime,
                        minute_utime,
                        second_utime
                    );
                    row![p.stat.pid, p.stat.ppid, rss, cputime, name]
                }
            }
        }).collect::<Vec<_>>()
    );

    table.set_titles(
        match (long, perf) {
            (false, false) =>
                row!["Pid", "Ppid", "Cmd"],
            (true, false) =>
                row!["Pid", "Ppid", "Cmd"],
            (false, true) =>
                row!["Pid", "Ppid", "RSS", "Time", "Cmd"],
            (true, true) =>
                row!["Pid", "Ppid", "RSS", "Time", "Cmd"]
        }
    );
    table.set_format(
        FormatBuilder::new()
            .column_separator(' ')
            .build()
    );
    table.printstd();
}

// Given a vector of Pid structs, treeify their names, and return them in the right order.
// This is similar to ps -AH.
fn treeify_names(pids: Vec<Pid>, name_indents: &mut HashMap<TaskId, String>) -> Vec<Pid> {
    let mut child_pids = HashMap::new();
    for pid in pids {
        let ppid = pid.stat.ppid;
        child_pids.entry(ppid)
            .or_insert(Vec::new())
            .push(pid);
    }
    enumerate_children(0, &mut child_pids, name_indents, -1)
}

// Enumerate children pids, and return them.
fn enumerate_children(pid: TaskId, child_pids: &mut HashMap<TaskId, Vec<Pid>>,
    name_indents: &mut HashMap<TaskId, String>, indent: i32) -> Vec<Pid> {
    name_indents.insert(pid,
        match indent {
            i if i >= 0 =>
                repeat("  ").take(i as usize).collect::<String>(),
            _ => "".to_owned()
        }
    );
    let mut pids = Vec::new();
    let ppids = match child_pids.remove(&pid) {
        Some(v) => v,
        None => { return pids; }
    };
    for pid in ppids {
        let pid_num = pid.stat.pid;
        pids.push(pid);
        pids.append(
            &mut enumerate_children(pid_num, child_pids, name_indents, indent + 1)
        );
    }
    pids
}

struct ProgOpts {
    query: PidQuery,
    tree: bool,
    perf: bool,
    long: bool,
    verbose: bool
}

fn parse_args() -> ProgOpts {
    let mut opts = ProgOpts {
        query: PidQuery::NoneQuery,
        tree: false,
        perf: false,
        long: false,
        verbose: false
    };

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Query linux processes");
        ap.refer(&mut opts.tree)
            .add_option(&["-t", "--tree"], StoreTrue, "Display process tree");
        ap.refer(&mut opts.perf)
            .add_option(&["-p", "--perf"], StoreTrue, "Display performance information");
        ap.refer(&mut opts.long)
            .add_option(&["-l", "--long"], StoreTrue, "Display more information");
        ap.refer(&mut opts.verbose)
            .add_option(&["-v", "--verbose"], StoreTrue, "Verbose output");
        ap.refer(&mut opts.query)
            .add_argument("query", Store, "Optional query to search by, pid or string");
        ap.parse_args_or_exit();
    }

    opts
}
<|endoftext|>