<commit_before>use device;
use device::shade::{Stage, CreateShaderError, ShaderModel};
use super::mesh::{Mesh, VertexFormat};

/// Program linking error
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum ProgramError {
    /// Unable to compile the vertex shader
    Vertex(CreateShaderError),
    /// Unable to compile the fragment shader
    Fragment(CreateShaderError),
    /// Unable to link
    Link(()),
}

/// A type storing shader source for different graphics APIs and versions.
#[allow(missing_docs)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct ShaderSource<'a> {
    pub glsl_120: Option<&'a [u8]>,
    pub glsl_130: Option<&'a [u8]>,
    pub glsl_140: Option<&'a [u8]>,
    pub glsl_150: Option<&'a [u8]>,
    pub glsl_430: Option<&'a [u8]>,
    // TODO: hlsl_sm_N...
    pub targets: &'a [&'a str],
}

impl<'a> ShaderSource<'a> {
    /// Pick one of the stored versions that is the highest supported by the device.
    pub fn choose(&self, model: ShaderModel) -> Result<&'a [u8], ()> {
        // following https://www.opengl.org/wiki/Detecting_the_Shader_Model
        let version = model.to_number();
        Ok(match *self {
            ShaderSource { glsl_430: Some(s), .. } if version >= 50 => s,
            ShaderSource { glsl_150: Some(s), .. } if version >= 40 => s,
            ShaderSource { glsl_130: Some(s), .. } if version >= 30 => s,
            ShaderSource { glsl_120: Some(s), .. } if version >= 20 => s,
            _ => return Err(()),
        })
    }
}

/// Backend extension trait for convenience methods
pub trait DeviceExt: device::Device {
    /// Create a new renderer
    fn create_renderer(&mut self) -> ::Renderer<<Self as device::Device>::CommandBuffer>;
    /// Create a new mesh from the given vertex data.
    /// Convenience function around `create_buffer` and `Mesh::from_format`.
    fn create_mesh<T: VertexFormat + Copy>(&mut self, data: &[T]) -> Mesh;
    /// Create a simple program given a vertex shader with a fragment one.
    fn link_program(&mut self, vs_code: &[u8], fs_code: &[u8])
                    -> Result<device::ProgramHandle, ProgramError>;
    /// Create a simple program given `ShaderSource` versions of vertex and
    /// fragment shaders, chooss the matching versions for the device.
    fn link_program_source(&mut self, vs_src: ShaderSource, fs_src: ShaderSource)
                           -> Result<device::ProgramHandle, ProgramError>;
}

impl<D: device::Device> DeviceExt for D {
    fn create_renderer(&mut self) -> ::Renderer<D::CommandBuffer> {
        ::Renderer {
            command_buffer: device::draw::CommandBuffer::new(),
            data_buffer: device::draw::DataBuffer::new(),
            common_array_buffer: self.create_array_buffer(),
            draw_frame_buffer: self.create_frame_buffer(),
            read_frame_buffer: self.create_frame_buffer(),
            default_frame_buffer: device::get_main_frame_buffer(),
            render_state: super::RenderState::new(),
            parameters: super::ParamStorage::new(),
        }
    }

    fn create_mesh<T: VertexFormat + Copy>(&mut self, data: &[T]) -> Mesh {
        let nv = data.len();
        debug_assert!(nv < {
            use std::num::Int;
            let val: device::VertexCount = Int::max_value();
            val as usize
        });
        let buf = self.create_buffer_static(data);
        Mesh::from_format(buf, nv as device::VertexCount)
    }

    fn link_program(&mut self, vs_code: &[u8], fs_code: &[u8])
                    -> Result<device::ProgramHandle, ProgramError> {
        let vs = match self.create_shader(Stage::Vertex, vs_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Vertex(e)),
        };
        let fs = match self.create_shader(Stage::Fragment, fs_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Fragment(e)),
        };

        self.create_program(&[vs, fs], None)
            .map_err(|e| ProgramError::Link(e))
    }

    fn link_program_source(&mut self, vs_src: ShaderSource, fs_src: ShaderSource)
                           -> Result<device::ProgramHandle, ProgramError> {
        let model = self.get_capabilities().shader_model;
        let err_model = CreateShaderError::ModelNotSupported;

        let vs = match vs_src.choose(model) {
            Ok(code) => match self.create_shader(Stage::Vertex, code) {
                Ok(s) => s,
                Err(e) => return Err(ProgramError::Vertex(e)),
            },
            Err(_) => return Err(ProgramError::Vertex(err_model))
        };

        let fs = match fs_src.choose(model) {
            Ok(code) => match self.create_shader(Stage::Fragment, code) {
                Ok(s) => s,
                Err(e) => return Err(ProgramError::Fragment(e)),
            },
            Err(_) => return Err(ProgramError::Fragment(err_model))
        };

        self.create_program(&[vs, fs], Some(fs_src.targets))
            .map_err(|e| ProgramError::Link(e))
    }
}
<commit_msg>Added an empty constructor to ShaderSource<commit_after>use device;
use device::shade::{Stage, CreateShaderError, ShaderModel};
use super::mesh::{Mesh, VertexFormat};

/// Program linking error
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum ProgramError {
    /// Unable to compile the vertex shader
    Vertex(CreateShaderError),
    /// Unable to compile the fragment shader
    Fragment(CreateShaderError),
    /// Unable to link
    Link(()),
}

/// A type storing shader source for different graphics APIs and versions.
#[allow(missing_docs)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct ShaderSource<'a> {
    pub glsl_120: Option<&'a [u8]>,
    pub glsl_130: Option<&'a [u8]>,
    pub glsl_140: Option<&'a [u8]>,
    pub glsl_150: Option<&'a [u8]>,
    pub glsl_430: Option<&'a [u8]>,
    // TODO: hlsl_sm_N...
    pub targets: &'a [&'a str],
}

impl<'a> ShaderSource<'a> {
    /// Create an empty shader source. Useful for specifying the remaining
    /// structure members upon construction.
    pub fn empty() -> ShaderSource<'a> {
        ShaderSource {
            glsl_120: None,
            glsl_130: None,
            glsl_140: None,
            glsl_150: None,
            glsl_430: None,
            targets: &[],
        }
    }

    /// Pick one of the stored versions that is the highest supported by the device.
    pub fn choose(&self, model: ShaderModel) -> Result<&'a [u8], ()> {
        // following https://www.opengl.org/wiki/Detecting_the_Shader_Model
        let version = model.to_number();
        Ok(match *self {
            ShaderSource { glsl_430: Some(s), .. } if version >= 50 => s,
            ShaderSource { glsl_150: Some(s), .. } if version >= 40 => s,
            ShaderSource { glsl_140: Some(s), .. } if version >= 40 => s,
            ShaderSource { glsl_130: Some(s), .. } if version >= 30 => s,
            ShaderSource { glsl_120: Some(s), .. } if version >= 20 => s,
            _ => return Err(()),
        })
    }
}

/// Backend extension trait for convenience methods
pub trait DeviceExt: device::Device {
    /// Create a new renderer
    fn create_renderer(&mut self) -> ::Renderer<<Self as device::Device>::CommandBuffer>;
    /// Create a new mesh from the given vertex data.
    /// Convenience function around `create_buffer` and `Mesh::from_format`.
    fn create_mesh<T: VertexFormat + Copy>(&mut self, data: &[T]) -> Mesh;
    /// Create a simple program given a vertex shader with a fragment one.
    fn link_program(&mut self, vs_code: &[u8], fs_code: &[u8])
                    -> Result<device::ProgramHandle, ProgramError>;
    /// Create a simple program given `ShaderSource` versions of vertex and
    /// fragment shaders, chooss the matching versions for the device.
    fn link_program_source(&mut self, vs_src: ShaderSource, fs_src: ShaderSource)
                           -> Result<device::ProgramHandle, ProgramError>;
}

impl<D: device::Device> DeviceExt for D {
    fn create_renderer(&mut self) -> ::Renderer<D::CommandBuffer> {
        ::Renderer {
            command_buffer: device::draw::CommandBuffer::new(),
            data_buffer: device::draw::DataBuffer::new(),
            common_array_buffer: self.create_array_buffer(),
            draw_frame_buffer: self.create_frame_buffer(),
            read_frame_buffer: self.create_frame_buffer(),
            default_frame_buffer: device::get_main_frame_buffer(),
            render_state: super::RenderState::new(),
            parameters: super::ParamStorage::new(),
        }
    }

    fn create_mesh<T: VertexFormat + Copy>(&mut self, data: &[T]) -> Mesh {
        let nv = data.len();
        debug_assert!(nv < {
            use std::num::Int;
            let val: device::VertexCount = Int::max_value();
            val as usize
        });
        let buf = self.create_buffer_static(data);
        Mesh::from_format(buf, nv as device::VertexCount)
    }

    fn link_program(&mut self, vs_code: &[u8], fs_code: &[u8])
                    -> Result<device::ProgramHandle, ProgramError> {
        let vs = match self.create_shader(Stage::Vertex, vs_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Vertex(e)),
        };
        let fs = match self.create_shader(Stage::Fragment, fs_code) {
            Ok(s) => s,
            Err(e) => return Err(ProgramError::Fragment(e)),
        };

        self.create_program(&[vs, fs], None)
            .map_err(|e| ProgramError::Link(e))
    }

    fn link_program_source(&mut self, vs_src: ShaderSource, fs_src: ShaderSource)
                           -> Result<device::ProgramHandle, ProgramError> {
        let model = self.get_capabilities().shader_model;
        let err_model = CreateShaderError::ModelNotSupported;

        let vs = match vs_src.choose(model) {
            Ok(code) => match self.create_shader(Stage::Vertex, code) {
                Ok(s) => s,
                Err(e) => return Err(ProgramError::Vertex(e)),
            },
            Err(_) => return Err(ProgramError::Vertex(err_model))
        };

        let fs = match fs_src.choose(model) {
            Ok(code) => match self.create_shader(Stage::Fragment, code) {
                Ok(s) => s,
                Err(e) => return Err(ProgramError::Fragment(e)),
            },
            Err(_) => return Err(ProgramError::Fragment(err_model))
        };

        self.create_program(&[vs, fs], Some(fs_src.targets))
            .map_err(|e| ProgramError::Link(e))
    }
}
<|endoftext|>


<commit_before>extern crate kite;
extern crate kite_rocksdb;
extern crate chrono;
#[macro_use]
extern crate router;
extern crate url;
#[macro_use]
extern crate log;
#[macro_use(o, b)]
extern crate slog;
extern crate slog_term;
#[macro_use]
extern crate maplit;
extern crate unicode_segmentation;
extern crate uuid;
#[macro_use]
extern crate serde_json;
extern crate atomicwrites;

