<commit_before>#![crate_id = "graphics"]
#![deny(missing_doc)]

//! Attempt of creating a cheap drawing context.

use std::num::Float;

pub type Matrix2d = [f64, ..6];
pub type Color = [f64, ..4];
pub type Rectangle = [f64, ..4];

/// Implemented by all graphics back-ends.
/// This trait uses default methods to simplify implementation.
pub trait BackEnd {
    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f64(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f64(&mut self, _vertices: &[f64], _colors: &[f64]) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f32(&mut self, _vertices: &[f32], _colors: &[f32]) {}
}

/// Implemented by contexts that can transform.
pub trait Transform2d<'a> {
    /// Translate x and y.
    fn trans(&'a self, x: f64, y: f64) -> Self;

    /// Rotates degrees.
    #[inline(always)]
    fn rot_deg(&'a self, angle: f64) -> Self {
        let pi: f64 = Float::pi();
        self.rot_rad(angle * pi / 180.0)
    }

    /// Rotate radians.
    fn rot_rad(&'a self, angle: f64) -> Self;
    /// Scale.
    fn scale(&'a self, sx: f64, sy: f64) -> Self;
    /// Shear.
    fn shear(&'a self, sx: f64, sy: f64) -> Self;
}

/// A structure that might contain a value or a borrowed value.
/// This is to used as building block to create data structure
/// that is partially based on an existing structure.
pub enum Field<'a, T> {
    /// Contains a value.
    Value(T),
    /// Contains a borrowed pointer.
    Borrowed(&'a T),
}

impl<'a, T> Field<'a, T> {
    /// Gets a read only value.
    #[inline(always)]
    pub fn get(&'a self) -> &'a T {
        match *self {
            Value(ref val) => val,
            Borrowed(rval) => rval,
        }
    }
}

/// Multiplies two matrices.
#[inline(always)]
pub fn multiply(m: &[f64, ..6], b: &[f64, ..6]) -> Matrix2d {
    [m[0]*b[0]+m[1]*b[3]+m[2]*0.0,  m[0]*b[1]+m[1]*b[4]+m[2]*0.0,  m[0]*b[2]+m[1]*b[5]+m[2]*1.0,
     m[3]*b[0]+m[4]*b[3]+m[5]*0.0,  m[3]*b[1]+m[4]*b[4]+m[5]*0.0,  m[3]*b[2]+m[4]*b[5]+m[5]*1.0]
}

/// Creates a translation matrix.
#[inline(always)]
pub fn translate(x: f64, y: f64) -> Matrix2d {
    [1.0, 0.0, x,
     0.0, 1.0, y]
}

/// Creates a rotation matrix.
#[inline(always)]
pub fn rotate_radians(angle: f64) -> Matrix2d {
    let c = angle.cos();
    let s = angle.sin();
    [c, s, 0.0,
    -s, c, 0.0]
}

/// Create a scale matrix.
#[inline(always)]
pub fn scale(sx: f64, sy: f64) -> Matrix2d {
    [sx, 0.0, 0.0,
     0.0, sy, 0.0]
}

/// Create a shear matrix.
#[inline(always)]
pub fn shear(sx: f64, sy: f64) -> Matrix2d {
    [1.0, sx, 0.0,
     sy, 1.0, 0.0]
}

/// Drawing 2d context.
pub struct Context<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
}

impl<'a> Transform2d<'a> for Context<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let trans = translate(x, y);
                 multiply(&trans, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let rot = rotate_radians(angle);
                multiply(&rot, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let scale = scale(sx, sy);
                multiply(&scale, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let shear = shear(sx, sy);
                multiply(&shear, self.transform.get())
            }),
        }
    }
}

impl<'a> Context<'a> {
    /// Creates a new drawing context.
    pub fn new() -> Context {
        Context {
            base:  Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
            transform: Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
        }
    }

}

#[test]
fn test_context() {
    let c = Context::new();
    {
        let d = c.trans(20.0, 40.0);
        let d = d.trans(10.0, 10.0);
        assert_eq!(d.transform.get()[2], 30.0);
        assert_eq!(d.transform.get()[5], 50.0);
    }
    assert_eq!(c.transform.get()[2], 0.0);
    assert_eq!(c.transform.get()[5], 0.0);

    let c = c.rot_deg(90.0);
    assert!((c.transform.get()[0] - 0.0).abs() < 0.00001);
    assert!((c.transform.get()[1] - 1.0).abs() < 0.00001);
}

#[test]
fn test_scale() {
    let c = Context::new();
    let c = c.scale(2.0, 3.0);
    assert!((c.transform.get()[0] - 2.0).abs() < 0.00001);
    assert!((c.transform.get()[4] - 3.0).abs() < 0.00001);
}

/// A context with color information.
pub struct ColorContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for ColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }
}

/// A rectangle context.
pub struct RectangleContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    rect: Field<'a, Rectangle>,
}

impl<'a> Transform2d<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }
}

/// A rectangle color context.
pub struct RectangleColorContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    rect: Field<'a, Rectangle>,
    color: Field<'a, Color>,
}

<commit_msg>Transform2d for RectangleColorContext<commit_after>#![crate_id = "graphics"]
#![deny(missing_doc)]

//! Attempt of creating a cheap drawing context.

use std::num::Float;

pub type Matrix2d = [f64, ..6];
pub type Color = [f64, ..4];
pub type Rectangle = [f64, ..4];

/// Implemented by all graphics back-ends.
/// This trait uses default methods to simplify implementation.
pub trait BackEnd {
    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f64(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f64(&mut self, _vertices: &[f64], _colors: &[f64]) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f32(&mut self, _vertices: &[f32], _colors: &[f32]) {}
}

/// Implemented by contexts that can transform.
pub trait Transform2d<'a> {
    /// Translate x and y.
    fn trans(&'a self, x: f64, y: f64) -> Self;

    /// Rotates degrees.
    #[inline(always)]
    fn rot_deg(&'a self, angle: f64) -> Self {
        let pi: f64 = Float::pi();
        self.rot_rad(angle * pi / 180.0)
    }

    /// Rotate radians.
    fn rot_rad(&'a self, angle: f64) -> Self;
    /// Scale.
    fn scale(&'a self, sx: f64, sy: f64) -> Self;
    /// Shear.
    fn shear(&'a self, sx: f64, sy: f64) -> Self;
}

/// A structure that might contain a value or a borrowed value.
/// This is to used as building block to create data structure
/// that is partially based on an existing structure.
pub enum Field<'a, T> {
    /// Contains a value.
    Value(T),
    /// Contains a borrowed pointer.
    Borrowed(&'a T),
}

impl<'a, T> Field<'a, T> {
    /// Gets a read only value.
    #[inline(always)]
    pub fn get(&'a self) -> &'a T {
        match *self {
            Value(ref val) => val,
            Borrowed(rval) => rval,
        }
    }
}

/// Multiplies two matrices.
#[inline(always)]
pub fn multiply(m: &[f64, ..6], b: &[f64, ..6]) -> Matrix2d {
    [m[0]*b[0]+m[1]*b[3]+m[2]*0.0,  m[0]*b[1]+m[1]*b[4]+m[2]*0.0,  m[0]*b[2]+m[1]*b[5]+m[2]*1.0,
     m[3]*b[0]+m[4]*b[3]+m[5]*0.0,  m[3]*b[1]+m[4]*b[4]+m[5]*0.0,  m[3]*b[2]+m[4]*b[5]+m[5]*1.0]
}

/// Creates a translation matrix.
#[inline(always)]
pub fn translate(x: f64, y: f64) -> Matrix2d {
    [1.0, 0.0, x,
     0.0, 1.0, y]
}

/// Creates a rotation matrix.
#[inline(always)]
pub fn rotate_radians(angle: f64) -> Matrix2d {
    let c = angle.cos();
    let s = angle.sin();
    [c, s, 0.0,
    -s, c, 0.0]
}

/// Create a scale matrix.
#[inline(always)]
pub fn scale(sx: f64, sy: f64) -> Matrix2d {
    [sx, 0.0, 0.0,
     0.0, sy, 0.0]
}

/// Create a shear matrix.
#[inline(always)]
pub fn shear(sx: f64, sy: f64) -> Matrix2d {
    [1.0, sx, 0.0,
     sy, 1.0, 0.0]
}

/// Drawing 2d context.
pub struct Context<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
}

impl<'a> Transform2d<'a> for Context<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let trans = translate(x, y);
                 multiply(&trans, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let rot = rotate_radians(angle);
                multiply(&rot, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let scale = scale(sx, sy);
                multiply(&scale, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let shear = shear(sx, sy);
                multiply(&shear, self.transform.get())
            }),
        }
    }
}

impl<'a> Context<'a> {
    /// Creates a new drawing context.
    pub fn new() -> Context {
        Context {
            base:  Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
            transform: Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
        }
    }

}

#[test]
fn test_context() {
    let c = Context::new();
    {
        let d = c.trans(20.0, 40.0);
        let d = d.trans(10.0, 10.0);
        assert_eq!(d.transform.get()[2], 30.0);
        assert_eq!(d.transform.get()[5], 50.0);
    }
    assert_eq!(c.transform.get()[2], 0.0);
    assert_eq!(c.transform.get()[5], 0.0);

    let c = c.rot_deg(90.0);
    assert!((c.transform.get()[0] - 0.0).abs() < 0.00001);
    assert!((c.transform.get()[1] - 1.0).abs() < 0.00001);
}

#[test]
fn test_scale() {
    let c = Context::new();
    let c = c.scale(2.0, 3.0);
    assert!((c.transform.get()[0] - 2.0).abs() < 0.00001);
    assert!((c.transform.get()[4] - 3.0).abs() < 0.00001);
}

/// A context with color information.
pub struct ColorContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for ColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }
}