pub mod analysis;
pub mod query_parser;
pub mod mapping;
pub mod document;
pub mod index;
pub mod system;
mod api;
mod logger;

use std::path::Path;
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use slog::Logger;

use system::System;

const VERSION: &'static str = "0.1a0";

fn main() {
    let log = Logger::new_root(o!());
    log.set_drain(slog_term::async_stderr());

    log.info("[sys] starting rusticsearch", b!("version" => VERSION));

    logger::init().unwrap();

    let system = Arc::new(System::new(log, Path::new("data/").to_path_buf()));

    system.log.info("[sys] loading indices", b!());
    system.load_indices();

    {
        let system = system.clone();
        thread::spawn(move || {
            loop {
                {
                    let indices = system.indices.read().unwrap();
                    for index in indices.values() {
                        // TODO: Catch panic
                        index.run_maintenance_task().unwrap();
                    }
                }

                thread::sleep(Duration::new(1, 0));
            }
        });
    }

    system.log.info("[sys] starting api server", b!());
    api::api_main(system);
}
<commit_msg>Get version from Cargo.toml<commit_after>extern crate kite;
extern crate kite_rocksdb;
extern crate chrono;
#[macro_use]
extern crate router;
extern crate url;
#[macro_use]
extern crate log;
#[macro_use(o, b)]
extern crate slog;
extern crate slog_term;
#[macro_use]
extern crate maplit;
extern crate unicode_segmentation;
extern crate uuid;
#[macro_use]
extern crate serde_json;
extern crate atomicwrites;

pub mod analysis;
pub mod query_parser;
pub mod mapping;
pub mod document;
pub mod index;
pub mod system;
mod api;
mod logger;

use std::path::Path;
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use slog::Logger;

use system::System;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

fn main() {
    let log = Logger::new_root(o!());
    log.set_drain(slog_term::async_stderr());

    log.info("[sys] starting rusticsearch", b!("version" => VERSION));

    logger::init().unwrap();

    let system = Arc::new(System::new(log, Path::new("data/").to_path_buf()));

    system.log.info("[sys] loading indices", b!());
    system.load_indices();

    {
        let system = system.clone();
        thread::spawn(move || {
            loop {
                {
                    let indices = system.indices.read().unwrap();
                    for index in indices.values() {
                        // TODO: Catch panic
                        index.run_maintenance_task().unwrap();
                    }
                }

                thread::sleep(Duration::new(1, 0));
            }
        });
    }

    system.log.info("[sys] starting api server", b!());
    api::api_main(system);
}
<|endoftext|>


<commit_before>/* Fundamental layout structures and algorithms. */

use au = gfx::geometry;
use core::dvec::DVec;
use core::to_str::ToStr;
use core::rand;
use css::styles::SpecifiedStyle;
use css::values::{BoxSizing, Length, Px, CSSDisplay};
use dom::base::{Element, ElementKind, HTMLDivElement, HTMLImageElement};
use dom::base::{Node, NodeData, NodeKind, NodeTree};
use dom::rcu;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::geometry::au;
use image::{Image, ImageHolder};
use layout::block::BlockFlowData;
use layout::context::LayoutContext;
use layout::debug::DebugMethods;
use layout::inline::InlineFlowData;
use layout::root::RootFlowData;
use layout::text::TextBoxData;
use servo_text::text_run::TextRun;
use std::arc::{ARC, clone};
use std::net::url::Url;
use task::spawn;
use util::color::Color;
use util::tree;
use vec::{push, push_all};

struct FlowLayoutData {
    mut min_width: au,
    mut pref_width: au,
    mut position: Rect<au>,
}

fn FlowLayoutData() -> FlowLayoutData {
    FlowLayoutData {
        min_width: au(0),
        pref_width: au(0),
        position : au::zero_rect(),
    }
}

/* The type of the formatting context, and data specific to each
context, such as lineboxes or float lists */
enum FlowContextData {
    AbsoluteFlow,
    BlockFlow(BlockFlowData),
    FloatFlow,
    InlineBlockFlow,
    InlineFlow(InlineFlowData),
    RootFlow(RootFlowData),
    TableFlow
}

/* A particular kind of layout context. It manages the positioning of
   layout boxes within the context.

   Flow contexts form a tree that is induced by the structure of the
   box tree. Each context is responsible for laying out one or more
   boxes, according to the flow type. The number of flow contexts should
   be much fewer than the number of boxes. The context maintains a vector
   of its constituent boxes in their document order.
*/
struct FlowContext {
    kind: FlowContextData,
    data: FlowLayoutData,
    /* reference to parent, children flow contexts */
    tree: tree::Tree<@FlowContext>,
    /* TODO: debug only */
    mut id: int
}

fn FlowContext(id: int, kind: FlowContextData, tree: tree::Tree<@FlowContext>) -> FlowContext {
    FlowContext {
        kind: kind,
        data: FlowLayoutData(),
        tree: tree,
        id: id
    }
}

impl @FlowContext : cmp::Eq {
    pure fn eq(&&other: @FlowContext) -> bool { box::ptr_eq(self, other) }
    pure fn ne(&&other: @FlowContext) -> bool { !box::ptr_eq(self, other) }
}

impl @FlowContext {
    fn bubble_widths(ctx: &LayoutContext) {
        match self.kind {
            BlockFlow(*)  => self.bubble_widths_block(ctx),
            InlineFlow(*) => self.bubble_widths_inline(ctx),
            RootFlow(*)   => self.bubble_widths_root(ctx),
            _ => fail fmt!("Tried to bubble_widths of flow: %?", self.kind)
        }
    }

    fn assign_widths(ctx: &LayoutContext) {
        match self.kind {
            BlockFlow(*)  => self.assign_widths_block(ctx),
            InlineFlow(*) => self.assign_widths_inline(ctx),
            RootFlow(*)   => self.assign_widths_root(ctx),
            _ => fail fmt!("Tried to assign_widths of flow: %?", self.kind)
        }
    }

    fn assign_height(ctx: &LayoutContext) {
        match self.kind {
            BlockFlow(*)  => self.assign_height_block(ctx),
            InlineFlow(*) => self.assign_height_inline(ctx),
            RootFlow(*)   => self.assign_height_root(ctx),
            _ => fail fmt!("Tried to assign_height of flow: %?", self.kind)
        }
    }
}

/* The tree holding FlowContexts */
enum FlowTree { FlowTree }

impl FlowTree : tree::ReadMethods<@FlowContext> {
    fn each_child(ctx: @FlowContext, f: fn(&&@FlowContext) -> bool) {
        tree::each_child(self, ctx, f)
    }

    fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
        f(b.tree)
    }
}

impl FlowTree : tree::WriteMethods<@FlowContext> {
    fn add_child(parent: @FlowContext, child: @FlowContext) {
        assert !box::ptr_eq(parent, child);
        tree::add_child(self, parent, child)
    }

    fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
        f(b.tree)
    }
}

/* A box's kind influences how its styles are interpreted during
   layout.  For example, replaced content such as images are resized
   differently than tables, text, or other content.

   It also holds data specific to different box types, such as text.
*/

struct BoxLayoutData {
    mut min_width: au,
    mut pref_width: au,
    mut position: Rect<au>,

    mut font_size: Length,
    mut background_image: Option<ImageHolder>,
}

fn BoxLayoutData() -> BoxLayoutData {
    BoxLayoutData {
        min_width: au(0),
        pref_width: au(0),
        position : au::zero_rect(),

        font_size : Px(0.0),
        background_image : None,
    }
}

enum BoxData {
    GenericBox,
    ImageBox(Size2D<au>),
    TextBox(TextBoxData)
}

struct Box {
    /* references to children, parent */
    tree : tree::Tree<@Box>,
    /* originating DOM node */
    node : Node,
    /* reference to containing flow context, which this box
       participates in */
    ctx  : @FlowContext,
    /* results of flow computation */
    data : BoxLayoutData,
    /* kind tag and kind-specific data */
    kind : BoxData,
    /* TODO: debug only */
    mut id: int
}

fn Box(id: int, node: Node, ctx: @FlowContext, kind: BoxData) -> Box {
    Box {
        /* will be set when box is parented */
        tree : tree::empty(),
        node : node,
        ctx  : ctx,
        data : BoxLayoutData(),
        kind : kind,
        id : id
    }
}

impl @Box {
    pure fn is_replaced() -> bool {
        match self.kind {
            ImageBox(*) => true, // TODO: form elements, etc
            _ => false
        }
    }

    pure fn get_min_width() -> au {
        match self.kind {
            // TODO: this should account for min/pref widths of the
            // box element in isolation. That includes
            // border/margin/padding but not child widths. The block
            // FlowContext will combine the width of this element and
            // that of its children to arrive at the context width.
            GenericBox => au(0),
            // TODO: If image isn't available, consult Node
            // attrs, etc. to determine intrinsic dimensions. These
            // dimensions are not defined by CSS 2.1, but are defined
            // by the HTML5 spec in Section 4.8.1
            ImageBox(size) => size.width,
            // TODO: account for line breaks, etc. The run should know
            // how to compute its own min and pref widths, and should
            // probably cache them.
            TextBox(d) => d.runs.foldl(au(0), |sum, run| {
                au::max(sum, run.min_break_width())
            })
        }
    }

    pure fn get_pref_width() -> au {
        match self.kind {
            // TODO: this should account for min/pref widths of the
            // box element in isolation. That includes
            // border/margin/padding but not child widths. The block
            // FlowContext will combine the width of this element and
            // that of its children to arrive at the context width.
            GenericBox => au(0),
            // TODO: If image isn't available, consult Node
            // attrs, etc. to determine intrinsic dimensions. These
            // dimensions are not defined by CSS 2.1, but are defined
            // by the HTML5 spec in Section 4.8.1
            ImageBox(size) => size.width,
            // TODO: account for line breaks, etc. The run should know
            // how to compute its own min and pref widths, and should
            // probably cache them.
            TextBox(d) => d.runs.foldl(au(0), |sum, run| {
                au::max(sum, run.size().width)
            })
        }
    }

    /* Returns the amount of left, right "fringe" used by this
    box. This should be based on margin, border, padding, width. */
    fn get_used_width() -> (au, au) {
        // TODO: this should actually do some computation!
        // See CSS 2.1, Section 10.3, 10.4.

        (au(0), au(0))
    }

    /* Returns the amount of left, right "fringe" used by this
    box. This should be based on margin, border, padding, width. */
    fn get_used_height() -> (au, au) {
        // TODO: this should actually do some computation!
        // See CSS 2.1, Section 10.5, 10.6.

        (au(0), au(0))
    }

    // This will be very unhappy if it is getting run in parallel with
    // anything trying to read the background image
    fn get_image() -> Option<ARC<~Image>> {
        let mut image = None;

        // Do a dance where we swap the ImageHolder out before we can
        // get the image out of it because we can't match against it
        // because holder.get_image() is not pure.
        if (self.data.background_image).is_some() {
            let mut temp = None;
            temp <-> self.data.background_image;
            let holder <- option::unwrap(temp);
            image = holder.get_image();
            self.data.background_image = Some(holder);
        }

        image
    }
}

// FIXME: Why do these have to be redefined for each node type?

/* The tree holding boxes */
enum BoxTree { BoxTree }

impl BoxTree : tree::ReadMethods<@Box> {
    fn each_child(node: @Box, f: fn(&&@Box) -> bool) {
        tree::each_child(self, node, f)
    }

    fn with_tree_fields<R>(&&b: @Box, f: fn(tree::Tree<@Box>) -> R) -> R {
        f(b.tree)
    }
}

impl BoxTree : tree::WriteMethods<@Box> {
    fn add_child(parent: @Box, child: @Box) {
        assert !box::ptr_eq(parent, child);
        tree::add_child(self, parent, child)
    }

    fn with_tree_fields<R>(&&b: @Box, f: fn(tree::Tree<@Box>) -> R) -> R {
        f(b.tree)
    }
}

// Debugging

impl @FlowContext : DebugMethods {
    fn dump() {
        self.dump_indent(0u);
    }

    /** Dumps the flow tree, for debugging, with indentation. */
    fn dump_indent(indent: uint) {
        let mut s = ~"|";
        for uint::range(0u, indent) |_i| {
            s += ~"---- ";
        }

        s += self.debug_str();
        debug!("%s", s);

        for FlowTree.each_child(self) |child| {
            child.dump_indent(indent + 1u)
        }
    }

    /* TODO: we need a string builder. This is horribly inefficient */
    fn debug_str() -> ~str {
        let repr = match self.kind {
            InlineFlow(d) => {
                let mut s = d.boxes.foldl(~"InlineFlow(children=", |s, box| {
                    fmt!("%s %?", s, box.id)
                });
                s += ~")"; s
            },
            BlockFlow(d) => {
                match d.box {
                    Some(b) => fmt!("BlockFlow(box=b%?)", d.box.get().id),
                    None => ~"BlockFlow",
                }
            },
            _ => fmt!("%?", self.kind)
        };

        fmt!("c%? %?", self.id, repr)
    }
}

impl @Box : DebugMethods {
    fn dump() {
        self.dump_indent(0u);
    }

    /* Dumps the node tree, for debugging, with indentation. */
    fn dump_indent(indent: uint) {
        let mut s = ~"";
        for uint::range(0u, indent) |_i| {
            s += ~"    ";
        }

        s += self.debug_str();
        debug!("%s", s);

        for BoxTree.each_child(self) |kid| {
            kid.dump_indent(indent + 1u)
        }
    }

    fn debug_str() -> ~str {
        let repr = match self.kind {
            GenericBox(*) => ~"GenericBox",
            ImageBox(*) => ~"ImageBox",
            TextBox(d) => {
                let mut s = d.runs.foldl(~"TextBox(runs=", |s, run| {
                    fmt!("%s  \"%s\"", s, run.text)
                });
                s += ~")"; s
            }
        };

        fmt!("box b%?: %?", self.id, repr)
    }
}

#[cfg(test)]
mod test {
    use dom::base::{Element, ElementData, HTMLDivElement, HTMLImageElement, Node, NodeKind};
    use dom::base::{NodeScope};
    use dom::rcu::Scope;

    /*
    use sdl;
    use sdl::video;

    fn with_screen(f: fn(*sdl::surface)) {
        let screen = video::set_video_mode(
            320, 200, 32,
            ~[video::hwsurface], ~[video::doublebuf]);
        assert screen != ptr::null();

        f(screen);

        video::free_surface(screen);
    }
    */

    fn flat_bounds(root: @Box) -> ~[Rect<au>] {
        let mut r = ~[];
        for tree::each_child(BoxTree, root) |c| {
            push_all(r, flat_bounds(c));
        }

        push(r, copy root.data.position);

        return r;
    }

    // TODO: redo tests here, but probably is part of box_builder.rs
}

<commit_msg>Remove used min/pref width from BoxLayoutData<commit_after>/* Fundamental layout structures and algorithms. */

use au = gfx::geometry;
use core::dvec::DVec;
use core::to_str::ToStr;
use core::rand;
use css::styles::SpecifiedStyle;
use css::values::{BoxSizing, Length, Px, CSSDisplay};
use dom::base::{Element, ElementKind, HTMLDivElement, HTMLImageElement};
use dom::base::{Node, NodeData, NodeKind, NodeTree};
use dom::rcu;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::geometry::au;
use image::{Image, ImageHolder};
use layout::block::BlockFlowData;
use layout::context::LayoutContext;
use layout::debug::DebugMethods;
use layout::inline::InlineFlowData;
use layout::root::RootFlowData;
use layout::text::TextBoxData;
use servo_text::text_run::TextRun;
use std::arc::{ARC, clone};
use std::net::url::Url;
use task::spawn;
use util::color::Color;
use util::tree;
use vec::{push, push_all};

struct FlowLayoutData {
    mut min_width: au,
    mut pref_width: au,
    mut position: Rect<au>,
}

fn FlowLayoutData() -> FlowLayoutData {
    FlowLayoutData {
        min_width: au(0),
        pref_width: au(0),
        position : au::zero_rect(),
    }
}

/* The type of the formatting context, and data specific to each
context, such as lineboxes or float lists */
enum FlowContextData {
    AbsoluteFlow,
    BlockFlow(BlockFlowData),
    FloatFlow,
    InlineBlockFlow,
    InlineFlow(InlineFlowData),
    RootFlow(RootFlowData),
    TableFlow
}

/* A particular kind of layout context. It manages the positioning of
   layout boxes within the context.

   Flow contexts form a tree that is induced by the structure of the
   box tree. Each context is responsible for laying out one or more
   boxes, according to the flow type. The number of flow contexts should
   be much fewer than the number of boxes. The context maintains a vector
   of its constituent boxes in their document order.
*/
struct FlowContext {
    kind: FlowContextData,
    data: FlowLayoutData,
    /* reference to parent, children flow contexts */
    tree: tree::Tree<@FlowContext>,
    /* TODO: debug only */
    mut id: int
}

fn FlowContext(id: int, kind: FlowContextData, tree: tree::Tree<@FlowContext>) -> FlowContext {
    FlowContext {
        kind: kind,
        data: FlowLayoutData(),
        tree: tree,
        id: id
    }
}

impl @FlowContext : cmp::Eq {
    pure fn eq(&&other: @FlowContext) -> bool { box::ptr_eq(self, other) }
    pure fn ne(&&other: @FlowContext) -> bool { !box::ptr_eq(self, other) }
}

impl @FlowContext {
    fn bubble_widths(ctx: &LayoutContext) {
        match self.kind {
            BlockFlow(*)  => self.bubble_widths_block(ctx),
            InlineFlow(*) => self.bubble_widths_inline(ctx),
            RootFlow(*)   => self.bubble_widths_root(ctx),
            _ => fail fmt!("Tried to bubble_widths of flow: %?", self.kind)
        }
    }

    fn assign_widths(ctx: &LayoutContext) {
        match self.kind {
            BlockFlow(*)  => self.assign_widths_block(ctx),
            InlineFlow(*) => self.assign_widths_inline(ctx),
            RootFlow(*)   => self.assign_widths_root(ctx),
            _ => fail fmt!("Tried to assign_widths of flow: %?", self.kind)
        }
    }

    fn assign_height(ctx: &LayoutContext) {
        match self.kind {
            BlockFlow(*)  => self.assign_height_block(ctx),
            InlineFlow(*) => self.assign_height_inline(ctx),
            RootFlow(*)   => self.assign_height_root(ctx),
            _ => fail fmt!("Tried to assign_height of flow: %?", self.kind)
        }
    }
}

/* The tree holding FlowContexts */
enum FlowTree { FlowTree }

impl FlowTree : tree::ReadMethods<@FlowContext> {
    fn each_child(ctx: @FlowContext, f: fn(&&@FlowContext) -> bool) {
        tree::each_child(self, ctx, f)
    }

    fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
        f(b.tree)
    }
}

impl FlowTree : tree::WriteMethods<@FlowContext> {
    fn add_child(parent: @FlowContext, child: @FlowContext) {
        assert !box::ptr_eq(parent, child);
        tree::add_child(self, parent, child)
    }

    fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
        f(b.tree)
    }
}

/* A box's kind influences how its styles are interpreted during
   layout.  For example, replaced content such as images are resized
   differently than tables, text, or other content.

   It also holds data specific to different box types, such as text.
*/

struct BoxLayoutData {
    mut position: Rect<au>,
    mut font_size: Length,
    mut background_image: Option<ImageHolder>,
}

fn BoxLayoutData() -> BoxLayoutData {
    BoxLayoutData {
        position : au::zero_rect(),
        font_size : Px(0.0),
        background_image : None,
    }
}

enum BoxData {
    GenericBox,
    ImageBox(Size2D<au>),
    TextBox(TextBoxData)
}

struct Box {
    /* references to children, parent */
    tree : tree::Tree<@Box>,
    /* originating DOM node */
    node : Node,
    /* reference to containing flow context, which this box
       participates in */
    ctx  : @FlowContext,
    /* results of flow computation */
    data : BoxLayoutData,
    /* kind tag and kind-specific data */
    kind : BoxData,
    /* TODO: debug only */
    mut id: int
}

fn Box(id: int, node: Node, ctx: @FlowContext, kind: BoxData) -> Box {
    Box {
        /* will be set when box is parented */
        tree : tree::empty(),
        node : node,
        ctx  : ctx,
        data : BoxLayoutData(),
        kind : kind,
        id : id
    }
}

impl @Box {
    pure fn is_replaced() -> bool {
        match self.kind {
            ImageBox(*) => true, // TODO: form elements, etc
            _ => false
        }
    }