/// A rectangle context.
pub struct RectangleContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    rect: Field<'a, Rectangle>,
}

impl<'a> Transform2d<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }
}

/// A rectangle color context.
pub struct RectangleColorContext<'a> {
    base: Field<'a, Matrix2d>,
    transform: Field<'a, Matrix2d>,
    rect: Field<'a, Rectangle>,
    color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for RectangleColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

<|endoftext|>


<commit_before>use crate::alloc::borrow::Cow;
use crate::{Machine, Relocation, SectionIndex, SectionKind, Symbol, SymbolMap, Uuid};

/// An object file.
pub trait Object<'data, 'file> {
    /// A segment in the object file.
    type Segment: ObjectSegment<'data>;

    /// An iterator over the segments in the object file.
    type SegmentIterator: Iterator<Item = Self::Segment>;

    /// A section in the object file.
    type Section: ObjectSection<'data>;

    /// An iterator over the sections in the object file.
    type SectionIterator: Iterator<Item = Self::Section>;

    /// An iterator over the symbols in the object file.
    type SymbolIterator: Iterator<Item = Symbol<'data>>;

    /// Get the machine type of the file.
    fn machine(&self) -> Machine;

    /// Get an iterator over the segments in the file.
    fn segments(&'file self) -> Self::SegmentIterator;

    /// Get the entry point address of the binary
    fn entry(&'file self) -> u64;

    /// Get the section named `section_name`, if such a section exists.
    ///
    /// If `section_name` starts with a '.' then it is treated as a system section name,
    /// and is compared using the conventions specific to the object file format. This
    /// includes:
    /// - if ".text" is requested for a Mach-O object file, then the actual
    /// section name that is searched for is "__text".
    /// - if ".debug_info" is requested for an ELF object file, then
    /// ".zdebug_info" may be returned (and similarly for other debug sections).
    ///
    /// For some object files, multiple segments may contain sections with the same
    /// name. In this case, the first matching section will be used.
    fn section_by_name(&'file self, section_name: &str) -> Option<Self::Section>;

    /// Get the section at the given index.
    ///
    /// The meaning of the index depends on the object file.
    ///
    /// For some object files, this requires iterating through all sections.
    fn section_by_index(&'file self, index: SectionIndex) -> Option<Self::Section>;

    /// Get the contents of the section named `section_name`, if such
    /// a section exists.
    ///
    /// The `section_name` is interpreted according to `Self::section_by_name`.
    ///
    /// This may decompress section data.
    fn section_data_by_name(&'file self, section_name: &str) -> Option<Cow<'data, [u8]>> {
        self.section_by_name(section_name)
            .map(|section| section.uncompressed_data())
    }

    /// Get an iterator over the sections in the file.
    fn sections(&'file self) -> Self::SectionIterator;

    /// Get the debugging symbol at the given index.
    ///
    /// This is similar to `self.symbols().nth(index)`, except that
    /// the index will take into account malformed or unsupported symbols.
    fn symbol_by_index(&self, index: u64) -> Option<Symbol<'data>>;

    /// Get an iterator over the debugging symbols in the file.
    ///
    /// This may skip over symbols that are malformed or unsupported.
    fn symbols(&'file self) -> Self::SymbolIterator;

    /// Get an iterator over the dynamic linking symbols in the file.
    ///
    /// This may skip over symbols that are malformed or unsupported.
    fn dynamic_symbols(&'file self) -> Self::SymbolIterator;

    /// Construct a map from addresses to symbols.
    fn symbol_map(&self) -> SymbolMap<'data>;

    /// Return true if the file is little endian, false if it is big endian.
    fn is_little_endian(&self) -> bool;

    /// Return true if the file contains debug information sections, false if not.
    fn has_debug_symbols(&self) -> bool;

    /// The UUID from a Mach-O `LC_UUID` load command.
    #[inline]
    fn mach_uuid(&self) -> Option<Uuid> {
        None
    }

    /// The build ID from an ELF `NT_GNU_BUILD_ID` note.
    #[inline]
    fn build_id(&self) -> Option<&'data [u8]> {
        None
    }

    /// The filename and CRC from a `.gnu_debuglink` section.
    #[inline]
    fn gnu_debuglink(&self) -> Option<(&'data [u8], u32)> {
        None
    }
}

/// A loadable segment defined in an object file.
///
/// For ELF, this is a program header with type `PT_LOAD`.
/// For Mach-O, this is a load command with type `LC_SEGMENT` or `LC_SEGMENT_64`.
pub trait ObjectSegment<'data> {
    /// Returns the virtual address of the segment.
    fn address(&self) -> u64;

    /// Returns the size of the segment in memory.
    fn size(&self) -> u64;

    /// Returns a reference to the file contents of the segment.
    /// The length of this data may be different from the size of the
    /// segment in memory.
    fn data(&self) -> &'data [u8];

    /// Return the segment data in the given range.
    fn data_range(&self, address: u64, size: u64) -> Option<&'data [u8]>;

    /// Returns the name of the segment.
    fn name(&self) -> Option<&str>;
}

/// A section defined in an object file.
pub trait ObjectSection<'data> {
    /// An iterator over the relocations for a section.
    ///
    /// The first field in the item tuple is the section offset
    /// that the relocation applies to.
    type RelocationIterator: Iterator<Item = (u64, Relocation)>;

    /// Returns the section index.
    fn index(&self) -> SectionIndex;

    /// Returns the address of the section.
    fn address(&self) -> u64;

    /// Returns the size of the section in memory.
    fn size(&self) -> u64;

    /// Returns the raw contents of the section.
    /// The length of this data may be different from the size of the
    /// section in memory.
    ///
    /// This does not do any decompression.
    fn data(&self) -> Cow<'data, [u8]>;

    /// Return the raw contents of the section data in the given range.
    ///
    /// This does not do any decompression.
    fn data_range(&self, address: u64, size: u64) -> Option<&'data [u8]>;

    /// Returns the uncompressed contents of the section.
    /// The length of this data may be different from the size of the
    /// section in memory.
    fn uncompressed_data(&self) -> Cow<'data, [u8]>;

    /// Returns the name of the section.
    fn name(&self) -> Option<&str>;

    /// Returns the name of the segment for this section.
    fn segment_name(&self) -> Option<&str>;

    /// Return the kind of this section.
    fn kind(&self) -> SectionKind;

    /// Get the relocations for this section.
    fn relocations(&self) -> Self::RelocationIterator;
}
<commit_msg>Add Object::symbol_data<commit_after>use crate::alloc::borrow::Cow;
use crate::{Machine, Relocation, SectionIndex, SectionKind, Symbol, SymbolMap, Uuid};

/// An object file.
pub trait Object<'data, 'file> {
    /// A segment in the object file.
    type Segment: ObjectSegment<'data>;

    /// An iterator over the segments in the object file.
    type SegmentIterator: Iterator<Item = Self::Segment>;

    /// A section in the object file.
    type Section: ObjectSection<'data>;

    /// An iterator over the sections in the object file.
    type SectionIterator: Iterator<Item = Self::Section>;

    /// An iterator over the symbols in the object file.
    type SymbolIterator: Iterator<Item = Symbol<'data>>;

    /// Get the machine type of the file.
    fn machine(&self) -> Machine;

    /// Get an iterator over the segments in the file.
    fn segments(&'file self) -> Self::SegmentIterator;

    /// Get the entry point address of the binary
    fn entry(&'file self) -> u64;

    /// Get the section named `section_name`, if such a section exists.
    ///
    /// If `section_name` starts with a '.' then it is treated as a system section name,
    /// and is compared using the conventions specific to the object file format. This
    /// includes:
    /// - if ".text" is requested for a Mach-O object file, then the actual
    /// section name that is searched for is "__text".
    /// - if ".debug_info" is requested for an ELF object file, then
    /// ".zdebug_info" may be returned (and similarly for other debug sections).
    ///
    /// For some object files, multiple segments may contain sections with the same
    /// name. In this case, the first matching section will be used.
    fn section_by_name(&'file self, section_name: &str) -> Option<Self::Section>;

    /// Get the section at the given index.
    ///
    /// The meaning of the index depends on the object file.
    ///
    /// For some object files, this requires iterating through all sections.
    fn section_by_index(&'file self, index: SectionIndex) -> Option<Self::Section>;

    /// Get the contents of the section named `section_name`, if such
    /// a section exists.
    ///
    /// The `section_name` is interpreted according to `Self::section_by_name`.
    ///
    /// This may decompress section data.
    fn section_data_by_name(&'file self, section_name: &str) -> Option<Cow<'data, [u8]>> {
        self.section_by_name(section_name)
            .map(|section| section.uncompressed_data())
    }

    /// Get an iterator over the sections in the file.
    fn sections(&'file self) -> Self::SectionIterator;

    /// Get the debugging symbol at the given index.
    ///
    /// This is similar to `self.symbols().nth(index)`, except that
    /// the index will take into account malformed or unsupported symbols.
    fn symbol_by_index(&self, index: u64) -> Option<Symbol<'data>>;

    /// Get an iterator over the debugging symbols in the file.
    ///
    /// This may skip over symbols that are malformed or unsupported.
    fn symbols(&'file self) -> Self::SymbolIterator;

    /// Get the data for the given symbol.
    fn symbol_data(&'file self, symbol: &Symbol<'data>) -> Option<&'data [u8]> {
        if symbol.is_undefined() {
            return None;
        }
        let address = symbol.address();
        let size = symbol.size();
        if let Some(index) = symbol.section_index() {
            self.section_by_index(index)
                .and_then(|section| section.data_range(address, size))
        } else {
            self.segments()
                .find_map(|segment| segment.data_range(address, size))
        }
    }

    /// Get an iterator over the dynamic linking symbols in the file.
    ///
    /// This may skip over symbols that are malformed or unsupported.
    fn dynamic_symbols(&'file self) -> Self::SymbolIterator;

    /// Construct a map from addresses to symbols.
    fn symbol_map(&self) -> SymbolMap<'data>;

    /// Return true if the file is little endian, false if it is big endian.
    fn is_little_endian(&self) -> bool;

    /// Return true if the file contains debug information sections, false if not.
    fn has_debug_symbols(&self) -> bool;

    /// The UUID from a Mach-O `LC_UUID` load command.
    #[inline]
    fn mach_uuid(&self) -> Option<Uuid> {
        None
    }

    /// The build ID from an ELF `NT_GNU_BUILD_ID` note.
    #[inline]
    fn build_id(&self) -> Option<&'data [u8]> {
        None
    }

    /// The filename and CRC from a `.gnu_debuglink` section.
    #[inline]
    fn gnu_debuglink(&self) -> Option<(&'data [u8], u32)> {
        None
    }
}

/// A loadable segment defined in an object file.
///
/// For ELF, this is a program header with type `PT_LOAD`.
/// For Mach-O, this is a load command with type `LC_SEGMENT` or `LC_SEGMENT_64`.
pub trait ObjectSegment<'data> {
    /// Returns the virtual address of the segment.
    fn address(&self) -> u64;

    /// Returns the size of the segment in memory.
    fn size(&self) -> u64;

    /// Returns a reference to the file contents of the segment.
    /// The length of this data may be different from the size of the
    /// segment in memory.
    fn data(&self) -> &'data [u8];

    /// Return the segment data in the given range.
    fn data_range(&self, address: u64, size: u64) -> Option<&'data [u8]>;

    /// Returns the name of the segment.
    fn name(&self) -> Option<&str>;
}

/// A section defined in an object file.
pub trait ObjectSection<'data> {
    /// An iterator over the relocations for a section.
    ///
    /// The first field in the item tuple is the section offset
    /// that the relocation applies to.
    type RelocationIterator: Iterator<Item = (u64, Relocation)>;

    /// Returns the section index.
    fn index(&self) -> SectionIndex;

    /// Returns the address of the section.
    fn address(&self) -> u64;

    /// Returns the size of the section in memory.
    fn size(&self) -> u64;

    /// Returns the raw contents of the section.
    /// The length of this data may be different from the size of the
    /// section in memory.
    ///
    /// This does not do any decompression.
    fn data(&self) -> Cow<'data, [u8]>;

    /// Return the raw contents of the section data in the given range.
    ///
    /// This does not do any decompression.
    fn data_range(&self, address: u64, size: u64) -> Option<&'data [u8]>;

    /// Returns the uncompressed contents of the section.
    /// The length of this data may be different from the size of the
    /// section in memory.
    fn uncompressed_data(&self) -> Cow<'data, [u8]>;

    /// Returns the name of the section.
    fn name(&self) -> Option<&str>;

    /// Returns the name of the segment for this section.
    fn segment_name(&self) -> Option<&str>;

    /// Return the kind of this section.
    fn kind(&self) -> SectionKind;

    /// Get the relocations for this section.
    fn relocations(&self) -> Self::RelocationIterator;
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

use sys::{Component, Disk, DiskType, NetworkData, Process, Processor};
use Pid;
use ProcessStatus;

use std::collections::HashMap;
use std::ffi::OsStr;
use std::path::Path;

/// Contains all the methods of the `Disk` struct.
pub trait DiskExt {
    /// Returns the disk type.
    fn get_type(&self) -> DiskType;

    /// Returns the disk name.
    fn get_name(&self) -> &OsStr;

    /// Returns the file system used on this disk (so for example: `EXT4`, `NTFS`, etc...).
    fn get_file_system(&self) -> &[u8];

    /// Returns the mount point of the disk (`/` for example).
    fn get_mount_point(&self) -> &Path;

    /// Returns the total disk size, in bytes.
    fn get_total_space(&self) -> u64;

    /// Returns the available disk size, in bytes.
    fn get_available_space(&self) -> u64;

    /// Update the disk' information.
    fn update(&mut self) -> bool;
}

/// Contains all the methods of the `Process` struct.
pub trait ProcessExt {
    /// Create a new process only containing the given information.
    ///
    /// On windows, the `start_time` argument is ignored.
    fn new(pid: Pid, parent: Option<Pid>, start_time: u64) -> Self;

    /// Sends the given `signal` to the process.
    fn kill(&self, signal: ::Signal) -> bool;

    /// Returns the name of the processus.
    fn name(&self) -> &str;

    /// Returns the command line.
    ///
    /// On Windows, this is always a one element vector.
    fn cmd(&self) -> &[String];

    /// Returns the path to the processus.
    fn exe(&self) -> &str;

    /// Returns the pid of the processus.
    fn pid(&self) -> Pid;

    /// Returns the environment of the process.
    ///
    /// Always empty on Windows except for current processus.
    fn environ(&self) -> &[String];

    /// Returns the current working directory.
    ///
    /// Always empty on Windows.
    fn cwd(&self) -> &str;

    /// Returns the path of the root directory.
    ///
    /// Always empty on Windows.
    fn root(&self) -> &str;

    /// Returns the memory usage (in kB).
    fn memory(&self) -> u64;

    /// Returns the parent pid.
    fn parent(&self) -> Option<Pid>;

    /// Returns the status of the processus.
    fn status(&self) -> ProcessStatus;

    /// Returns the time of process launch (in seconds).
    fn start_time(&self) -> u64;

    /// Returns the total CPU usage.
    fn cpu_usage(&self) -> f32;
}

/// Contains all the methods of the `Processor` struct.
pub trait ProcessorExt {
    /// Returns this processor's usage.
    fn get_cpu_usage(&self) -> f32;

    /// Returns this processor's name.
    fn get_name(&self) -> &str;
}

/// Contains all the methods of the `System` struct.
pub trait SystemExt {
    /// Creates a new `System` instance. It only contains the disks' list at this stage. Use the
    /// [`refresh_all`] method to update its internal information (or any of the `refresh_` method).
    ///
    /// [`refresh_all`]: #method.refresh_all
    fn new() -> Self;

    /// Refresh system information (such as memory, swap, CPU usage and components' temperature).
    fn refresh_system(&mut self);

    /// Get all processes and update their information.
    fn refresh_processes(&mut self);

    /// Refresh *only* the process corresponding to `pid`. Returns `false` if the process doesn't
    /// exist.
    fn refresh_process(&mut self, pid: Pid) -> bool;

    /// Refreshes the listed disks' information.
    fn refresh_disks(&mut self);

    /// The disk list will be emptied then completely recomputed.
    fn refresh_disk_list(&mut self);

    /// Refresh data network.
    fn refresh_network(&mut self);

    /// Refreshes all system, processes and disks information.
    fn refresh_all(&mut self) {
        self.refresh_system();
        self.refresh_processes();
        self.refresh_disks();
        self.refresh_network();
    }

    /// Returns the process list.
    fn get_process_list(&self) -> &HashMap<Pid, Process>;

    /// Returns the process corresponding to the given pid or `None` if no such process exists.
    fn get_process(&self, pid: Pid) -> Option<&Process>;

    /// Returns a list of process containing the given `name`.
    fn get_process_by_name(&self, name: &str) -> Vec<&Process> {
        let mut ret = vec!();
        for val in self.get_process_list().values() {
            if val.name().contains(name) {
                ret.push(val);
            }
        }
        ret
    }

    /// The first processor in the array is the "main" one (aka the addition of all the others).
    fn get_processor_list(&self) -> &[Processor];

    /// Returns total RAM size.
    fn get_total_memory(&self) -> u64;

    /// Returns free RAM size.
    fn get_free_memory(&self) -> u64;

    /// Returns used RAM size.
    fn get_used_memory(&self) -> u64;

    /// Returns SWAP size.
    fn get_total_swap(&self) -> u64;

    /// Returns free SWAP size.
    fn get_free_swap(&self) -> u64;

    /// Returns used SWAP size.
    fn get_used_swap(&self) -> u64;

    /// Returns components list.
    fn get_components_list(&self) -> &[Component];

    /// Returns disks' list.
    fn get_disks(&self) -> &[Disk];

    /// Returns network data.
    fn get_network(&self) -> &NetworkData;

    /// Returns system uptime.
    fn get_uptime(&self) -> u64;
}

/// Getting volume of incoming and outcoming data.
pub trait NetworkExt {
    /// Returns the number of incoming bytes.
    fn get_income(&self) -> u64;

    /// Returns the number of outcoming bytes.
    fn get_outcome(&self) -> u64;
}

/// Getting a component temperature information.
pub trait ComponentExt {
    /// Returns the component's temperature (in celsius degree).
    fn get_temperature(&self) -> f32;
    /// Returns the maximum temperature of this component.
    fn get_max(&self) -> f32;
    /// Returns the highest temperature before the computer halts.
    fn get_critical(&self) -> Option<f32>;
    /// Returns component's label.
    fn get_label(&self) -> &str;
}
<commit_msg>Improve doc a bit<commit_after>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

use sys::{Component, Disk, DiskType, NetworkData, Process, Processor};
use Pid;
use ProcessStatus;

use std::collections::HashMap;
use std::ffi::OsStr;
use std::path::Path;

/// Contains all the methods of the `Disk` struct.
pub trait DiskExt {
    /// Returns the disk type.
    fn get_type(&self) -> DiskType;

    /// Returns the disk name.
    fn get_name(&self) -> &OsStr;

    /// Returns the file system used on this disk (so for example: `EXT4`, `NTFS`, etc...).
    fn get_file_system(&self) -> &[u8];

    /// Returns the mount point of the disk (`/` for example).
    fn get_mount_point(&self) -> &Path;

    /// Returns the total disk size, in bytes.
    fn get_total_space(&self) -> u64;

    /// Returns the available disk size, in bytes.
    fn get_available_space(&self) -> u64;

    /// Update the disk' information.
    fn update(&mut self) -> bool;
}

/// Contains all the methods of the `Process` struct.
pub trait ProcessExt {
    /// Create a new process only containing the given information.
    ///
    /// On windows, the `start_time` argument is ignored.
    fn new(pid: Pid, parent: Option<Pid>, start_time: u64) -> Self;

    /// Sends the given `signal` to the process.
    fn kill(&self, signal: ::Signal) -> bool;

    /// Returns the name of the processus.
    fn name(&self) -> &str;

    /// Returns the command line.
    // ///
    // /// On Windows, this is always a one element vector.
    fn cmd(&self) -> &[String];

    /// Returns the path to the processus.
    fn exe(&self) -> &str;

    /// Returns the pid of the processus.
    fn pid(&self) -> Pid;

    /// Returns the environment of the process.
    ///
    /// Always empty on Windows except for current processus.
    fn environ(&self) -> &[String];

    /// Returns the current working directory.
    ///
    /// Always empty on Windows.
    fn cwd(&self) -> &str;

    /// Returns the path of the root directory.
    ///
    /// Always empty on Windows.
    fn root(&self) -> &str;

    /// Returns the memory usage (in kB).
    fn memory(&self) -> u64;

    /// Returns the parent pid.
    fn parent(&self) -> Option<Pid>;

    /// Returns the status of the processus.
    fn status(&self) -> ProcessStatus;

    /// Returns the time of process launch (in seconds).
    fn start_time(&self) -> u64;

    /// Returns the total CPU usage.
    fn cpu_usage(&self) -> f32;
}

/// Contains all the methods of the `Processor` struct.
pub trait ProcessorExt {
    /// Returns this processor's usage.
    ///
    /// Note: You'll need to refresh it at least twice at first if you want to have a
    /// non-zero value.
    fn get_cpu_usage(&self) -> f32;

    /// Returns this processor's name.
    fn get_name(&self) -> &str;
}

/// Contains all the methods of the `System` struct.
pub trait SystemExt {
    /// Creates a new `System` instance. It only contains the disks' list at this stage. Use the
    /// [`refresh_all`] method to update its internal information (or any of the `refresh_` method).
    ///
    /// [`refresh_all`]: #method.refresh_all
    fn new() -> Self;

    /// Refresh system information (such as memory, swap, CPU usage and components' temperature).
    fn refresh_system(&mut self);

    /// Get all processes and update their information.
    fn refresh_processes(&mut self);

    /// Refresh *only* the process corresponding to `pid`. Returns `false` if the process doesn't
    /// exist.
    fn refresh_process(&mut self, pid: Pid) -> bool;

    /// Refreshes the listed disks' information.
    fn refresh_disks(&mut self);

    /// The disk list will be emptied then completely recomputed.
    fn refresh_disk_list(&mut self);

    /// Refresh data network.
    fn refresh_network(&mut self);

    /// Refreshes all system, processes and disks information.
    fn refresh_all(&mut self) {
        self.refresh_system();
        self.refresh_processes();
        self.refresh_disks();
        self.refresh_network();
    }

    /// Returns the process list.
    fn get_process_list(&self) -> &HashMap<Pid, Process>;

    /// Returns the process corresponding to the given pid or `None` if no such process exists.
    fn get_process(&self, pid: Pid) -> Option<&Process>;

    /// Returns a list of process containing the given `name`.
    fn get_process_by_name(&self, name: &str) -> Vec<&Process> {
        let mut ret = vec!();
        for val in self.get_process_list().values() {
            if val.name().contains(name) {
                ret.push(val);
            }
        }
        ret
    }

    /// The first processor in the array is the "main" one (aka the addition of all the others).
    fn get_processor_list(&self) -> &[Processor];

    /// Returns total RAM size.
    fn get_total_memory(&self) -> u64;

    /// Returns free RAM size.
    fn get_free_memory(&self) -> u64;

    /// Returns used RAM size.
    fn get_used_memory(&self) -> u64;

    /// Returns SWAP size.
    fn get_total_swap(&self) -> u64;

    /// Returns free SWAP size.
    fn get_free_swap(&self) -> u64;

    /// Returns used SWAP size.
    fn get_used_swap(&self) -> u64;

    /// Returns components list.
    fn get_components_list(&self) -> &[Component];

    /// Returns disks' list.
    fn get_disks(&self) -> &[Disk];

    /// Returns network data.
    fn get_network(&self) -> &NetworkData;

    /// Returns system uptime.
    fn get_uptime(&self) -> u64;
}

/// Getting volume of incoming and outcoming data.
pub trait NetworkExt {
    /// Returns the number of incoming bytes.
    fn get_income(&self) -> u64;

    /// Returns the number of outcoming bytes.
    fn get_outcome(&self) -> u64;
}

/// Getting a component temperature information.
pub trait ComponentExt {
    /// Returns the component's temperature (in celsius degree).
    fn get_temperature(&self) -> f32;
    /// Returns the maximum temperature of this component.
    fn get_max(&self) -> f32;
    /// Returns the highest temperature before the computer halts.
    fn get_critical(&self) -> Option<f32>;
    /// Returns component's label.
    fn get_label(&self) -> &str;
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Mul, Div, Neg, Rem};
use std::cmp::{PartialEq};
use super::super::num::{Num, Zero, One, Signed};
use super::parse_decimal_error::ParseDecimalError;

const ZERO: u32 = 0b0_00000_000000_00000000000000000000;
const SIGN_MASK: u32 = 0b1_00000_000000_00000000000000000000;
const COMBINATION_MASK: u32 = 0b0_11111_000000_00000000000000000000;
const EXPONENT_MASK: u32 = 0b0_00000_111111_00000000000000000000;
const COEFFICIENT_CONTINUATION_MASK: u32 = 0b0_00000_000000_11111111111111111111;

#[derive(Debug, Clone, Copy)]
pub struct Decimal32 {
    data: u32,
}

impl Decimal32 {
    /// Creates and initializes a Decimal32 representation of zero.
    pub fn new() -> Decimal32 {
        Decimal32::zero()
    }
}

impl Add<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn add(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Sub<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn sub(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Mul<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn mul(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Div<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn div(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Neg for Decimal32 {
    type Output = Decimal32;

    fn neg(self) -> Decimal32 {
        Decimal32 {
            data: self.data ^ 1 << 31
        }
    }
}

impl Rem<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn rem(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl PartialEq for Decimal32 {
    fn eq(&self, other: &Decimal32) -> bool {
        true // TODO
    }
}

impl Num for Decimal32 {
    type FromStrRadixErr = ParseDecimalError;

    fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
        Ok(Decimal32::zero()) // TODO
    }
}

impl Zero for Decimal32 {
    fn zero() -> Decimal32 {
        Decimal32 { data: ZERO }
    }

    fn is_zero(&self) -> bool {
        true
    }
}

impl One for Decimal32 {
    fn one() -> Decimal32 {
        Decimal32 { data: ZERO } // TODO
    }
}

impl Signed for Decimal32 {
    fn abs(&self) -> Decimal32 {
        Decimal32 { data: self.data & (!SIGN_MASK) }
    }

    fn abs_sub(&self, other: &Decimal32) -> Decimal32 {
        // TODO
        // The positive difference of two numbers.
        // Returns zero if the number is less than or equal to other, otherwise the difference between self and other is returned.
        *self
    }

    fn signum(&self) -> Decimal32 {
        // TODO
        // Returns the sign of the number.
        // For f32 and f64:
        // 1.0 if the number is positive, +0.0 or INFINITY
        // -1.0 if the number is negative, -0.0 or NEG_INFINITY
        // NaN if the number is NaN
        *self
    }

    /// Note: Zero can be positive or negative.
    fn is_positive(&self) -> bool {
        self.data & SIGN_MASK == 0
    }

    /// Note: Zero can be positive or negative.
    fn is_negative(&self) -> bool {
        self.data & ZERO != 0
    }
}
    <commit_msg>doesn't build... stubbed out ways of retrieving the parts of decimal32<commit_after>use std::ops::{Add, Sub, Mul, Div, Neg, Rem};
use std::cmp::{PartialEq};
use super::super::num::{Num, Zero, One, Signed};
use super::parse_decimal_error::ParseDecimalError;

#[derive(Debug, Clone, Copy)]
pub struct Decimal32 {
    data: u32,
}

impl Decimal32 {
    /// Creates and initializes a Decimal32 representation of zero.
    pub fn new() -> Decimal32 {
        Decimal32::zero()
    }

    fn get_sign_field(&self) -> u32 {
        let mask = 0b1_00000_000000_00000000000000000000;
        (self.data & mask) >> 31
    }

    fn get_combination_field(&self) -> u32 {
        let mask = 0b0_11111_000000_00000000000000000000;
        (self.data & mask) >> 26
    }

    fn get_first_two_bits_combination_field(&self) -> u32 {
        let combination_field = self.get_combination_field();
        combination_field >> 3
    }

    fn get_second_two_bits_combination_field(&self) -> u32 {
        let mask = 0b00110;
        let combination_field = self.get_combination_field();
        (combination_field & mask) >> 1
    }

    fn get_normal_exponent(&self) -> u32 {
        let mask: u32 = 0b0_00111_111000_00000000000000000000;
        (self.data & mask) >> 23
    }

    fn get_shifted_exponent(&self) -> u32 {
        let mask: u32 = 0b0_00001_111110_00000000000000000000;
        (self.data & mask) >> 21
    }

    fn get_normal_significand(&self) -> u32 {
        let mask = 0b0_00000_000111_11111111111111111111;
        self.data & mask
    }

    fn get_shifted_significand(&self) -> u32 {
        let implicit_100 = 0b100_0_00000_00000_00000_00000;
        let mask = 0b0_00000_000001_11111111111111111111;
        implicit_100 + (self.data & mask)
    }
}

impl Add<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn add(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Sub<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn sub(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Mul<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn mul(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Div<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn div(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Neg for Decimal32 {
    type Output = Decimal32;

    fn neg(self) -> Decimal32 {
        Decimal32 {
            data: self.data ^ 1 << 31
        }
    }
}

impl Rem<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn rem(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl PartialEq for Decimal32 {
    fn eq(&self, other: &Decimal32) -> bool {
        true // TODO
    }
}

impl Num for Decimal32 {
    type FromStrRadixErr = ParseDecimalError;

    fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
        Ok(Decimal32::zero()) // TODO
    }
}

impl Zero for Decimal32 {
    fn zero() -> Decimal32 {
        Decimal32 { data: ZERO }
    }

    fn is_zero(&self) -> bool {
        true
    }
}

impl One for Decimal32 {
    fn one() -> Decimal32 {
        Decimal32 { data: ZERO } // TODO
    }
}

impl Signed for Decimal32 {
    fn abs(&self) -> Decimal32 {
        Decimal32 { data: self.data & (!SIGN_MASK) }
    }

    fn abs_sub(&self, other: &Decimal32) -> Decimal32 {
        // TODO
        // The positive difference of two numbers.
        // Returns zero if the number is less than or equal to other, otherwise the difference between self and other is returned.
        *self
    }

    fn signum(&self) -> Decimal32 {
        // TODO
        // Returns the sign of the number.
        // For f32 and f64:
        // 1.0 if the number is positive, +0.0 or INFINITY
        // -1.0 if the number is negative, -0.0 or NEG_INFINITY
        // NaN if the number is NaN
        *self
    }

    /// Note: Zero can be positive or negative.
    fn is_positive(&self) -> bool {
        self.get_sign_field() == 0
    }

    /// Note: Zero can be positive or negative.
    fn is_negative(&self) -> bool {
        self.get_sign_field() != 0
    }
}
    <|endoftext|>


<commit_before>use {Int, LargeInt};

macro_rules! mul {
    ($intrinsic:ident: $ty:ty) => {
        /// Returns `a * b`
        #[cfg_attr(not(test), no_mangle)]
        pub extern fn $intrinsic(a: $ty, b: $ty) -> $ty {
            let half_bits = <$ty>::bits() / 4;
            let lower_mask = !0 >> half_bits;
            let mut low = (a.low() & lower_mask) * (b.low() & lower_mask);
            let mut t = low >> half_bits;
            low &= lower_mask;
            t += (a.low() >> half_bits) * (b.low() & lower_mask);
            low += (t & lower_mask) << half_bits;
            let mut high = t >> half_bits;
            t = low >> half_bits;
            low &= lower_mask;
            t += (b.low() >> half_bits) * (a.low() & lower_mask);
            low += (t & lower_mask) << half_bits;
            high += t >> half_bits;
            high += (a.low() >> half_bits) * (b.low() >> half_bits);
            high += a.high().wrapping_mul(b.low()) + a.low().wrapping_mul(b.high());
            <$ty>::from_parts(low, high)
        }
    }
}

macro_rules! mulo {
    ($intrinsic:ident: $ty:ty) => {
        /// Returns `a * b` and sets `*overflow = 1` if `a * b` overflows
        #[cfg_attr(not(test), no_mangle)]
        pub extern fn $intrinsic(a: $ty, b: $ty, overflow: &mut i32) -> $ty {
            *overflow = 0;
            let result = a.wrapping_mul(b);
            if a == <$ty>::min_value() {
                if b != 0 && b != 1 {
                    *overflow = 1;
                }
                return result;
            }
            if b == <$ty>::min_value() {
                if a != 0 && a != 1 {
                    *overflow = 1;
                }
                return result;
            }

            let sa = a >> (<$ty>::bits() - 1);
            let abs_a = (a ^ sa) - sa;
            let sb = b >> (<$ty>::bits() - 1);
            let abs_b = (b ^ sb) - sb;
            if abs_a < 2 || abs_b < 2 {
                return result;
            }
            if sa == sb {
                if abs_a > <$ty>::max_value() / abs_b {
                    *overflow = 1;
                }
            } else {
                if abs_a > <$ty>::min_value() / -abs_b {
                    *overflow = 1;
                }
            }
            result
        }
    }
}

mul!(__muldi4: u64);
mulo!(__mulosi4: i32);
mulo!(__mulodi4: i64);

#[cfg(test)]
mod tests {
    use qc::{I32, I64, U64};

    quickcheck! {
        fn muldi(a: U64, b: U64) -> bool {
            let (a, b) = (a.0, b.0);
            let r = super::__muldi4(a, b);
            r == a.wrapping_mul(b)
        }

        fn mulosi(a: I32, b: I32) -> bool {
            let (a, b) = (a.0, b.0);
            let mut overflow = 2;
            let r = super::__mulosi4(a, b, &mut overflow);
            if overflow != 0 && overflow != 1 {
                return false;
            }
            (r, overflow != 0) == a.overflowing_mul(b)
        }

        fn mulodi(a: I64, b: I64) -> bool {
            let (a, b) = (a.0, b.0);
            let mut overflow = 2;
            let r = super::__mulodi4(a, b, &mut overflow);
            if overflow != 0 && overflow != 1 {
                return false;
            }
            (r, overflow != 0) == a.overflowing_mul(b)
        }
    }
}
<commit_msg>use wrapping_add in muldi4<commit_after>use {Int, LargeInt};

macro_rules! mul {
    ($intrinsic:ident: $ty:ty) => {
        /// Returns `a * b`
        #[cfg_attr(not(test), no_mangle)]
        pub extern fn $intrinsic(a: $ty, b: $ty) -> $ty {
            let half_bits = <$ty>::bits() / 4;
            let lower_mask = !0 >> half_bits;
            let mut low = (a.low() & lower_mask) * (b.low() & lower_mask);
            let mut t = low >> half_bits;
            low &= lower_mask;
            t += (a.low() >> half_bits) * (b.low() & lower_mask);
            low += (t & lower_mask) << half_bits;
            let mut high = t >> half_bits;
            t = low >> half_bits;
            low &= lower_mask;
            t += (b.low() >> half_bits) * (a.low() & lower_mask);
            low += (t & lower_mask) << half_bits;
            high += t >> half_bits;
            high += (a.low() >> half_bits) * (b.low() >> half_bits);
            high = high.wrapping_add(a.high().wrapping_mul(b.low()).wrapping_add(a.low().wrapping_mul(b.high())));
            <$ty>::from_parts(low, high)
        }
    }
}

macro_rules! mulo {
    ($intrinsic:ident: $ty:ty) => {
        /// Returns `a * b` and sets `*overflow = 1` if `a * b` overflows
        #[cfg_attr(not(test), no_mangle)]
        pub extern fn $intrinsic(a: $ty, b: $ty, overflow: &mut i32) -> $ty {
            *overflow = 0;
            let result = a.wrapping_mul(b);
            if a == <$ty>::min_value() {
                if b != 0 && b != 1 {
                    *overflow = 1;
                }
                return result;
            }
            if b == <$ty>::min_value() {
                if a != 0 && a != 1 {
                    *overflow = 1;
                }
                return result;
            }

            let sa = a >> (<$ty>::bits() - 1);
            let abs_a = (a ^ sa) - sa;
            let sb = b >> (<$ty>::bits() - 1);
            let abs_b = (b ^ sb) - sb;
            if abs_a < 2 || abs_b < 2 {
                return result;
            }
            if sa == sb {
                if abs_a > <$ty>::max_value() / abs_b {
                    *overflow = 1;
                }
            } else {
                if abs_a > <$ty>::min_value() / -abs_b {
                    *overflow = 1;
                }
            }
            result
        }
    }
}

mul!(__muldi4: u64);
mulo!(__mulosi4: i32);
mulo!(__mulodi4: i64);

#[cfg(test)]
mod tests {
    use qc::{I32, I64, U64};

    quickcheck! {
        fn muldi(a: U64, b: U64) -> bool {
            let (a, b) = (a.0, b.0);
            let r = super::__muldi4(a, b);
            r == a.wrapping_mul(b)
        }

        fn mulosi(a: I32, b: I32) -> bool {
            let (a, b) = (a.0, b.0);
            let mut overflow = 2;
            let r = super::__mulosi4(a, b, &mut overflow);
            if overflow != 0 && overflow != 1 {
                return false;
            }
            (r, overflow != 0) == a.overflowing_mul(b)
        }

        fn mulodi(a: I64, b: I64) -> bool {
            let (a, b) = (a.0, b.0);
            let mut overflow = 2;
            let r = super::__mulodi4(a, b, &mut overflow);
            if overflow != 0 && overflow != 1 {
                return false;
            }
            (r, overflow != 0) == a.overflowing_mul(b)
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::io::{Error, ErrorKind};
use std::cell::UnsafeCell;
use std::sync::{Arc, Mutex};
use std::os::unix::io::{RawFd, AsRawFd};

use libc;
use simple_slab::Slab;

use super::{Stream, Handler};

/// Memory region for all concurrent connections.
pub type ConnectionSlab = Arc<MutSlab>;
/// Protected memory region for newly accepted connections.
pub type NewConnectionSlab = Arc<Mutex<Slab<Connection>>>;
/// Queue of Connections needing various I/O operations.
pub type IoQueue = Arc<Mutex<Vec<IoPair>>>;

#[derive(Clone, PartialEq, Eq)]
pub enum IoEvent {
    /// Epoll reported data is available on the socket for reading
    ReadAvailable,
    /// Epoll reported the socket is writable
    WriteAvailable,
    /// Epoll reported the socket is both writable and has data available for reading
    ReadWriteAvailable
}

#[derive(Clone)]
pub struct IoPair {
    /// The type of I/O needed on this Connection
    pub event: IoEvent,
    /// The connection `event` is paired with
    pub arc_connection: Arc<Connection>
}

pub struct Connection {
    /// Underlying file descriptor.
    pub fd: RawFd,
    /// A Some(Error) options means this connection is in
    /// an error'd state and should be closed.
    pub err_mutex: Mutex<Option<Error>>,
    /// Mutex to ensure thread safe, ordered writes to our streams.
    /// They may have internal buffers
    pub tx_mutex: Mutex<()>,
    /// Socket (Stream implemented trait-object).
    pub stream: Arc<UnsafeCell<Stream>>
}
unsafe impl Send for Connection {}
unsafe impl Sync for Connection {}

pub struct MutSlab {
    pub inner: UnsafeCell<Slab<Arc<Connection>>>
}
unsafe impl Send for MutSlab {}
unsafe impl Sync for MutSlab {}

pub struct EventHandler(pub *mut Handler);
unsafe impl Send for EventHandler {}
unsafe impl Sync for EventHandler {}
impl Clone for EventHandler {
    fn clone(&self) -> EventHandler {
        let EventHandler(ptr) = *self;
        unsafe {
            let same_location = &mut *ptr;
            EventHandler(same_location)
        }
    }
}

pub struct HydrogenSocket {
    /// Epoll fd
    epfd: RawFd,
    /// The connection this socket represents
    arc_connection: Arc<Connection>,
    /// Function responsible for re-arming fd in epoll instance
    rearm_fn: unsafe fn(RawFd, &Arc<Connection>, i32)
}

impl HydrogenSocket {
    pub fn new(arc_connection: Arc<Connection>,
               epfd: RawFd,
               rearm_fn: unsafe fn(RawFd, &Arc<Connection>, i32))
               -> HydrogenSocket
    {
        HydrogenSocket {
            epfd: epfd,
            arc_connection: arc_connection,
            rearm_fn: rearm_fn
        }
    }

    pub fn send(&self, buf: &[u8]) {
        let err;
        { // Mutex lock
            let _ = match self.arc_connection.tx_mutex.lock() {
                Ok(g) => g,
                Err(p) => p.into_inner()
            };

            let stream_ptr = self.arc_connection.stream.get();
            let write_result = unsafe {
                (*stream_ptr).send(buf)
            };
            if write_result.is_ok() {
                return;
            }

            err = write_result.unwrap_err();
        } // Mutex unlock

        match err.kind() {
            ErrorKind::WouldBlock => {
                let execute = self.rearm_fn;
                unsafe {
                    execute(self.epfd, &(self.arc_connection), libc::EPOLLOUT);
                }
            }
            _ => {
                { // Mutex lock
                    let mut err_state = match self.arc_connection.err_mutex.lock() {
                        Ok(g) => g,
                        Err(p) => p.into_inner()
                    };
                    *err_state = Some(err);
                } // Mutex unlock
            }
        }
    }
}

impl AsRawFd for HydrogenSocket {
    fn as_raw_fd(&self) -> RawFd {
        self.arc_connection.fd
    }
}
<commit_msg>Updated things.<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::io::{Error, ErrorKind};
use std::cell::UnsafeCell;
use std::sync::{Arc, Mutex};
use std::os::unix::io::{RawFd, AsRawFd};

use libc;
use simple_slab::Slab;

use super::{Stream, Handler};

/// Memory region for all concurrent connections.
pub type ConnectionSlab = Arc<MutSlab>;
/// Protected memory region for newly accepted connections.
pub type NewConnectionSlab = Arc<Mutex<Slab<Connection>>>;
/// Queue of Connections needing various I/O operations.
pub type IoQueue = Arc<Mutex<Vec<IoPair>>>;

#[derive(Clone, PartialEq, Eq)]
pub enum IoEvent {
    /// Epoll reported data is available on the socket for reading
    ReadAvailable,
    /// Epoll reported the socket is writable
    WriteAvailable,
    /// Epoll reported the socket is both writable and has data available for reading
    ReadWriteAvailable
}

#[derive(Clone)]
pub struct IoPair {
    /// The type of I/O needed on this Connection
    pub event: IoEvent,
    /// The connection `event` is paired with
    pub arc_connection: Arc<Connection>
}

pub struct Connection {
    /// Underlying file descriptor.
    pub fd: RawFd,
    /// A Some(Error) options means this connection is in
    /// an error'd state and should be closed.
    pub err_mutex: Mutex<Option<Error>>,
    /// Mutex to ensure thread safe, ordered writes to our streams.
    /// They may have internal buffers
    pub tx_mutex: Mutex<()>,
    /// Socket (Stream implemented trait-object).
    pub stream: Arc<UnsafeCell<Stream>>
}
unsafe impl Send for Connection {}
unsafe impl Sync for Connection {}

pub struct MutSlab {
    pub inner: UnsafeCell<Slab<Arc<Connection>>>
}
unsafe impl Send for MutSlab {}
unsafe impl Sync for MutSlab {}

pub struct EventHandler(pub *mut Handler);
unsafe impl Send for EventHandler {}
unsafe impl Sync for EventHandler {}
impl Clone for EventHandler {
    fn clone(&self) -> EventHandler {
        let EventHandler(ptr) = *self;
        unsafe {
            let same_location = &mut *ptr;
            EventHandler(same_location)
        }
    }
}

pub struct HydrogenSocket {
    /// Epoll fd
    epfd: RawFd,
    /// The connection this socket represents
    arc_connection: Arc<Connection>,
    /// Function responsible for re-arming fd in epoll instance
    rearm_fn: unsafe fn(RawFd, &Arc<Connection>, i32)
}

impl Clone for HydrogenSocket {
    fn clone(&self) -> HydrogenSocket {
        let fn_ptr = self.rearm_fn;
        HydrogenSocket {
            epfd: self.epfd,
            arc_connection: self.arc_connection.clone(),
            rearm_fn: fn_ptr
        }
    }
}

impl HydrogenSocket {
    pub fn new(arc_connection: Arc<Connection>,
               epfd: RawFd,
               rearm_fn: unsafe fn(RawFd, &Arc<Connection>, i32))
               -> HydrogenSocket
    {
        HydrogenSocket {
            epfd: epfd,
            arc_connection: arc_connection,
            rearm_fn: rearm_fn
        }
    }

    pub fn send(&self, buf: &[u8]) {
        let err;
        { // Mutex lock
            let _ = match self.arc_connection.tx_mutex.lock() {
                Ok(g) => g,
                Err(p) => p.into_inner()
            };

            let stream_ptr = self.arc_connection.stream.get();
            let write_result = unsafe {
                (*stream_ptr).send(buf)
            };
            if write_result.is_ok() {
                return;
            }

            err = write_result.unwrap_err();
        } // Mutex unlock

        match err.kind() {
            ErrorKind::WouldBlock => {
                let execute = self.rearm_fn;
                unsafe {
                    execute(self.epfd, &(self.arc_connection), libc::EPOLLOUT);
                }
            }
            _ => {
                { // Mutex lock
                    let mut err_state = match self.arc_connection.err_mutex.lock() {
                        Ok(g) => g,
                        Err(p) => p.into_inner()
                    };
                    *err_state = Some(err);
                } // Mutex unlock
            }
        }
    }
}

impl AsRawFd for HydrogenSocket {
    fn as_raw_fd(&self) -> RawFd {
        self.arc_connection.fd
    }
}
<|endoftext|>


<commit_before>extern crate pad;
extern crate regex;

use std::cmp::Ordering;
use self::pad::PadStr;
use std::fmt;
use std::path::PathBuf;
use colored::*;

#[derive(Ord, Eq, PartialOrd, PartialEq, Debug, Copy, Clone)]
pub struct FileSize {
    size: u64,
}

impl FileSize {

    pub fn new(i: u64) -> FileSize {
        FileSize { size: i }
    }

    pub fn add(&mut self, other: FileSize) -> () {
        self.size += other.size;
    }

}

pub struct NamePair {
    bytes: FileSize,
    depth: u8,
    name: String,
    is_dir: bool,
}

fn sort_by_size(fst: &NamePair, snd: &NamePair) -> Ordering {
    fst.bytes.cmp(&snd.bytes)
}

impl NamePair {
    pub fn new(path: String, bytes_in: FileSize, d: u8, b: bool) -> NamePair {
        NamePair { name: path, bytes: bytes_in, depth: d, is_dir: b }
    }
}

pub struct FileTree {
    pub file_size: FileSize,
    files: Vec<NamePair>,
}

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

impl FileTree {

    // for whatever reason, it's faster to display smallest files first
    pub fn sort(mut self, maybe_num: Option<usize>, d: u8, min_bytes:Option<u64>, dirs_only: bool) -> FileTree {

        let min_size = if let Some(x) = min_bytes.map(FileSize::new) { x }
            else { FileSize::new(100000) };

        // filter by depth & truncate
        if let Some(n) = maybe_num {
            self.files.sort_by(|a, b| sort_by_size(b, a));
            let new = self.files.into_iter()
                .filter(|a| a.depth <= d && (if dirs_only { a.is_dir } else { true }) && a.bytes > min_size )
                .take(n).collect::<Vec<NamePair>>();
            FileTree { file_size: self.file_size, files: new }
        }

        // sort by size and filter by depth
        else {
            self.files.sort_by(|a, b| sort_by_size(a, b));
            let new = self.files.into_iter()
                .filter(|a| a.depth <= d && (if dirs_only { a.is_dir } else { true }) && a.bytes > min_size )
                .collect::<Vec<NamePair>>();
            FileTree { file_size: self.file_size, files: new }
        }
    }

    pub fn filtered(mut self, d: u8, min_bytes: Option<u64>, dirs_only: bool) -> FileTree {

        let min_size = if let Some(x) = min_bytes.map(FileSize::new) { x }
            else { FileSize::new(100000) };

        self.files = self.files.into_iter()
            .filter(|a| a.depth <= d && (if dirs_only { a.is_dir } else { true }) && a.bytes > min_size )
            .filter(|a| a.depth <= d)
            .collect::<Vec<NamePair>>();

        FileTree { file_size: self.file_size, files: self.files }
    }

    pub fn new() -> FileTree {
        FileTree { file_size: FileSize::new(0), files: Vec::new() }
    }

    pub fn push(&mut self,
                path: String,
                size: FileSize,
                subtree: Option<&mut FileTree>,
                depth: u8,
                is_dir: bool) -> () {

        // add to total
        self.file_size.add(size);

        // append subtree if appropriate
        if let Some(s) = subtree {
                self.files.append(&mut s.files);
        }

        // return new file tree
        self.files.push(NamePair::new(path, size, depth, is_dir));

    }

    // TODO: make this more intelligent about what it displays
    // 2: if we display the child directory, don't show the parent? unless we display more than one
    //    child, in which case it's probably best to display all 3. AND if a directory is on the
    //    gitignore, it's best to not display its children.
    // 3: if we *are* displaying files, only display the first few in a directory
    pub fn display_tree(&mut self, init_dir: PathBuf) -> () {

        // display stuff
        let vec = &self.files;
        for name_pair in vec {
            if name_pair.bytes != FileSize::new(0) {
                let to_formatted = format!("{}", name_pair.bytes);
                println!("{}\t {}", &to_formatted.green(), name_pair.name);
            }
        }

        // display total if it's nonzero
        if self.file_size != FileSize::new(0) {
            let to_formatted = format!("{}", self.file_size);
            let path = init_dir.display();
            println!("{}\t {}", &to_formatted.green(), path);
        }

    }

}

// TODO print by significant figures?
impl fmt::Display for FileSize {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        if self.size < 1024 {
            let pre_size = format!("{}", self.size);
            write!(f, "{} b", &pre_size.pad_to_width(4))
        }

        else if self.size < 1048576 { // 2^20 = 1024 * 1024
            let pre_size = format!("{}", self.size/1024);
            write!(f, "{} kB", &pre_size.pad_to_width(4))
        }

        else if self.size < 1073741824 { // 2^30
            let pre_size = format!("{}", self.size/1048576);
            write!(f, "{} MB", &pre_size.pad_to_width(4))
        }

        else if self.size < 1099511627776 { // 2^40
            let pre_size = format!("{}", self.size/1073741824);
            write!(f, "{} GB", &pre_size.pad_to_width(4))
        }

        else { // for 1 TB and above
            let pre_size = format!("{}", self.size/1099511627776);
            write!(f, "{} TB", &pre_size.pad_to_width(4))
        }
    }
}
<commit_msg>bug fix<commit_after>extern crate pad;
extern crate regex;

use std::cmp::Ordering;
use self::pad::PadStr;
use std::fmt;
use std::path::PathBuf;
use colored::*;

#[derive(Ord, Eq, PartialOrd, PartialEq, Debug, Copy, Clone)]
pub struct FileSize {
    size: u64,
}

impl FileSize {

    pub fn new(i: u64) -> FileSize {
        FileSize { size: i }
    }

    pub fn add(&mut self, other: FileSize) -> () {
        self.size += other.size;
    }

}

pub struct NamePair {
    bytes: FileSize,
    depth: u8,
    name: String,
    is_dir: bool,
}

fn sort_by_size(fst: &NamePair, snd: &NamePair) -> Ordering {
    fst.bytes.cmp(&snd.bytes)
}

impl NamePair {
    pub fn new(path: String, bytes_in: FileSize, d: u8, b: bool) -> NamePair {
        NamePair { name: path, bytes: bytes_in, depth: d, is_dir: b }
    }
}

pub struct FileTree {
    pub file_size: FileSize,
    files: Vec<NamePair>,
}

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

impl FileTree {

    // for whatever reason, it's faster to display smallest files first
    pub fn sort(mut self, maybe_num: Option<usize>, d: u8, min_bytes:Option<u64>, dirs_only: bool) -> FileTree {

        let min_size = if let Some(x) = min_bytes.map(FileSize::new) { x }
            else { FileSize::new(1) };

        // filter by depth & truncate
        if let Some(n) = maybe_num {
            self.files.sort_by(|a, b| sort_by_size(b, a));
            let new = self.files.into_iter()
                .filter(|a| a.depth <= d && (if dirs_only { a.is_dir } else { true }) && a.bytes > min_size )
                .take(n).collect::<Vec<NamePair>>();
            FileTree { file_size: self.file_size, files: new }
        }

        // sort by size and filter by depth
        else {
            self.files.sort_by(|a, b| sort_by_size(a, b));
            let new = self.files.into_iter()
                .filter(|a| a.depth <= d && (if dirs_only { a.is_dir } else { true }) && a.bytes > min_size )
                .collect::<Vec<NamePair>>();
            FileTree { file_size: self.file_size, files: new }
        }
    }

    pub fn filtered(mut self, d: u8, min_bytes: Option<u64>, dirs_only: bool) -> FileTree {

        let min_size = if let Some(x) = min_bytes.map(FileSize::new) { x }
            else { FileSize::new(1) };

        self.files = self.files.into_iter()
            .filter(|a| a.depth <= d && (if dirs_only { a.is_dir } else { true }) && a.bytes > min_size )
            .filter(|a| a.depth <= d)
            .collect::<Vec<NamePair>>();

        FileTree { file_size: self.file_size, files: self.files }
    }

    pub fn new() -> FileTree {
        FileTree { file_size: FileSize::new(0), files: Vec::new() }
    }

    pub fn push(&mut self,
                path: String,
                size: FileSize,
                subtree: Option<&mut FileTree>,
                depth: u8,
                is_dir: bool) -> () {

        // add to total
        self.file_size.add(size);

        // append subtree if appropriate
        if let Some(s) = subtree {
                self.files.append(&mut s.files);
        }

        // return new file tree
        self.files.push(NamePair::new(path, size, depth, is_dir));

    }

    // TODO: make this more intelligent about what it displays
    // 2: if we display the child directory, don't show the parent? unless we display more than one
    //    child, in which case it's probably best to display all 3. AND if a directory is on the
    //    gitignore, it's best to not display its children.
    // 3: if we *are* displaying files, only display the first few in a directory
    pub fn display_tree(&mut self, init_dir: PathBuf) -> () {

        // display stuff
        let vec = &self.files;
        for name_pair in vec {
            if name_pair.bytes != FileSize::new(0) {
                let to_formatted = format!("{}", name_pair.bytes);
                println!("{}\t {}", &to_formatted.green(), name_pair.name);
            }
        }

        // display total if it's nonzero
        if self.file_size != FileSize::new(0) {
            let to_formatted = format!("{}", self.file_size);
            let path = init_dir.display();
            println!("{}\t {}", &to_formatted.green(), path);
        }

    }

}

// TODO print by significant figures?
impl fmt::Display for FileSize {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        if self.size < 1024 {
            let pre_size = format!("{}", self.size);
            write!(f, "{} b", &pre_size.pad_to_width(4))
        }

        else if self.size < 1048576 { // 2^20 = 1024 * 1024
            let pre_size = format!("{}", self.size/1024);
            write!(f, "{} kB", &pre_size.pad_to_width(4))
        }

        else if self.size < 1073741824 { // 2^30
            let pre_size = format!("{}", self.size/1048576);
            write!(f, "{} MB", &pre_size.pad_to_width(4))
        }

        else if self.size < 1099511627776 { // 2^40
            let pre_size = format!("{}", self.size/1073741824);
            write!(f, "{} GB", &pre_size.pad_to_width(4))
        }

        else { // for 1 TB and above
            let pre_size = format!("{}", self.size/1099511627776);
            write!(f, "{} TB", &pre_size.pad_to_width(4))
        }
    }
}
<|endoftext|>


<commit_before>

use syntax::ptr::P;
use syntax::ast;
use syntax::ast::*;
use rustc::lint::{Context, LintPass, LintArray, Lint, Level};
use syntax::codemap::Span;

/// Handles all the linting of funky types
#[allow(missing_copy_implementations)]
pub struct TypePass;

declare_lint!(pub BOX_VEC, Warn,
              "Warn on usage of Box<Vec<T>>");
declare_lint!(pub LINKEDLIST, Warn,
              "Warn on usage of LinkedList");

/// Matches a type with a provided string, and returns its type parameters if successful
pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> {
    match ty.node {
        TyPath(Path {segments: ref seg, ..}, _) => {
            // So ast::Path isn't the full path, just the tokens that were provided.
            // I could muck around with the maps and find the full path
            // however the more efficient way is to simply reverse the iterators and zip them
            // which will compare them in reverse until one of them runs out of segments
            if seg.iter().rev().zip(segments.iter().rev()).all(|(a,b)| a.identifier.as_str() == *b) {
                match seg.as_slice().last() {
                    Some(&PathSegment {parameters: AngleBracketedParameters(ref a), ..}) => {
                        Some(a.types.as_slice())
                    }
                    _ => None
                }
            } else {
                None
            }
        },
        _ => None
    }
}

/// Lets me span a note only if the lint is shown
pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, note: &str) {
    cx.span_lint(lint, span, msg);
    if cx.current_level(lint) != Level::Allow {
        cx.sess().span_note(span, note);
    }
}

impl LintPass for TypePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(BOX_VEC, LINKEDLIST)
    }

    fn check_ty(&mut self, cx: &Context, ty: &ast::Ty) {
        {
            // In case stuff gets moved around
            use std::boxed::Box;
            use std::vec::Vec;
        }
        match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.first())
          .map(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"]))
          .map(|_| {
            span_note_and_lint(cx, BOX_VEC, ty.span,
                              "You seem to be trying to use Box<Vec<T>>. Did you mean to use Vec<T>?",
                              "Vec<T> is already on the heap, Box<Vec<T>> makes an extra allocation");
          });
        {
            // In case stuff gets moved around
            use collections::linked_list::LinkedList as DL1;
            use std::collections::linked_list::LinkedList as DL2;
            use std::collections::linked_list::LinkedList as DL3;
        }
        let dlists = [vec!["std","collections","linked_list","LinkedList"],
                      vec!["std","collections","linked_list","LinkedList"],
                      vec!["collections","linked_list","LinkedList"]];
        for path in dlists.iter() {
            if match_ty_unwrap(ty, path.as_slice()).is_some() {
                span_note_and_lint(cx, LINKEDLIST, ty.span,
                                   "I see you're using a LinkedList! Perhaps you meant some other data structure?",
                                   "A RingBuf might work.");
                return;
            }
        }
    }
}
<commit_msg>rustup<commit_after>

use syntax::ptr::P;
use syntax::ast;
use syntax::ast::*;
use rustc::lint::{Context, LintPass, LintArray, Lint, Level};
use syntax::codemap::Span;

/// Handles all the linting of funky types
#[allow(missing_copy_implementations)]
pub struct TypePass;

declare_lint!(pub BOX_VEC, Warn,
              "Warn on usage of Box<Vec<T>>");
declare_lint!(pub LINKEDLIST, Warn,
              "Warn on usage of LinkedList");

/// Matches a type with a provided string, and returns its type parameters if successful
pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> {
    match ty.node {
        TyPath(_, Path {segments: ref seg, ..}) => {
            // So ast::Path isn't the full path, just the tokens that were provided.
            // I could muck around with the maps and find the full path
            // however the more efficient way is to simply reverse the iterators and zip them
            // which will compare them in reverse until one of them runs out of segments
            if seg.iter().rev().zip(segments.iter().rev()).all(|(a,b)| a.identifier.as_str() == *b) {
                match seg[..].last() {
                    Some(&PathSegment {parameters: AngleBracketedParameters(ref a), ..}) => {
                        Some(&a.types[..])
                    }
                    _ => None
                }
            } else {
                None
            }
        },
        _ => None
    }
}

/// Lets me span a note only if the lint is shown
pub fn span_note_and_lint(cx: &Context, lint: &'static Lint, span: Span, msg: &str, note: &str) {
    cx.span_lint(lint, span, msg);
    if cx.current_level(lint) != Level::Allow {
        cx.sess().span_note(span, note);
    }
}

impl LintPass for TypePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(BOX_VEC, LINKEDLIST)
    }

    fn check_ty(&mut self, cx: &Context, ty: &ast::Ty) {
        {
            // In case stuff gets moved around
            use std::boxed::Box;
            use std::vec::Vec;
        }
        match_ty_unwrap(ty, &["std", "boxed", "Box"]).and_then(|t| t.first())
          .map(|t| match_ty_unwrap(&**t, &["std", "vec", "Vec"]))
          .map(|_| {
            span_note_and_lint(cx, BOX_VEC, ty.span,
                              "You seem to be trying to use Box<Vec<T>>. Did you mean to use Vec<T>?",
                              "Vec<T> is already on the heap, Box<Vec<T>> makes an extra allocation");
          });
        {
            // In case stuff gets moved around
            use collections::linked_list::LinkedList as DL1;
            use std::collections::linked_list::LinkedList as DL2;
            use std::collections::linked_list::LinkedList as DL3;
        }
        let dlists = [vec!["std","collections","linked_list","LinkedList"],
                      vec!["std","collections","linked_list","LinkedList"],
                      vec!["collections","linked_list","LinkedList"]];
        for path in dlists.iter() {
            if match_ty_unwrap(ty, &path[..]).is_some() {
                span_note_and_lint(cx, LINKEDLIST, ty.span,
                                   "I see you're using a LinkedList! Perhaps you meant some other data structure?",
                                   "A RingBuf might work.");
                return;
            }
        }
    }
}
<|endoftext|>