    pure fn get_min_width() -> au {
        match self.kind {
            // TODO: this should account for min/pref widths of the
            // box element in isolation. That includes
            // border/margin/padding but not child widths. The block
            // FlowContext will combine the width of this element and
            // that of its children to arrive at the context width.
            GenericBox => au(0),
            // TODO: If image isn't available, consult Node
            // attrs, etc. to determine intrinsic dimensions. These
            // dimensions are not defined by CSS 2.1, but are defined
            // by the HTML5 spec in Section 4.8.1
            ImageBox(size) => size.width,
            // TODO: account for line breaks, etc. The run should know
            // how to compute its own min and pref widths, and should
            // probably cache them.
            TextBox(d) => d.runs.foldl(au(0), |sum, run| {
                au::max(sum, run.min_break_width())
            })
        }
    }

    pure fn get_pref_width() -> au {
        match self.kind {
            // TODO: this should account for min/pref widths of the
            // box element in isolation. That includes
            // border/margin/padding but not child widths. The block
            // FlowContext will combine the width of this element and
            // that of its children to arrive at the context width.
            GenericBox => au(0),
            // TODO: If image isn't available, consult Node
            // attrs, etc. to determine intrinsic dimensions. These
            // dimensions are not defined by CSS 2.1, but are defined
            // by the HTML5 spec in Section 4.8.1
            ImageBox(size) => size.width,
            // TODO: account for line breaks, etc. The run should know
            // how to compute its own min and pref widths, and should
            // probably cache them.
            TextBox(d) => d.runs.foldl(au(0), |sum, run| {
                au::max(sum, run.size().width)
            })
        }
    }

    /* Returns the amount of left, right "fringe" used by this
    box. This should be based on margin, border, padding, width. */
    fn get_used_width() -> (au, au) {
        // TODO: this should actually do some computation!
        // See CSS 2.1, Section 10.3, 10.4.

        (au(0), au(0))
    }

    /* Returns the amount of left, right "fringe" used by this
    box. This should be based on margin, border, padding, width. */
    fn get_used_height() -> (au, au) {
        // TODO: this should actually do some computation!
        // See CSS 2.1, Section 10.5, 10.6.

        (au(0), au(0))
    }

    // This will be very unhappy if it is getting run in parallel with
    // anything trying to read the background image
    fn get_image() -> Option<ARC<~Image>> {
        let mut image = None;

        // Do a dance where we swap the ImageHolder out before we can
        // get the image out of it because we can't match against it
        // because holder.get_image() is not pure.
        if (self.data.background_image).is_some() {
            let mut temp = None;
            temp <-> self.data.background_image;
            let holder <- option::unwrap(temp);
            image = holder.get_image();
            self.data.background_image = Some(holder);
        }

        image
    }
}

// FIXME: Why do these have to be redefined for each node type?

/* The tree holding boxes */
enum BoxTree { BoxTree }

impl BoxTree : tree::ReadMethods<@Box> {
    fn each_child(node: @Box, f: fn(&&@Box) -> bool) {
        tree::each_child(self, node, f)
    }

    fn with_tree_fields<R>(&&b: @Box, f: fn(tree::Tree<@Box>) -> R) -> R {
        f(b.tree)
    }
}

impl BoxTree : tree::WriteMethods<@Box> {
    fn add_child(parent: @Box, child: @Box) {
        assert !box::ptr_eq(parent, child);
        tree::add_child(self, parent, child)
    }

    fn with_tree_fields<R>(&&b: @Box, f: fn(tree::Tree<@Box>) -> R) -> R {
        f(b.tree)
    }
}

// Debugging

impl @FlowContext : DebugMethods {
    fn dump() {
        self.dump_indent(0u);
    }

    /** Dumps the flow tree, for debugging, with indentation. */
    fn dump_indent(indent: uint) {
        let mut s = ~"|";
        for uint::range(0u, indent) |_i| {
            s += ~"---- ";
        }

        s += self.debug_str();
        debug!("%s", s);

        for FlowTree.each_child(self) |child| {
            child.dump_indent(indent + 1u)
        }
    }

    /* TODO: we need a string builder. This is horribly inefficient */
    fn debug_str() -> ~str {
        let repr = match self.kind {
            InlineFlow(d) => {
                let mut s = d.boxes.foldl(~"InlineFlow(children=", |s, box| {
                    fmt!("%s %?", s, box.id)
                });
                s += ~")"; s
            },
            BlockFlow(d) => {
                match d.box {
                    Some(b) => fmt!("BlockFlow(box=b%?)", d.box.get().id),
                    None => ~"BlockFlow",
                }
            },
            _ => fmt!("%?", self.kind)
        };

        fmt!("c%? %?", self.id, repr)
    }
}

impl @Box : DebugMethods {
    fn dump() {
        self.dump_indent(0u);
    }

    /* Dumps the node tree, for debugging, with indentation. */
    fn dump_indent(indent: uint) {
        let mut s = ~"";
        for uint::range(0u, indent) |_i| {
            s += ~"    ";
        }

        s += self.debug_str();
        debug!("%s", s);

        for BoxTree.each_child(self) |kid| {
            kid.dump_indent(indent + 1u)
        }
    }

    fn debug_str() -> ~str {
        let repr = match self.kind {
            GenericBox(*) => ~"GenericBox",
            ImageBox(*) => ~"ImageBox",
            TextBox(d) => {
                let mut s = d.runs.foldl(~"TextBox(runs=", |s, run| {
                    fmt!("%s  \"%s\"", s, run.text)
                });
                s += ~")"; s
            }
        };

        fmt!("box b%?: %?", self.id, repr)
    }
}

#[cfg(test)]
mod test {
    use dom::base::{Element, ElementData, HTMLDivElement, HTMLImageElement, Node, NodeKind};
    use dom::base::{NodeScope};
    use dom::rcu::Scope;

    /*
    use sdl;
    use sdl::video;

    fn with_screen(f: fn(*sdl::surface)) {
        let screen = video::set_video_mode(
            320, 200, 32,
            ~[video::hwsurface], ~[video::doublebuf]);
        assert screen != ptr::null();

        f(screen);

        video::free_surface(screen);
    }
    */

    fn flat_bounds(root: @Box) -> ~[Rect<au>] {
        let mut r = ~[];
        for tree::each_child(BoxTree, root) |c| {
            push_all(r, flat_bounds(c));
        }

        push(r, copy root.data.position);

        return r;
    }

    // TODO: redo tests here, but probably is part of box_builder.rs
}

<|endoftext|>


<commit_before>// 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 engine::Engine;
use engine::EngineError;
use engine::EngineResult;
use engine::ErrorEnum;

use engine::Pool;

use std::cell::RefCell;
use std::path::Path;
use std::collections::BTreeMap;
use std::iter::FromIterator;
use std::rc::Rc;

use super::blockdev::SimDev;
use super::pool::SimPool;
use super::randomization::Randomizer;

#[derive(Debug)]
pub struct SimEngine {
    pub pools: BTreeMap<String, Box<Pool>>,
    rdm: Rc<RefCell<Randomizer>>,
}

impl SimEngine {
    pub fn new() -> SimEngine {
        SimEngine {
            pools: BTreeMap::new(),
            rdm: Rc::new(RefCell::new(Randomizer::new())),
        }
    }
}

impl Engine for SimEngine {
    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   raid_level: u16)
                   -> EngineResult<()> {

        if self.pools.contains_key(name) {
            return Err(EngineError::Stratis(ErrorEnum::AlreadyExists(name.into())));
        }

        let devs: Vec<Box<SimDev>> =
            blockdev_paths.iter().map(|x| SimDev::new_dev(self.rdm.clone(), x)).collect();

        match self.rdm.borrow_mut().get_bad_item(&devs) {
            Some(d) => {
                let path_as_str = d.name.to_str().unwrap_or("unstringable path");
                return Err(EngineError::Stratis(ErrorEnum::Busy(path_as_str.into())));
            }
            None => {}
        }

        let pool = SimPool::new_pool(self.rdm.clone(), devs.as_slice(), raid_level);

        if self.rdm.borrow_mut().throw_die() {
            return Err(EngineError::Stratis(ErrorEnum::Error("X".into())));
        }

        self.pools.insert(name.to_owned(), pool);
        Ok(())
    }

    fn destroy_pool(&mut self, name: &str) -> EngineResult<()> {
        if self.rdm.borrow_mut().throw_die() {
            return Err(EngineError::Stratis(ErrorEnum::Busy("X".into())));
        }

        self.pools.remove(name);

        Ok(())
    }
    fn get_pool(&mut self, name: &str) -> EngineResult<&mut Box<Pool>> {

        let return_pool = match self.pools.get_mut(name) {
            Some(pool) => pool,
            None => return Err(EngineError::Stratis(ErrorEnum::NotFound(name.into()))),
        };

        Ok(return_pool)
    }

    fn list_pools(&self) -> EngineResult<BTreeMap<String, Box<Pool>>> {

        Ok(BTreeMap::from_iter(self.pools.iter().map(|x| (x.0.clone(), x.1.copy()))))

    }
}
<commit_msg>Use a better method for checking whether devices are bad.<commit_after>// 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 engine::Engine;
use engine::EngineError;
use engine::EngineResult;
use engine::ErrorEnum;

use engine::Pool;

use std::cell::RefCell;
use std::path::Path;
use std::collections::BTreeMap;
use std::iter::FromIterator;
use std::rc::Rc;

use super::blockdev::SimDev;
use super::pool::SimPool;
use super::randomization::Randomizer;

#[derive(Debug)]
pub struct SimEngine {
    pub pools: BTreeMap<String, Box<Pool>>,
    rdm: Rc<RefCell<Randomizer>>,
}

impl SimEngine {
    pub fn new() -> SimEngine {
        SimEngine {
            pools: BTreeMap::new(),
            rdm: Rc::new(RefCell::new(Randomizer::new())),
        }
    }
}

impl Engine for SimEngine {
    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   raid_level: u16)
                   -> EngineResult<()> {

        if self.pools.contains_key(name) {
            return Err(EngineError::Stratis(ErrorEnum::AlreadyExists(name.into())));
        }

        let mut devs: Vec<Box<SimDev>> =
            blockdev_paths.iter().map(|x| SimDev::new_dev(self.rdm.clone(), x)).collect();

        for dev in devs.iter_mut() {
            dev.update();
        }

        let bad_devs: Vec<&Box<SimDev>> = devs.iter().filter(|dev| !dev.usable()).collect();

        if !bad_devs.is_empty() {
            return Err(EngineError::Stratis(ErrorEnum::Busy("some devices are unusable".into())));
        }

        let pool = SimPool::new_pool(self.rdm.clone(), devs.as_slice(), raid_level);

        if self.rdm.borrow_mut().throw_die() {
            return Err(EngineError::Stratis(ErrorEnum::Error("X".into())));
        }

        self.pools.insert(name.to_owned(), pool);
        Ok(())
    }

    fn destroy_pool(&mut self, name: &str) -> EngineResult<()> {
        if self.rdm.borrow_mut().throw_die() {
            return Err(EngineError::Stratis(ErrorEnum::Busy("X".into())));
        }

        self.pools.remove(name);

        Ok(())
    }
    fn get_pool(&mut self, name: &str) -> EngineResult<&mut Box<Pool>> {

        let return_pool = match self.pools.get_mut(name) {
            Some(pool) => pool,
            None => return Err(EngineError::Stratis(ErrorEnum::NotFound(name.into()))),
        };

        Ok(return_pool)
    }

    fn list_pools(&self) -> EngineResult<BTreeMap<String, Box<Pool>>> {

        Ok(BTreeMap::from_iter(self.pools.iter().map(|x| (x.0.clone(), x.1.copy()))))

    }
}
<|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/.

extern crate libc;
extern crate errno;

use std::{fmt, error};
use std::io::{Read, Write, Error, ErrorKind};

use self::libc::{c_int, c_void};

pub struct Socket {
    pub fd: c_int
}

impl Read for Socket {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        if buf.len() < 1 {
            return Err(Error::new(ErrorKind::Other, ReadError::InvalidBuffer))
        }

        let result = unsafe {
            libc::read(self.fd, buf as *mut _ as *mut c_void, buf.len())
        };

        if result < 0 {
            return Err(Error::new(ErrorKind::Other, ReadError::from_errno(result as i32)))
        }

        Ok(result as usize)
    }
}

impl Write for Socket {
    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
        let result = unsafe {
            libc::write(self.fd, buf as *const _ as *const c_void, buf.len())
        };

        if result < 0 {
            return Err(Error::new(ErrorKind::Other, WriteError::from_errno(result as i32)))
        }

        Ok(result as usize)
    }

    fn flush(&mut self) -> Result<(), Error> { Ok(()) }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum ReadError {
    /// System did not have enough memory to complete the read operation.
    NoMemory,
    /// The file descriptor fd refers to a file other than a socket and has been
    /// marked nonblocking (O_NONBLOCK), and the read would block.
    WouldBlock,
    /// This could be several things:
    ///
    /// * Fd is not a valid file descriptor.
    /// * Fd is not open for reading.
    /// * Fd is attached to an object which is unsuitable for reading
    /// * The file was opened with the `O_DIRECT` flag, and either the address specified in buf,
    ///   the value specified in count, or the current file offset is not suitably aligned.
    /// * fd was created via a call to timerfd_create(2) and the wrong size buffer was given to
    ///   `read()`
    InvalidFd,
    /// buf is outside your accessible address space.
    MemAccess,
    /// The call was interrupted by a signal before any data was read.
    /// [see signal(7)][signal7]
    /// [signal7]: http://man7.org/linux/man-pages/man7/signal.7.html
    Signal,
    /// I/O error. This will happen for example when the process is in a background process
    /// group, tries to read from its controlling terminal, and either it is ignoring or
    /// blocking SIGTTIN or its process group is orphaned. It may also occur when there
    /// is a low-level I/O error while reading from a disk or tape.
    Io,
    /// End of file has been reached or fd is connected to a TCP socket where the other end has
    /// been closed, but the write command has not had enough time to finish writing to the
    /// internal buffer. No more can be read from this socket.
    Closed,
    /// Passed buffer length was less than 1
    InvalidBuffer
}

impl ReadError {
    pub fn from_errno(errno: i32) -> ReadError {
        match errno {
            libc::ENOMEM => ReadError::NoMemory,
            libc::EBADF => ReadError::InvalidFd,
            libc::EFAULT => ReadError::MemAccess,
            libc::EINTR => ReadError::Signal,
            libc::EINVAL => ReadError::InvalidFd,
            libc::EIO => ReadError::Io,
            libc::EISDIR => ReadError::InvalidFd,
            libc::ECONNRESET => ReadError::Closed,
            libc::EOF => ReadError::Closed,
            libc::EWOULDBLOCK => ReadError::WouldBlock,

            _ => panic!("Unexpected errno during read: {}", errno)
        }
    }
}

impl fmt::Display for ReadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ReadError::NoMemory => "NoMemory".fmt(f),
            ReadError::WouldBlock => "WouldBlock".fmt(f),
            ReadError::InvalidFd => "InvalidFd".fmt(f),
            ReadError::MemAccess => "MemAccess".fmt(f),
            ReadError::Signal => "Signal".fmt(f),
            ReadError::Io => "Io".fmt(f),
            ReadError::Closed => "Closed".fmt(f),
            ReadError::InvalidBuffer => "InvalidBuffer".fmt(f)
        }
    }
}

impl error::Error for ReadError {
    fn description(&self) -> &str {
        match *self {
            ReadError::NoMemory => "NoMemory",
            ReadError::WouldBlock => "WouldBlock",
            ReadError::InvalidFd => "InvalidFd",
            ReadError::MemAccess => "MemAccess",
            ReadError::Signal => "Signal",
            ReadError::Io => "Io",
            ReadError::Closed => "Closed",
            ReadError::InvalidBuffer => "InvalidBuffer"
        }
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum WriteError {
    /// The file descriptor fd refers to a file other than a socket and has been
    /// marked nonblocking (O_NONBLOCK), and the read would block.
    WouldBlock,
    /// This could be several things:
    ///
    /// * Fd is not a valid file descriptor.
    /// * Fd is not open for writing.
    /// * Fd is attached to an object which is unsuitable for writing
    /// * The file was opened with the `O_DIRECT` flag, and either the address specified in buf,
    ///   the value specified in count, or the current file offset is not suitably aligned.
    InvalidFd,
    /// buf is outside your accessible address space.
    MemAccess,
    /// The call was interrupted by a signal before any data was read.
    /// [see signal(7)][signal7]
    /// [signal7]: http://man7.org/linux/man-pages/man7/signal.7.html
    Signal,
    /// A low-level I/O error occurred while modifying the inode.
    Io,
    /// fd is connected to a pipe or socket whose reading end is closed. When this happens
    /// the writing process will also receive a SIGPIPE signal. (Thus, the write return value
    /// is seen only if the program catches, blocks or ignores this signal.) Or, fd is connected
    /// to a TCP socket where the other end has been closed, but the write command has not had
    /// enough time to finish writing to the internal buffer.
    Closed
}

impl WriteError {
    pub fn from_errno(errno: i32) -> WriteError {
        match errno {
            libc::EAGAIN => WriteError::WouldBlock,
            libc::EBADF => WriteError::InvalidFd,
            libc::EFAULT => WriteError::MemAccess,
            libc::EINTR => WriteError::Signal,
            libc::EINVAL => WriteError::InvalidFd,
            libc::EIO => WriteError::Io,
            libc::EPIPE => WriteError::Closed,
            libc::ECONNRESET => WriteError::Closed,

            _ => panic!("Unexpected errno during read: {}", errno)
        }
    }
}

impl fmt::Display for WriteError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            WriteError::WouldBlock => "WouldBlock".fmt(f),
            WriteError::InvalidFd => "InvalidFd".fmt(f),
            WriteError::MemAccess => "MemAccess".fmt(f),
            WriteError::Signal => "Signal".fmt(f),
            WriteError::Io => "Io".fmt(f),
            WriteError::Closed => "Closed".fmt(f)
        }
    }
}

impl error::Error for WriteError {
    fn description(&self) -> &str {
        match *self {
            WriteError::WouldBlock => "WouldBlock",
            WriteError::InvalidFd => "InvalidFd",
            WriteError::MemAccess => "MemAccess",
            WriteError::Signal => "Signal",
            WriteError::Io => "Io",
            WriteError::Closed => "Closed"
        }
    }
}
<commit_msg>Comments added<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/.

extern crate libc;
extern crate errno;

use std::{fmt, error};
use std::io::{Read, Write, Error, ErrorKind};

use self::libc::{c_int, c_void};

pub struct Socket {
    /// This socket's file descriptor
    pub fd: c_int
}

impl Read for Socket {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        if buf.len() < 1 {
            return Err(Error::new(ErrorKind::Other, ReadError::InvalidBuffer))
        }

        let result = unsafe {
            libc::read(self.fd, buf as *mut _ as *mut c_void, buf.len())
        };

        if result < 0 {
            return Err(Error::new(ErrorKind::Other, ReadError::from_errno(result as i32)))
        }

        Ok(result as usize)
    }
}

impl Write for Socket {
    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
        let result = unsafe {
            libc::write(self.fd, buf as *const _ as *const c_void, buf.len())
        };

        if result < 0 {
            return Err(Error::new(ErrorKind::Other, WriteError::from_errno(result as i32)))
        }

        Ok(result as usize)
    }

    fn flush(&mut self) -> Result<(), Error> { Ok(()) }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum ReadError {
    /// System did not have enough memory to complete the read operation.
    NoMemory,
    /// The file descriptor fd refers to a file other than a socket and has been
    /// marked nonblocking (O_NONBLOCK), and the read would block.
    WouldBlock,
    /// This could be several things:
    ///
    /// * Fd is not a valid file descriptor.
    /// * Fd is not open for reading.
    /// * Fd is attached to an object which is unsuitable for reading
    /// * The file was opened with the `O_DIRECT` flag, and either the address specified in buf,
    ///   the value specified in count, or the current file offset is not suitably aligned.
    /// * fd was created via a call to timerfd_create(2) and the wrong size buffer was given to
    ///   `read()`
    InvalidFd,
    /// buf is outside your accessible address space.
    MemAccess,
    /// The call was interrupted by a signal before any data was read.
    /// [see signal(7)][signal7]
    /// [signal7]: http://man7.org/linux/man-pages/man7/signal.7.html
    Signal,
    /// I/O error. This will happen for example when the process is in a background process
    /// group, tries to read from its controlling terminal, and either it is ignoring or
    /// blocking SIGTTIN or its process group is orphaned. It may also occur when there
    /// is a low-level I/O error while reading from a disk or tape.
    Io,
    /// End of file has been reached or fd is connected to a TCP socket where the other end has
    /// been closed, but the write command has not had enough time to finish writing to the
    /// internal buffer. No more can be read from this socket.
    Closed,
    /// Passed buffer length was less than 1
    InvalidBuffer
}

impl ReadError {
    pub fn from_errno(errno: i32) -> ReadError {
        match errno {
            libc::ENOMEM => ReadError::NoMemory,
            libc::EBADF => ReadError::InvalidFd,
            libc::EFAULT => ReadError::MemAccess,
            libc::EINTR => ReadError::Signal,
            libc::EINVAL => ReadError::InvalidFd,
            libc::EIO => ReadError::Io,
            libc::EISDIR => ReadError::InvalidFd,
            libc::ECONNRESET => ReadError::Closed,
            libc::EOF => ReadError::Closed,
            libc::EWOULDBLOCK => ReadError::WouldBlock,

            _ => panic!("Unexpected errno during read: {}", errno)
        }
    }
}

impl fmt::Display for ReadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ReadError::NoMemory => "NoMemory".fmt(f),
            ReadError::WouldBlock => "WouldBlock".fmt(f),
            ReadError::InvalidFd => "InvalidFd".fmt(f),
            ReadError::MemAccess => "MemAccess".fmt(f),
            ReadError::Signal => "Signal".fmt(f),
            ReadError::Io => "Io".fmt(f),
            ReadError::Closed => "Closed".fmt(f),
            ReadError::InvalidBuffer => "InvalidBuffer".fmt(f)
        }
    }
}

impl error::Error for ReadError {
    fn description(&self) -> &str {
        match *self {
            ReadError::NoMemory => "NoMemory",
            ReadError::WouldBlock => "WouldBlock",
            ReadError::InvalidFd => "InvalidFd",
            ReadError::MemAccess => "MemAccess",
            ReadError::Signal => "Signal",
            ReadError::Io => "Io",
            ReadError::Closed => "Closed",
            ReadError::InvalidBuffer => "InvalidBuffer"
        }
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum WriteError {
    /// The file descriptor fd refers to a file other than a socket and has been
    /// marked nonblocking (O_NONBLOCK), and the read would block.
    WouldBlock,
    /// This could be several things:
    ///
    /// * Fd is not a valid file descriptor.
    /// * Fd is not open for writing.
    /// * Fd is attached to an object which is unsuitable for writing
    /// * The file was opened with the `O_DIRECT` flag, and either the address specified in buf,
    ///   the value specified in count, or the current file offset is not suitably aligned.
    InvalidFd,
    /// buf is outside your accessible address space.
    MemAccess,
    /// The call was interrupted by a signal before any data was read.
    /// [see signal(7)][signal7]
    /// [signal7]: http://man7.org/linux/man-pages/man7/signal.7.html
    Signal,
    /// A low-level I/O error occurred while modifying the inode.
    Io,
    /// fd is connected to a pipe or socket whose reading end is closed. When this happens
    /// the writing process will also receive a SIGPIPE signal. (Thus, the write return value
    /// is seen only if the program catches, blocks or ignores this signal.) Or, fd is connected
    /// to a TCP socket where the other end has been closed, but the write command has not had
    /// enough time to finish writing to the internal buffer.
    Closed
}

impl WriteError {
    pub fn from_errno(errno: i32) -> WriteError {
        match errno {
            libc::EAGAIN => WriteError::WouldBlock,
            libc::EBADF => WriteError::InvalidFd,
            libc::EFAULT => WriteError::MemAccess,
            libc::EINTR => WriteError::Signal,
            libc::EINVAL => WriteError::InvalidFd,
            libc::EIO => WriteError::Io,
            libc::EPIPE => WriteError::Closed,
            libc::ECONNRESET => WriteError::Closed,

            _ => panic!("Unexpected errno during read: {}", errno)
        }
    }
}

impl fmt::Display for WriteError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            WriteError::WouldBlock => "WouldBlock".fmt(f),
            WriteError::InvalidFd => "InvalidFd".fmt(f),
            WriteError::MemAccess => "MemAccess".fmt(f),
            WriteError::Signal => "Signal".fmt(f),
            WriteError::Io => "Io".fmt(f),
            WriteError::Closed => "Closed".fmt(f)
        }
    }
}

impl error::Error for WriteError {
    fn description(&self) -> &str {
        match *self {
            WriteError::WouldBlock => "WouldBlock",
            WriteError::InvalidFd => "InvalidFd",
            WriteError::MemAccess => "MemAccess",
            WriteError::Signal => "Signal",
            WriteError::Io => "Io",
            WriteError::Closed => "Closed"
        }
    }
}
<|endoftext|>


<commit_before>use fixedbitset::FixedBitSet;
use std::iter;

use super::weight::Weight;

pub struct Graph {
    num_nodes: usize,

    // a 2-d matrix indexed by (source, target); if `Weight::max()`
    // is stored in a particular entry, that means that there is no
    // edge. Otherwise, the weight is found.
    weights: Vec<Weight>,
}

impl Graph {
    pub fn new(num_nodes: usize) -> Graph {
        Graph {
            num_nodes: num_nodes,
            weights: iter::repeat(Weight::max()).take(num_nodes * num_nodes).collect(),
        }
    }

    pub fn num_nodes(&self) -> usize {
        self.num_nodes
    }

    pub fn all_nodes(&self) -> impl Iterator<Item=Node> {
        (0..self.num_nodes).map(Node::new)
    }

    pub fn node_set(&self) -> NodeSet {
        NodeSet { bits: FixedBitSet::with_capacity(self.num_nodes) }
    }

    fn edge_index(&self, source: Node, target: Node) -> usize {
        (source.index * self.num_nodes) + target.index
    }

    pub fn set_weight(&mut self, source: Node, target: Node, w: Weight) {
        assert!(!w.is_max());
        let index = self.edge_index(source, target);
        self.weights[index] = w;
    }

    pub fn edge_weight(&self, source: Node, target: Node) -> Option<Weight> {
        let w = self.weights[self.edge_index(source, target)];
        if w.is_max() { None } else { Some(w) }
    }

    pub fn edges<'a>(&'a self, source: Node) -> impl Iterator<Item=Edge> {
        self.all_nodes()
            .filter_map(move |target| {
                self.edge_weight(source, target)
                    .map(|weight| {
                        Edge {
                            source: source,
                            target: target,
                            weight: weight,
                        }
                    })
            })
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Node {
    index: usize,
}

impl Node {
    pub fn new(index: usize) -> Node {
        Node { index: index }
    }

    pub fn index(&self) -> usize {
        self.index
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct Edge {
    pub source: Node,
    pub target: Node,
    pub weight: Weight,
}

#[derive(Clone, Debug)]
pub struct NodeSet {
    bits: FixedBitSet,
}

impl NodeSet {
    pub fn contains(&self, node: Node) -> bool {
        self.bits.contains(node.index)
    }

    pub fn with(&self, node: Node) -> NodeSet {
        let mut s = self.clone();
        s.insert(node);
        s
    }

    pub fn insert(&mut self, node: Node) {
        self.bits.set(node.index, true);
    }

    pub fn remove(&mut self, node: Node) {
        self.bits.set(node.index, false);
    }
}
<commit_msg>demo/tsp: impl Iterator needs a lifetime annotation<commit_after>use fixedbitset::FixedBitSet;
use std::iter;

use super::weight::Weight;

pub struct Graph {
    num_nodes: usize,

    // a 2-d matrix indexed by (source, target); if `Weight::max()`
    // is stored in a particular entry, that means that there is no
    // edge. Otherwise, the weight is found.
    weights: Vec<Weight>,
}

impl Graph {
    pub fn new(num_nodes: usize) -> Graph {
        Graph {
            num_nodes: num_nodes,
            weights: iter::repeat(Weight::max()).take(num_nodes * num_nodes).collect(),
        }
    }

    pub fn num_nodes(&self) -> usize {
        self.num_nodes
    }

    pub fn all_nodes(&self) -> impl Iterator<Item=Node> {
        (0..self.num_nodes).map(Node::new)
    }

    pub fn node_set(&self) -> NodeSet {
        NodeSet { bits: FixedBitSet::with_capacity(self.num_nodes) }
    }

    fn edge_index(&self, source: Node, target: Node) -> usize {
        (source.index * self.num_nodes) + target.index
    }

    pub fn set_weight(&mut self, source: Node, target: Node, w: Weight) {
        assert!(!w.is_max());
        let index = self.edge_index(source, target);
        self.weights[index] = w;
    }

    pub fn edge_weight(&self, source: Node, target: Node) -> Option<Weight> {
        let w = self.weights[self.edge_index(source, target)];
        if w.is_max() { None } else { Some(w) }
    }

    pub fn edges<'a>(&'a self, source: Node) -> impl Iterator<Item=Edge> + 'a {
        self.all_nodes()
            .filter_map(move |target| {
                self.edge_weight(source, target)
                    .map(|weight| {
                        Edge {
                            source: source,
                            target: target,
                            weight: weight,
                        }
                    })
            })
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Node {
    index: usize,
}

impl Node {
    pub fn new(index: usize) -> Node {
        Node { index: index }
    }

    pub fn index(&self) -> usize {
        self.index
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct Edge {
    pub source: Node,
    pub target: Node,
    pub weight: Weight,
}

#[derive(Clone, Debug)]
pub struct NodeSet {
    bits: FixedBitSet,
}

impl NodeSet {
    pub fn contains(&self, node: Node) -> bool {
        self.bits.contains(node.index)
    }

    pub fn with(&self, node: Node) -> NodeSet {
        let mut s = self.clone();
        s.insert(node);
        s
    }

    pub fn insert(&mut self, node: Node) {
        self.bits.set(node.index, true);
    }

    pub fn remove(&mut self, node: Node) {
        self.bits.set(node.index, false);
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syn::ItemEnum;

use super::{
    api::{AnalysisPhase, Api, ApiName, FuncToConvert, StructDetails, TypedefKind},
    apivec::ApiVec,
    convert_error::{ConvertErrorWithContext, ErrorContext},
    ConvertError,
};
use crate::{
    conversion::convert_error::ErrorContextType,
    types::{Namespace, QualifiedName},
};

/// Run some code which may generate a ConvertError.
/// If it does, try to note the problem in our output APIs
/// such that users will see documentation of the error.
pub(crate) fn report_any_error<F, T>(
    ns: &Namespace,
    apis: &mut ApiVec<impl AnalysisPhase>,
    fun: F,
) -> Option<T>
where
    F: FnOnce() -> Result<T, ConvertErrorWithContext>,
{
    match fun() {
        Ok(result) => Some(result),
        Err(ConvertErrorWithContext(err, None)) => {
            eprintln!("Ignored item: {}", err);
            None
        }
        Err(ConvertErrorWithContext(err, Some(ctx))) => {
            eprintln!("Ignored item {}: {}", ctx, err);
            let id = match ctx.get_type() {
                ErrorContextType::Item(id) | ErrorContextType::SanitizedItem(id) => id,
                ErrorContextType::Method { self_ty, .. } => self_ty,
            };
            let name = ApiName::new_from_qualified_name(QualifiedName::new(ns, id.clone()));
            apis.push(Api::IgnoredItem {
                name,
                err,
                ctx: Some(ctx),
            });
            None
        }
    }
}

/// Run some code which generates an API. Add that API, or if
/// anything goes wrong, instead add a note of the problem in our
/// output API such that users will see documentation for the problem.
pub(crate) fn convert_apis<FF, SF, EF, TF, A, B: 'static>(
    in_apis: ApiVec<A>,
    out_apis: &mut ApiVec<B>,
    mut func_conversion: FF,
    mut struct_conversion: SF,
    mut enum_conversion: EF,
    mut typedef_conversion: TF,
) where
    A: AnalysisPhase,
    B: AnalysisPhase,
    FF: FnMut(
        ApiName,
        Box<FuncToConvert>,
        A::FunAnalysis,
    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
    SF: FnMut(
        ApiName,
        Box<StructDetails>,
        A::StructAnalysis,
    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
    EF: FnMut(
        ApiName,
        ItemEnum,
    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
    TF: FnMut(
        ApiName,
        TypedefKind,
        Option<QualifiedName>,
        A::TypedefAnalysis,
    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
{
    out_apis.extend(in_apis.into_iter().flat_map(|api| {
        let fullname = api.name_info().clone();
        let result: Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext> = match api {
            // No changes to any of these...
            Api::ConcreteType {
                name,
                rs_definition,
                cpp_definition,
            } => Ok(Box::new(std::iter::once(Api::ConcreteType {
                name,
                rs_definition,
                cpp_definition,
            }))),
            Api::ForwardDeclaration { name } => {
                Ok(Box::new(std::iter::once(Api::ForwardDeclaration { name })))
            }
            Api::StringConstructor { name } => {
                Ok(Box::new(std::iter::once(Api::StringConstructor { name })))
            }
            Api::Const { name, const_item } => {
                Ok(Box::new(std::iter::once(Api::Const { name, const_item })))
            }
            Api::CType { name, typename } => {
                Ok(Box::new(std::iter::once(Api::CType { name, typename })))
            }
            Api::RustType { name, path } => {
                Ok(Box::new(std::iter::once(Api::RustType { name, path })))
            }
            Api::RustFn {
                name,
                details,
                receiver,
            } => Ok(Box::new(std::iter::once(Api::RustFn {
                name,
                details,
                receiver,
            }))),
            Api::RustSubclassFn {
                name,
                subclass,
                details,
            } => Ok(Box::new(std::iter::once(Api::RustSubclassFn {
                name,
                subclass,
                details,
            }))),
            Api::Subclass { name, superclass } => Ok(Box::new(std::iter::once(Api::Subclass {
                name,
                superclass,
            }))),
            Api::IgnoredItem { name, err, ctx } => {
                Ok(Box::new(std::iter::once(Api::IgnoredItem {
                    name,
                    err,
                    ctx,
                })))
            }
            Api::SubclassTraitItem { name, details } => {
                Ok(Box::new(std::iter::once(Api::SubclassTraitItem {
                    name,
                    details,
                })))
            }
            // Apply a mapping to the following
            Api::Enum { name, item } => enum_conversion(name, item),
            Api::Typedef {
                name,
                item,
                old_tyname,
                analysis,
            } => typedef_conversion(name, item, old_tyname, analysis),
            Api::Function {
                name,
                fun,
                analysis,
            } => func_conversion(name, fun, analysis),
            Api::Struct {
                name,
                details,
                analysis,
            } => struct_conversion(name, details, analysis),
        };
        api_or_error(fullname, result)
    }))
}

fn api_or_error<T: AnalysisPhase + 'static>(
    name: ApiName,
    api_or_error: Result<Box<dyn Iterator<Item = Api<T>>>, ConvertErrorWithContext>,
) -> Box<dyn Iterator<Item = Api<T>>> {
    match api_or_error {
        Ok(opt) => opt,
        Err(ConvertErrorWithContext(err, ctx)) => {
            eprintln!("Ignored {}: {}", name.cpp_name(), err);
            Box::new(std::iter::once(Api::IgnoredItem { name, err, ctx }))
        }
    }
}

/// Run some code which generates an API for an item (as opposed to
/// a method). Add that API, or if
/// anything goes wrong, instead add a note of the problem in our
/// output API such that users will see documentation for the problem.
pub(crate) fn convert_item_apis<F, A, B: 'static>(
    in_apis: ApiVec<A>,
    out_apis: &mut ApiVec<B>,
    mut fun: F,
) where
    F: FnMut(Api<A>) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertError>,
    A: AnalysisPhase,
    B: AnalysisPhase,
{
    out_apis.extend(in_apis.into_iter().flat_map(|api| {
        let fullname = api.name_info().clone();
        let tn = api.name().clone();
        let result = fun(api).map_err(|e| {
            ConvertErrorWithContext(e, Some(ErrorContext::new_for_item(tn.get_final_ident())))
        });
        api_or_error(fullname, result)
    }))
}
<commit_msg>Remove warning logging.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syn::ItemEnum;

use super::{
    api::{AnalysisPhase, Api, ApiName, FuncToConvert, StructDetails, TypedefKind},
    apivec::ApiVec,
    convert_error::{ConvertErrorWithContext, ErrorContext},
    ConvertError,
};
use crate::{
    conversion::convert_error::ErrorContextType,
    types::{Namespace, QualifiedName},
};

/// Run some code which may generate a ConvertError.
/// If it does, try to note the problem in our output APIs
/// such that users will see documentation of the error.
pub(crate) fn report_any_error<F, T>(
    ns: &Namespace,
    apis: &mut ApiVec<impl AnalysisPhase>,
    fun: F,
) -> Option<T>
where
    F: FnOnce() -> Result<T, ConvertErrorWithContext>,
{
    match fun() {
        Ok(result) => Some(result),
        Err(ConvertErrorWithContext(err, None)) => {
            eprintln!("Ignored item: {}", err);
            None
        }
        Err(ConvertErrorWithContext(err, Some(ctx))) => {
            let id = match ctx.get_type() {
                ErrorContextType::Item(id) | ErrorContextType::SanitizedItem(id) => id,
                ErrorContextType::Method { self_ty, .. } => self_ty,
            };
            let name = ApiName::new_from_qualified_name(QualifiedName::new(ns, id.clone()));
            apis.push(Api::IgnoredItem {
                name,
                err,
                ctx: Some(ctx),
            });
            None
        }
    }
}

/// Run some code which generates an API. Add that API, or if
/// anything goes wrong, instead add a note of the problem in our
/// output API such that users will see documentation for the problem.
pub(crate) fn convert_apis<FF, SF, EF, TF, A, B: 'static>(
    in_apis: ApiVec<A>,
    out_apis: &mut ApiVec<B>,
    mut func_conversion: FF,
    mut struct_conversion: SF,
    mut enum_conversion: EF,
    mut typedef_conversion: TF,
) where
    A: AnalysisPhase,
    B: AnalysisPhase,
    FF: FnMut(
        ApiName,
        Box<FuncToConvert>,
        A::FunAnalysis,
    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
    SF: FnMut(
        ApiName,
        Box<StructDetails>,
        A::StructAnalysis,
    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
    EF: FnMut(
        ApiName,
        ItemEnum,
    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
    TF: FnMut(
        ApiName,
        TypedefKind,
        Option<QualifiedName>,
        A::TypedefAnalysis,
    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
{
    out_apis.extend(in_apis.into_iter().flat_map(|api| {
        let fullname = api.name_info().clone();
        let result: Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext> = match api {
            // No changes to any of these...
            Api::ConcreteType {
                name,
                rs_definition,
                cpp_definition,
            } => Ok(Box::new(std::iter::once(Api::ConcreteType {
                name,
                rs_definition,
                cpp_definition,
            }))),
            Api::ForwardDeclaration { name } => {
                Ok(Box::new(std::iter::once(Api::ForwardDeclaration { name })))
            }
            Api::StringConstructor { name } => {
                Ok(Box::new(std::iter::once(Api::StringConstructor { name })))
            }
            Api::Const { name, const_item } => {
                Ok(Box::new(std::iter::once(Api::Const { name, const_item })))
            }
            Api::CType { name, typename } => {
                Ok(Box::new(std::iter::once(Api::CType { name, typename })))
            }
            Api::RustType { name, path } => {
                Ok(Box::new(std::iter::once(Api::RustType { name, path })))
            }
            Api::RustFn {
                name,
                details,
                receiver,
            } => Ok(Box::new(std::iter::once(Api::RustFn {
                name,
                details,
                receiver,
            }))),
            Api::RustSubclassFn {
                name,
                subclass,
                details,
            } => Ok(Box::new(std::iter::once(Api::RustSubclassFn {
                name,
                subclass,
                details,
            }))),
            Api::Subclass { name, superclass } => Ok(Box::new(std::iter::once(Api::Subclass {
                name,
                superclass,
            }))),
            Api::IgnoredItem { name, err, ctx } => {
                Ok(Box::new(std::iter::once(Api::IgnoredItem {
                    name,
                    err,
                    ctx,
                })))
            }
            Api::SubclassTraitItem { name, details } => {
                Ok(Box::new(std::iter::once(Api::SubclassTraitItem {
                    name,
                    details,
                })))
            }
            // Apply a mapping to the following
            Api::Enum { name, item } => enum_conversion(name, item),
            Api::Typedef {
                name,
                item,
                old_tyname,
                analysis,
            } => typedef_conversion(name, item, old_tyname, analysis),
            Api::Function {
                name,
                fun,
                analysis,
            } => func_conversion(name, fun, analysis),
            Api::Struct {
                name,
                details,
                analysis,
            } => struct_conversion(name, details, analysis),
        };
        api_or_error(fullname, result)
    }))
}

fn api_or_error<T: AnalysisPhase + 'static>(
    name: ApiName,
    api_or_error: Result<Box<dyn Iterator<Item = Api<T>>>, ConvertErrorWithContext>,
) -> Box<dyn Iterator<Item = Api<T>>> {
    match api_or_error {
        Ok(opt) => opt,
        Err(ConvertErrorWithContext(err, ctx)) => {
            Box::new(std::iter::once(Api::IgnoredItem { name, err, ctx }))
        }
    }
}

/// Run some code which generates an API for an item (as opposed to
/// a method). Add that API, or if
/// anything goes wrong, instead add a note of the problem in our
/// output API such that users will see documentation for the problem.
pub(crate) fn convert_item_apis<F, A, B: 'static>(
    in_apis: ApiVec<A>,
    out_apis: &mut ApiVec<B>,
    mut fun: F,
) where
    F: FnMut(Api<A>) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertError>,
    A: AnalysisPhase,
    B: AnalysisPhase,
{
    out_apis.extend(in_apis.into_iter().flat_map(|api| {
        let fullname = api.name_info().clone();
        let tn = api.name().clone();
        let result = fun(api).map_err(|e| {
            ConvertErrorWithContext(e, Some(ErrorContext::new_for_item(tn.get_final_ident())))
        });
        api_or_error(fullname, result)
    }))
}
<|endoftext|>


<commit_before><commit_msg>Assert non-negative block offsets<commit_after><|endoftext|>


<commit_before>use super::handle::HandleLike;
use super::handle_pool::HandlePool;

/// A named object collections. Every time u create or free a handle, a
/// attached instance `T` will be created/ freed.
#[derive(Default)]
pub struct ObjectPool<H: HandleLike, T: Sized> {
    handles: HandlePool<H>,
    entries: Vec<T>,
}

impl<H: HandleLike, T: Sized> ObjectPool<H, T> {
    /// Constructs a new, empty `ObjectPool`.
    pub fn new() -> Self {
        ObjectPool {
            handles: HandlePool::new(),
            entries: Vec::new(),
        }
    }

    /// Constructs a new `ObjectPool` with the specified capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        ObjectPool {
            handles: HandlePool::with_capacity(capacity),
            entries: Vec::with_capacity(capacity),
        }
    }

    /// Creates a `T` and named it with `Handle`.
    pub fn create(&mut self, value: T) -> H {
        let handle = self.handles.create();

        if handle.index() >= self.entries.len() as u32 {
            self.entries.push(value);
        } else {
            self.entries[handle.index() as usize] = value;
        }

        handle
    }

    /// Returns mutable reference to internal value with name `Handle`.
    #[inline]
    pub fn get_mut(&mut self, handle: H) -> Option<&mut T> {
        if self.handles.contains(handle) {
            unsafe { Some(self.entries.get_unchecked_mut(handle.index() as usize)) }
        } else {
            None
        }
    }

    /// Returns immutable reference to internal value with name `Handle`.
    #[inline]
    pub fn get(&self, handle: H) -> Option<&T> {
        if self.handles.contains(handle) {
            unsafe { Some(self.entries.get_unchecked(handle.index() as usize)) }
        } else {
            None
        }
    }

    /// Returns true if this `Handle` was created by `ObjectPool`, and has not been
    /// freed yet.
    #[inline]
    pub fn contains(&self, handle: H) -> bool {
        self.handles.contains(handle)
    }

    /// Recycles the value with name `Handle`.
    #[inline]
    pub fn free(&mut self, handle: H) -> Option<T> {
        if self.handles.free(handle) {
            unsafe {
                let mut v = ::std::mem::uninitialized();
                ::std::mem::swap(&mut v, &mut self.entries[handle.index() as usize]);
                Some(v)
            }
        } else {
            None
        }
    }

    /// Retains only the elements specified by the predicate.
    ///
    /// In other words, remove all objects such that f(k, &mut v) returns false.
    pub fn retain<P>(&mut self, mut predicate: P)
    where
        P: FnMut(H, &mut T) -> bool,
    {
        let entries = &mut self.entries;
        self.handles.retain(|handle| unsafe {
            let mut v = entries.get_unchecked_mut(handle.index() as usize);
            if predicate(handle, v) {
                true
            } else {
                let mut w = ::std::mem::uninitialized();
                ::std::mem::swap(&mut v, &mut w);
                false
            }
        });
    }

    /// Returns the total number of alive handle in this `ObjectPool`.
    #[inline]
    pub fn len(&self) -> usize {
        self.handles.len()
    }

    /// Checks if the pool is empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// an iterator visiting all key-value pairs in order. the iterator element type is (h, &t).
    #[inline]
    pub fn iter<'a>(&'a self) -> impl Iterator<Item = (H, &T)> + 'a {
        self.handles
            .iter()
            .map(move |v| unsafe { (v, self.entries.get_unchecked(v.index() as usize)) })
    }

    /// an iterator visiting all key-value pairs in order. the iterator element type is (h, &mut t).
    #[inline]
    pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = (H, &'a mut T)> {
        let entries = &mut self.entries;
        self.handles.iter().map(move |v| unsafe {
            let w = entries.get_unchecked_mut(v.index() as usize);
            (v, &mut *(w as *mut T))
        })
    }

    /// An iterator visiting all keys in order. The iterator element type is H.
    #[inline]
    pub fn keys<'a>(&'a self) -> impl Iterator<Item = H> + 'a {
        self.handles.iter()
    }

    /// An iterator visiting all entries in order. The iterator element type is &T.
    #[inline]
    pub fn values<'a>(&'a self) -> impl Iterator<Item = &T> + 'a {
        self.handles
            .iter()
            .map(move |v| unsafe { self.entries.get_unchecked(v.index() as usize) })
    }

    /// An iterator visiting all entries in order. The iterator element type is &mut T.
    #[inline]
    pub fn values_mut<'a>(&'a mut self) -> impl Iterator<Item = &mut T> + 'a {
        let entries = &mut self.entries;
        self.handles.iter().map(move |v| unsafe {
            let w = entries.get_unchecked_mut(v.index() as usize);
            &mut *(w as *mut T)
        })
    }
}

impl<H: HandleLike, T: Sized> Drop for ObjectPool<H, T> {
    fn drop(&mut self) {
        unsafe {
            for v in &self.handles {
                ::std::ptr::drop_in_place(&mut self.entries[v.index() as usize]);
            }

            self.entries.set_len(0);
        }
    }
}
<commit_msg>Addressed a unexpected `drop` on uninitialized value in `ObjectPool`.<commit_after>use super::handle::HandleLike;
use super::handle_pool::HandlePool;

/// A named object collections. Every time u create or free a handle, a
/// attached instance `T` will be created/ freed.
#[derive(Default)]
pub struct ObjectPool<H: HandleLike, T: Sized> {
    handles: HandlePool<H>,
    entries: Vec<T>,
}

impl<H: HandleLike, T: Sized> ObjectPool<H, T> {
    /// Constructs a new, empty `ObjectPool`.
    pub fn new() -> Self {
        ObjectPool {
            handles: HandlePool::new(),
            entries: Vec::new(),
        }
    }

    /// Constructs a new `ObjectPool` with the specified capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        ObjectPool {
            handles: HandlePool::with_capacity(capacity),
            entries: Vec::with_capacity(capacity),
        }
    }

    /// Creates a `T` and named it with `Handle`.
    pub fn create(&mut self, mut value: T) -> H {
        let handle = self.handles.create();

        if handle.index() >= self.entries.len() as u32 {
            self.entries.push(value);
        } else {
            ::std::mem::swap(&mut value, &mut self.entries[handle.index() as usize]);
            ::std::mem::forget(value);
        }

        handle
    }

    /// Returns mutable reference to internal value with name `Handle`.
    #[inline]
    pub fn get_mut(&mut self, handle: H) -> Option<&mut T> {
        if self.handles.contains(handle) {
            unsafe { Some(self.entries.get_unchecked_mut(handle.index() as usize)) }
        } else {
            None
        }
    }

    /// Returns immutable reference to internal value with name `Handle`.
    #[inline]
    pub fn get(&self, handle: H) -> Option<&T> {
        if self.handles.contains(handle) {
            unsafe { Some(self.entries.get_unchecked(handle.index() as usize)) }
        } else {
            None
        }
    }

    /// Returns true if this `Handle` was created by `ObjectPool`, and has not been
    /// freed yet.
    #[inline]
    pub fn contains(&self, handle: H) -> bool {
        self.handles.contains(handle)
    }

    /// Recycles the value with name `Handle`.
    #[inline]
    pub fn free(&mut self, handle: H) -> Option<T> {
        if self.handles.free(handle) {
            unsafe {
                let mut v = ::std::mem::uninitialized();
                ::std::mem::swap(&mut v, &mut self.entries[handle.index() as usize]);
                Some(v)
            }
        } else {
            None
        }
    }

    /// Retains only the elements specified by the predicate.
    ///
    /// In other words, remove all objects such that f(k, &mut v) returns false.
    pub fn retain<P>(&mut self, mut predicate: P)
    where
        P: FnMut(H, &mut T) -> bool,
    {
        let entries = &mut self.entries;
        self.handles.retain(|handle| unsafe {
            let mut v = entries.get_unchecked_mut(handle.index() as usize);
            if predicate(handle, v) {
                true
            } else {
                let mut w = ::std::mem::uninitialized();
                ::std::mem::swap(&mut v, &mut w);
                false
            }
        });
    }

    /// Returns the total number of alive handle in this `ObjectPool`.
    #[inline]
    pub fn len(&self) -> usize {
        self.handles.len()
    }

    /// Checks if the pool is empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// an iterator visiting all key-value pairs in order. the iterator element type is (h, &t).
    #[inline]
    pub fn iter<'a>(&'a self) -> impl Iterator<Item = (H, &T)> + 'a {
        self.handles
            .iter()
            .map(move |v| unsafe { (v, self.entries.get_unchecked(v.index() as usize)) })
    }

    /// an iterator visiting all key-value pairs in order. the iterator element type is (h, &mut t).
    #[inline]
    pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = (H, &'a mut T)> {
        let entries = &mut self.entries;
        self.handles.iter().map(move |v| unsafe {
            let w = entries.get_unchecked_mut(v.index() as usize);
            (v, &mut *(w as *mut T))
        })
    }

    /// An iterator visiting all keys in order. The iterator element type is H.
    #[inline]
    pub fn keys<'a>(&'a self) -> impl Iterator<Item = H> + 'a {
        self.handles.iter()
    }

    /// An iterator visiting all entries in order. The iterator element type is &T.
    #[inline]
    pub fn values<'a>(&'a self) -> impl Iterator<Item = &T> + 'a {
        self.handles
            .iter()
            .map(move |v| unsafe { self.entries.get_unchecked(v.index() as usize) })
    }

    /// An iterator visiting all entries in order. The iterator element type is &mut T.
    #[inline]
    pub fn values_mut<'a>(&'a mut self) -> impl Iterator<Item = &mut T> + 'a {
        let entries = &mut self.entries;
        self.handles.iter().map(move |v| unsafe {
            let w = entries.get_unchecked_mut(v.index() as usize);
            &mut *(w as *mut T)
        })
    }
}

impl<H: HandleLike, T: Sized> Drop for ObjectPool<H, T> {
    fn drop(&mut self) {
        unsafe {
            for v in &self.handles {
                ::std::ptr::drop_in_place(&mut self.entries[v.index() as usize]);
            }

            self.entries.set_len(0);
        }
    }
}
<|endoftext|>