<commit_before>use super::{ParallelIterator, ExactParallelIterator};

use std::collections::HashMap;
use std::hash::Hash;
use std::collections::LinkedList;

pub trait FromParIter<PAR_ITER> {
    fn from_par_iter(par_iter: PAR_ITER) -> Self;
}

/// Collect items from a parallel iterator into a freshly allocated
/// vector. This is very efficient, but requires precise knowledge of
/// the number of items being iterated.
impl<PAR_ITER, T> FromParIter<PAR_ITER> for Vec<T>
    where PAR_ITER: ExactParallelIterator<Item=T>,
          T: Send,
{
    fn from_par_iter(par_iter: PAR_ITER) -> Self {
        let mut vec = vec![];
        par_iter.collect_into(&mut vec);
        vec
    }
}

/// Collect items from a parallel iterator into a freshly allocated
/// linked list.
impl<PAR_ITER, T> FromParIter<PAR_ITER> for LinkedList<T>
    where PAR_ITER: ParallelIterator<Item=T>,
          T: Send,
{
    fn from_par_iter(par_iter: PAR_ITER) -> Self {
        par_iter.map(|elem| { let mut list = LinkedList::new(); list.push_back(elem); list })
                .reduce_with(|mut list1, mut list2| { list1.append(&mut list2); list1 })
                .unwrap_or_else(|| LinkedList::new())
    }
}

/// Collect items from a parallel iterator into a hashmap. To some
/// extent, a proof of concept, since it requires an intermediate
/// allocation into a vector at the moment.
impl<PAR_ITER, K: Eq + Hash, V> FromParIter<PAR_ITER> for HashMap<K, V>
    where PAR_ITER: ExactParallelIterator<Item=(K, V)>,
          (K, V): Send,
{
    fn from_par_iter(par_iter: PAR_ITER) -> Self {
        let vec: Vec<(K, V)> = par_iter.collect();
        vec.into_iter().collect()
    }
}
<commit_msg>convert map to use linked list instead<commit_after>use super::{ParallelIterator, ExactParallelIterator};

use std::collections::HashMap;
use std::hash::Hash;
use std::collections::LinkedList;

pub trait FromParIter<PAR_ITER> {
    fn from_par_iter(par_iter: PAR_ITER) -> Self;
}

/// Collect items from a parallel iterator into a freshly allocated
/// vector. This is very efficient, but requires precise knowledge of
/// the number of items being iterated.
impl<PAR_ITER, T> FromParIter<PAR_ITER> for Vec<T>
    where PAR_ITER: ExactParallelIterator<Item=T>,
          T: Send,
{
    fn from_par_iter(par_iter: PAR_ITER) -> Self {
        let mut vec = vec![];
        par_iter.collect_into(&mut vec);
        vec
    }
}

/// Collect items from a parallel iterator into a freshly allocated
/// linked list.
impl<PAR_ITER, T> FromParIter<PAR_ITER> for LinkedList<T>
    where PAR_ITER: ParallelIterator<Item=T>,
          T: Send,
{
    fn from_par_iter(par_iter: PAR_ITER) -> Self {
        par_iter.map(|elem| { let mut list = LinkedList::new(); list.push_back(elem); list })
                .reduce_with(|mut list1, mut list2| { list1.append(&mut list2); list1 })
                .unwrap_or_else(|| LinkedList::new())
    }
}

/// Collect (key, value) pairs from a parallel iterator into a
/// hashmap.  If multiple pairs correspond to the same key, then the
/// ones produced earlier in the parallel iterator will be
/// overwritten, just as with a sequential iterator.
impl<PAR_ITER, K: Eq + Hash, V> FromParIter<PAR_ITER> for HashMap<K, V>
    where PAR_ITER: ParallelIterator<Item=(K, V)>,
          (K, V): Send,
{
    fn from_par_iter(par_iter: PAR_ITER) -> Self {
        let vec: LinkedList<(K, V)> = par_iter.collect();
        vec.into_iter().collect()
    }
}
<|endoftext|>


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

use arc = std::arc;
use arc::ARC;
use au = gfx::geometry;
use au::au;
use core::dvec::DVec;
use core::to_str::ToStr;
use core::rand;
use css::styles::SpecifiedStyle;
use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColorTransparent};
use dl = gfx::display_list;
use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement};
use dom::node::{Element, Node, NodeData, NodeKind, NodeTree};
use geom::rect::Rect;
use geom::size::Size2D;
use geom::point::Point2D;
use image::{Image, ImageHolder};
use layout::context::LayoutContext;
use layout::debug::BoxedDebugMethods;
use layout::flow::FlowContext;
use layout::text::TextBoxData;
use servo_text::text_run::TextRun;
use std::net::url::Url;
use task::spawn;
use util::color::Color;
use util::tree;
use vec::{push, push_all};

/**
Render boxes (`struct RenderBox`) are the leafs of the layout
tree. They cannot position themselves. In general, render boxes do not
have a simple correspondence with CSS boxes as in the specification:

 * Several render boxes may correspond to the same CSS box or DOM
   node. For example, a CSS text box broken across two lines is
   represented by two render boxes.

 * Some CSS boxes are not created at all, such as some anonymous block
   boxes induced by inline boxes with block-level sibling boxes. In
   that case, Servo uses an InlineFlow with BlockFlow siblings; the
   InlineFlow is block-level, but not a block container. It is
   positioned as if it were a block box, but its children are
   positioned according to inline flow.

Fundamental box types include:

 * GenericBox: an empty box that contributes only borders, margins,
padding, backgrounds. It is analogous to a CSS nonreplaced content box.

 * ImageBox: a box that represents a (replaced content) image and its
   accompanying borders, shadows, etc.

 * TextBox: a box representing a single run of text with a distinct
   style. A TextBox may be split into two or more render boxes across
   line breaks. Several TextBoxes may correspond to a single DOM text
   node. Split text boxes are implemented by referring to subsets of a
   master TextRun object.

*/

/* 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 RenderBoxData {
    /* originating DOM node */
    node : Node,
    /* reference to containing flow context, which this box
       participates in */
    ctx  : @FlowContext,
    /* position of this box relative to owning flow */
    mut position : Rect<au>,
    font_size : Length,
    /* TODO (Issue #87): debug only */
    mut id: int
}

enum RenderBoxType {
    RenderBox_Generic,
    RenderBox_Image,
    RenderBox_Text,
}

pub enum RenderBox {
    GenericBox(RenderBoxData),
    ImageBox(RenderBoxData, ImageHolder),
    TextBox(RenderBoxData, TextBoxData),
    UnscannedTextBox(RenderBoxData, ~str)
}

enum InlineSpacerSide {
    LogicalBefore,
    LogicalAfter,
}

trait RenderBoxMethods {
    pure fn d(&self) -> &self/RenderBoxData;

    pure fn is_replaced() -> bool;
    pure fn can_split() -> bool;
    pure fn can_merge_with_box(@self, other: @RenderBox) -> bool;
    pure fn requires_inline_spacers() -> bool;
    pure fn content_box() -> Rect<au>;
    pure fn border_box() -> Rect<au>;

    fn get_min_width(&LayoutContext) -> au;
    fn get_pref_width(&LayoutContext) -> au;
    fn get_used_width() -> (au, au);
    fn get_used_height() -> (au, au);
    fn create_inline_spacer_for_side(&LayoutContext, InlineSpacerSide) -> Option<@RenderBox>;
    fn build_display_list(&dl::DisplayListBuilder, dirty: &Rect<au>,
                          offset: &Point2D<au>, &dl::DisplayList);
}

fn RenderBoxData(node: Node, ctx: @FlowContext, id: int) -> RenderBoxData {
    RenderBoxData {
        node : node,
        mut ctx  : ctx,
        mut position : au::zero_rect(),
        font_size: Px(0.0),
        id : id
    }
}

impl RenderBox : RenderBoxMethods {
    pure fn d(&self) -> &self/RenderBoxData {
        match *self {
            GenericBox(ref d)  => d,
            ImageBox(ref d, _) => d,
            TextBox(ref d, _)  => d,
            UnscannedTextBox(ref d, _) => d,
        }
    }

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

    pure fn can_split() -> bool {
        match self {
            TextBox(*) => true,
            _ => false
        }
    }

    pure fn can_merge_with_box(@self, other: @RenderBox) -> bool {
        assert !core::box::ptr_eq(self, other);

        match (self, other) {
            (@UnscannedTextBox(*), @UnscannedTextBox(*)) => true,
            (@TextBox(_,d1), @TextBox(_,d2)) => { core::box::ptr_eq(d1.run, d2.run) }
            (_, _) => false
        }
    }

    /** In general, these functions are transitively impure because they
     * may cause glyphs to be allocated. For now, it's impure because of
     * holder.get_image()
    */
    fn get_min_width(ctx: &LayoutContext) -> au {
        match self {
            // 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: consult CSS 'width', margin, border.
            // TODO: If image isn't available, consult 'width'.
            ImageBox(_,i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),
            TextBox(_,d) => d.run.min_width_for_range(ctx, d.offset, d.length),
            UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here."
        }
    }

    fn get_pref_width(_ctx: &LayoutContext) -> au {
        match self {
            // 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),
            ImageBox(_,i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),

            // a text box cannot span lines, so assume that this is an unsplit text box.

            // TODO: If text boxes have been split to wrap lines, then
            // they could report a smaller pref width during incremental reflow.
            // maybe text boxes should report nothing, and the parent flow could
            // factor in min/pref widths of any text runs that it owns.
            TextBox(_,d) => {
                let mut max_line_width: au = au(0);
                do d.run.iter_natural_lines_for_range(d.offset, d.length) |line_offset, line_len| {
                    let mut line_width: au = au(0);
                    do d.run.glyphs.iter_glyphs_for_range(line_offset, line_len) |_char_i, glyph| {
                        line_width += glyph.advance()
                    };

                    if max_line_width < line_width {
                        max_line_width = line_width;
                    };
                    true
                }

                max_line_width
            },
            UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here."
        }
    }

    /* 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))
    }

    /* Whether "spacer" boxes are needed to stand in for this DOM node */
    pure fn requires_inline_spacers() -> bool {
        return false;
    }

    /* The box formed by the content edge, as defined in CSS 2.1 Section 8.1.
       Coordinates are relative to the owning flow. */
    pure fn content_box() -> Rect<au> {
        match self {
            ImageBox(_,i) => {
                let size = i.size();
                Rect {
                    origin: copy self.d().position.origin,
                    size:   Size2D(au::from_px(size.width),
                                   au::from_px(size.height))
                }
            },
            GenericBox(*) => {
                copy self.d().position
                /* FIXME: The following hits an ICE for whatever reason

                let origin = self.d().position.origin;
                let size   = self.d().position.size;
                let (offset_left, offset_right) = self.get_used_width();
                let (offset_top, offset_bottom) = self.get_used_height();

                Rect {
                    origin: Point2D(origin.x + offset_left, origin.y + offset_top),
                    size:   Size2D(size.width - (offset_left + offset_right),
                                   size.height - (offset_top + offset_bottom))
                }*/
            },
            TextBox(*) => {
                copy self.d().position
            },
            UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here."
        }
    }

    /* The box formed by the border edge, as defined in CSS 2.1 Section 8.1.
       Coordinates are relative to the owning flow. */
    pure fn border_box() -> Rect<au> {
        // TODO: actually compute content_box + padding + border
        self.content_box()
    }

    // TODO: implement this, generating spacer
    fn create_inline_spacer_for_side(_ctx: &LayoutContext, _side: InlineSpacerSide) -> Option<@RenderBox> {
        None
    }

    // TODO: to implement stacking contexts correctly, we need to
    // create a set of display lists, one per each layer of a stacking
    // context. (CSS 2.1, Section 9.9.1). Each box is passed the list
    // set representing the box's stacking context. When asked to
    // construct its constituent display items, each box puts its
    // DisplayItems into the correct stack layer (according to CSS 2.1
    // Appendix E).  and then builder flattens the list at the end.

    /* Methods for building a display list. This is a good candidate
       for a function pointer as the number of boxes explodes.

    # Arguments

    * `builder` - the display list builder which manages the coordinate system and options.
    * `dirty` - Dirty rectangle, in the coordinate system of the owning flow (self.ctx)
    * `origin` - Total offset from display list root flow to this box's owning flow
    * `list` - List to which items should be appended
    */
    fn build_display_list(_builder: &dl::DisplayListBuilder, dirty: &Rect<au>,
                          offset: &Point2D<au>, list: &dl::DisplayList) {
        if !self.d().position.intersects(dirty) {
            return;
        }

        let bounds : Rect<au> = Rect(self.d().position.origin.add(offset),
                                     copy self.d().position.size);

        match self {
            UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here.",
            TextBox(_,d) => {
                list.push(~dl::Text(bounds, ~(copy *d.run), d.offset, d.length))
            },
            // TODO: items for background, border, outline
            GenericBox(*) => { },
            ImageBox(_,i) => {
                match i.get_image() {
                    Some(image) => list.push(~dl::Image(bounds, arc::clone(&image))),
                    /* No image data at all? Okay, add some fallback content instead. */
                    None => {
                        // TODO: shouldn't need to unbox CSSValue by now
                        let boxed_color = self.d().node.style().background_color;
                        let color = match boxed_color {
                            Specified(BgColor(c)) => c,
                            Specified(BgColorTransparent) | _ => util::color::rgba(0,0,0,0.0)
                        };
                        list.push(~dl::SolidColor(bounds, color.red, color.green, color.blue));
                    }
                }
            }
        }
    }
}

impl RenderBox : BoxedDebugMethods {
    fn dump(@self) {
        self.dump_indent(0u);
    }

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

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

    fn debug_str(@self) -> ~str {
        let repr = match self {
            @GenericBox(*) => ~"GenericBox",
            @ImageBox(*) => ~"ImageBox",
            @TextBox(_,d) => fmt!("TextBox(text=%s)", str::substr(d.run.text, d.offset, d.length)),
            @UnscannedTextBox(_,s) => fmt!("UnscannedTextBox(%s)", s)
        };

        fmt!("box b%?: %?", self.d().id, repr)
    }
}
<commit_msg>add RenderBox::is_whitespace()<commit_after>/* Fundamental layout structures and algorithms. */

use arc = std::arc;
use arc::ARC;
use au = gfx::geometry;
use au::au;
use core::dvec::DVec;
use core::to_str::ToStr;
use core::rand;
use css::styles::SpecifiedStyle;
use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColorTransparent};
use dl = gfx::display_list;
use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement};
use dom::node::{Element, Node, NodeData, NodeKind, NodeTree};
use geom::rect::Rect;
use geom::size::Size2D;
use geom::point::Point2D;
use image::{Image, ImageHolder};
use layout::context::LayoutContext;
use layout::debug::BoxedDebugMethods;
use layout::flow::FlowContext;
use layout::text::TextBoxData;
use servo_text::text_run::TextRun;
use std::net::url::Url;
use task::spawn;
use util::color::Color;
use util::tree;
use vec::{push, push_all};

/**
Render boxes (`struct RenderBox`) are the leafs of the layout
tree. They cannot position themselves. In general, render boxes do not
have a simple correspondence with CSS boxes as in the specification:

 * Several render boxes may correspond to the same CSS box or DOM
   node. For example, a CSS text box broken across two lines is
   represented by two render boxes.

 * Some CSS boxes are not created at all, such as some anonymous block
   boxes induced by inline boxes with block-level sibling boxes. In
   that case, Servo uses an InlineFlow with BlockFlow siblings; the
   InlineFlow is block-level, but not a block container. It is
   positioned as if it were a block box, but its children are
   positioned according to inline flow.

Fundamental box types include:

 * GenericBox: an empty box that contributes only borders, margins,
padding, backgrounds. It is analogous to a CSS nonreplaced content box.

 * ImageBox: a box that represents a (replaced content) image and its
   accompanying borders, shadows, etc.

 * TextBox: a box representing a single run of text with a distinct
   style. A TextBox may be split into two or more render boxes across
   line breaks. Several TextBoxes may correspond to a single DOM text
   node. Split text boxes are implemented by referring to subsets of a
   master TextRun object.

*/

/* 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 RenderBoxData {
    /* originating DOM node */
    node : Node,
    /* reference to containing flow context, which this box
       participates in */
    ctx  : @FlowContext,
    /* position of this box relative to owning flow */
    mut position : Rect<au>,
    font_size : Length,
    /* TODO (Issue #87): debug only */
    mut id: int
}

enum RenderBoxType {
    RenderBox_Generic,
    RenderBox_Image,
    RenderBox_Text,
}

pub enum RenderBox {
    GenericBox(RenderBoxData),
    ImageBox(RenderBoxData, ImageHolder),
    TextBox(RenderBoxData, TextBoxData),
    UnscannedTextBox(RenderBoxData, ~str)
}

enum InlineSpacerSide {
    LogicalBefore,
    LogicalAfter,
}

trait RenderBoxMethods {
    pure fn d(&self) -> &self/RenderBoxData;

    pure fn is_replaced() -> bool;
    pure fn can_split() -> bool;
    pure fn is_whitespace_only() -> bool;
    pure fn can_merge_with_box(@self, other: @RenderBox) -> bool;
    pure fn requires_inline_spacers() -> bool;
    pure fn content_box() -> Rect<au>;
    pure fn border_box() -> Rect<au>;

    fn get_min_width(&LayoutContext) -> au;
    fn get_pref_width(&LayoutContext) -> au;
    fn get_used_width() -> (au, au);
    fn get_used_height() -> (au, au);
    fn create_inline_spacer_for_side(&LayoutContext, InlineSpacerSide) -> Option<@RenderBox>;
    fn build_display_list(&dl::DisplayListBuilder, dirty: &Rect<au>,
                          offset: &Point2D<au>, &dl::DisplayList);
}

fn RenderBoxData(node: Node, ctx: @FlowContext, id: int) -> RenderBoxData {
    RenderBoxData {
        node : node,
        mut ctx  : ctx,
        mut position : au::zero_rect(),
        font_size: Px(0.0),
        id : id
    }
}

impl RenderBox : RenderBoxMethods {
    pure fn d(&self) -> &self/RenderBoxData {
        match *self {
            GenericBox(ref d)  => d,
            ImageBox(ref d, _) => d,
            TextBox(ref d, _)  => d,
            UnscannedTextBox(ref d, _) => d,
        }
    }

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

    pure fn can_split() -> bool {
        match self {
            TextBox(*) => true,
            _ => false
        }
    }

    pure fn is_whitespace_only() -> bool {
        match self {
            UnscannedTextBox(_, raw_text) => raw_text.is_whitespace(),
            _ => false
        }
    }

    pure fn can_merge_with_box(@self, other: @RenderBox) -> bool {
        assert !core::box::ptr_eq(self, other);

        match (self, other) {
            (@UnscannedTextBox(*), @UnscannedTextBox(*)) => true,
            (@TextBox(_,d1), @TextBox(_,d2)) => { core::box::ptr_eq(d1.run, d2.run) }
            (_, _) => false
        }
    }

    /** In general, these functions are transitively impure because they
     * may cause glyphs to be allocated. For now, it's impure because of
     * holder.get_image()
    */
    fn get_min_width(ctx: &LayoutContext) -> au {
        match self {
            // 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: consult CSS 'width', margin, border.
            // TODO: If image isn't available, consult 'width'.
            ImageBox(_,i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),
            TextBox(_,d) => d.run.min_width_for_range(ctx, d.offset, d.length),
            UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here."
        }
    }

    fn get_pref_width(_ctx: &LayoutContext) -> au {
        match self {
            // 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),
            ImageBox(_,i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),

            // a text box cannot span lines, so assume that this is an unsplit text box.

            // TODO: If text boxes have been split to wrap lines, then
            // they could report a smaller pref width during incremental reflow.
            // maybe text boxes should report nothing, and the parent flow could
            // factor in min/pref widths of any text runs that it owns.
            TextBox(_,d) => {
                let mut max_line_width: au = au(0);
                do d.run.iter_natural_lines_for_range(d.offset, d.length) |line_offset, line_len| {
                    let mut line_width: au = au(0);
                    do d.run.glyphs.iter_glyphs_for_range(line_offset, line_len) |_char_i, glyph| {
                        line_width += glyph.advance()
                    };

                    if max_line_width < line_width {
                        max_line_width = line_width;
                    };
                    true
                }

                max_line_width
            },
            UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here."
        }
    }

    /* 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))
    }

    /* Whether "spacer" boxes are needed to stand in for this DOM node */
    pure fn requires_inline_spacers() -> bool {
        return false;
    }

    /* The box formed by the content edge, as defined in CSS 2.1 Section 8.1.
       Coordinates are relative to the owning flow. */
    pure fn content_box() -> Rect<au> {
        match self {
            ImageBox(_,i) => {
                let size = i.size();
                Rect {
                    origin: copy self.d().position.origin,
                    size:   Size2D(au::from_px(size.width),
                                   au::from_px(size.height))
                }
            },
            GenericBox(*) => {
                copy self.d().position
                /* FIXME: The following hits an ICE for whatever reason

                let origin = self.d().position.origin;
                let size   = self.d().position.size;
                let (offset_left, offset_right) = self.get_used_width();
                let (offset_top, offset_bottom) = self.get_used_height();

                Rect {
                    origin: Point2D(origin.x + offset_left, origin.y + offset_top),
                    size:   Size2D(size.width - (offset_left + offset_right),
                                   size.height - (offset_top + offset_bottom))
                }*/
            },
            TextBox(*) => {
                copy self.d().position
            },
            UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here."
        }
    }

    /* The box formed by the border edge, as defined in CSS 2.1 Section 8.1.
       Coordinates are relative to the owning flow. */
    pure fn border_box() -> Rect<au> {
        // TODO: actually compute content_box + padding + border
        self.content_box()
    }

    // TODO: implement this, generating spacer
    fn create_inline_spacer_for_side(_ctx: &LayoutContext, _side: InlineSpacerSide) -> Option<@RenderBox> {
        None
    }

    // TODO: to implement stacking contexts correctly, we need to
    // create a set of display lists, one per each layer of a stacking
    // context. (CSS 2.1, Section 9.9.1). Each box is passed the list
    // set representing the box's stacking context. When asked to
    // construct its constituent display items, each box puts its
    // DisplayItems into the correct stack layer (according to CSS 2.1
    // Appendix E).  and then builder flattens the list at the end.

    /* Methods for building a display list. This is a good candidate
       for a function pointer as the number of boxes explodes.

    # Arguments

    * `builder` - the display list builder which manages the coordinate system and options.
    * `dirty` - Dirty rectangle, in the coordinate system of the owning flow (self.ctx)
    * `origin` - Total offset from display list root flow to this box's owning flow
    * `list` - List to which items should be appended
    */
    fn build_display_list(_builder: &dl::DisplayListBuilder, dirty: &Rect<au>,
                          offset: &Point2D<au>, list: &dl::DisplayList) {
        if !self.d().position.intersects(dirty) {
            return;
        }

        let bounds : Rect<au> = Rect(self.d().position.origin.add(offset),
                                     copy self.d().position.size);

        match self {
            UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here.",
            TextBox(_,d) => {
                list.push(~dl::Text(bounds, ~(copy *d.run), d.offset, d.length))
            },
            // TODO: items for background, border, outline
            GenericBox(*) => { },
            ImageBox(_,i) => {
                match i.get_image() {
                    Some(image) => list.push(~dl::Image(bounds, arc::clone(&image))),
                    /* No image data at all? Okay, add some fallback content instead. */
                    None => {
                        // TODO: shouldn't need to unbox CSSValue by now
                        let boxed_color = self.d().node.style().background_color;
                        let color = match boxed_color {
                            Specified(BgColor(c)) => c,
                            Specified(BgColorTransparent) | _ => util::color::rgba(0,0,0,0.0)
                        };
                        list.push(~dl::SolidColor(bounds, color.red, color.green, color.blue));
                    }
                }
            }
        }
    }
}

impl RenderBox : BoxedDebugMethods {
    fn dump(@self) {
        self.dump_indent(0u);
    }

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

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

    fn debug_str(@self) -> ~str {
        let repr = match self {
            @GenericBox(*) => ~"GenericBox",
            @ImageBox(*) => ~"ImageBox",
            @TextBox(_,d) => fmt!("TextBox(text=%s)", str::substr(d.run.text, d.offset, d.length)),
            @UnscannedTextBox(_,s) => fmt!("UnscannedTextBox(%s)", s)
        };

        fmt!("box b%?: %?", self.d().id, repr)
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate chrono;

use std::env;
use std::fs::DirBuilder;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::Write;
use std::io::Read;
use std::io;
use std::io::Seek;
use std::io::SeekFrom;
use std::ops::Sub;
use std::path::PathBuf;
use std::process;
use std::str;

use clap::{Arg, App, AppSettings, SubCommand};

use chrono::DateTime;
use chrono::Timelike;
use chrono::TimeZone;
use chrono::UTC;
use chrono::date::Date;

const RECORD_LENGTH: usize = 22;

#[derive(Debug)]
#[derive(PartialEq)]
enum Action {
	PunchIn,
	PunchOut,
	Unset
}

struct Record {
	timestamp: DateTime<UTC>,
	action: Action
}

fn main() {
    match ensure_log_file_exists() {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't create punch log: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    let args = App::new("Punch").
	    about("A simple time tracker app").
	    version("0.1").
        setting(AppSettings::ArgRequiredElseHelp).
        subcommand(SubCommand::with_name("in").about("Punch in")).
        subcommand(SubCommand::with_name("out").about("Punch out")).
        subcommand(SubCommand::with_name("card").about("Display state").
	        arg(Arg::with_name("week").long("week").short("w").help("Display summary for the last week")).
	        arg(Arg::with_name("mtd").long("mtd").short("m").help("Display summary for the month to date"))).
        get_matches();

	match args.subcommand() {
		("card", Some(specifier)) => {
			if specifier.is_present("week") {
				print_weekly_summary()
			}
			else if specifier.is_present("mtd") {
				println!("Print month-to-date summary")
			}
			else {
				print_current_state();
			}
		},
		("in", _) => {
			ensure_last_record_is_of_action(Action::PunchOut);
			write_record_to_log(chrono::UTC::now(), Action::PunchIn);
		},
		("out", _) => {
			ensure_last_record_is_of_action(Action::PunchIn);
			write_record_to_log(chrono::UTC::now(), Action::PunchOut);
		},
		_ => {
			println!("Unknown command")
		}
	}
}

fn write_record_to_log(tm: DateTime<UTC>, action: Action) {
	let action_token = match action {
		Action::PunchIn => "I",
		Action::PunchOut => "O",
		Action::Unset => "U"
	};

    let mut config_file = get_conf_file(false, true).unwrap();
    let fmt = tm.format("%FT%T");
	let formatted_timestamp = fmt.to_string();
	append_to_file(format!("{}_{}\n", formatted_timestamp, action_token).as_bytes(), &mut config_file);
}

fn print_weekly_summary() {
	let start_of_week = chrono::UTC::now().with_second(0).
		map(|ts| ts.with_minute(0).
			map(|ts| ts.with_hour(0))
		).unwrap().unwrap().unwrap();

		print_daily_durations_since(start_of_week);
}

fn print_daily_durations_since(start_time: chrono::DateTime<UTC>) {
	let mut daily_durations: Vec<DailyDuration> = vec![];
	let mut record_offset = 0;
	let mut record = empty_record();
	let mut config_file = get_conf_file(true, false).unwrap();

	while (true) {
		populate_record_at_offset_from_end(&mut config_file, &mut record, record_offset);

		record_offset -= 1;
	}
}

struct DailyDuration {
	date: chrono::date::Date<UTC>,
	duration: chrono::Duration
}

fn print_current_state() {
    let mut config_file = get_conf_file(true, false).unwrap();
    let mut record = empty_record();

    match populate_record_at_offset_from_end(&mut config_file, &mut record, 0) {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't read entry: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    if record.action == Action::PunchIn {
    	let current_timestamp = chrono::UTC::now();
    	let time_punched_in = current_timestamp.sub(record.timestamp);
    	println!("Punched in since {} ({})", record.timestamp, format_duration(time_punched_in))
    }
    else {
    	let mut previous_record = empty_record();
    	match populate_record_at_offset_from_end(&mut config_file, &mut previous_record, 1) {
	    	Ok(_) => {},
	    	Err(e) => {
	    		println!("Couldn't read entry: {}.\nExiting.", e);
				process::exit(1)
	    	}
	    }

    	let delta = record.timestamp.sub(previous_record.timestamp);
    	println!("Previously punched in between {} and {} ({})",
    		previous_record.timestamp, record.timestamp, format_duration(delta))
    }
}

fn format_duration(duration: chrono::Duration) -> String {
	format!("{:02}h{:02}m", duration.num_hours(), duration.num_minutes())
}

fn ensure_last_record_is_of_action(expected_action: Action) {
	let mut config_file = get_conf_file(true, false).unwrap();
    let mut record = empty_record();

    match populate_record_at_offset_from_end(&mut config_file, &mut record, 0) {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't create punch log: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    if record.action != expected_action {
    	match expected_action {
    		Action::PunchIn => {
    			println!("Already punched out, punch in first!");
				process::exit(0)
    		}
    		Action::PunchOut => {
    			println!("Already punched in, punch out first!");
    			process::exit(0)
    		}
    		Action::Unset => {
    			println!("Found unset action, log file corrupt");
    			process::exit(1)
    		}
    	}
    }
}

fn get_conf_file(read: bool, append: bool) -> io::Result<File> {
	let mut conf_file = PathBuf::new();
    conf_file.push(env::home_dir().unwrap());
    conf_file.push(".punch");
    conf_file.push("punch.log");

    OpenOptions::new().read(read).append(append).open(conf_file)
}

fn empty_record() -> Record {
	Record {
    	action: Action::Unset,
    	timestamp: chrono::UTC::now()
    }
}

fn populate_record_at_offset_from_end(config_file: &mut File, record: &mut Record, offset_from_end: u64) -> Result<(), String> {
	return seek_to_record_offset(config_file, offset_from_end).
		and_then(|_| populate_record_at_current_offset(config_file, record))
}

fn populate_record_at_current_offset(f: &mut File, record: &mut Record) -> Result<(), String> {
	let mut data = [0 as u8; RECORD_LENGTH];
	let read = f.read(&mut data);
	if read.unwrap() != RECORD_LENGTH {
		panic!("Could not read complete record of {} bytes", RECORD_LENGTH)
	}
	let (ts_data, rest) = data.split_at(19);
	let timestamp = str::from_utf8(&ts_data).unwrap();
	let parse_result = chrono::UTC.datetime_from_str(&timestamp, "%FT%T");

	let record_ts = parse_result.unwrap().with_timezone(&chrono::UTC);
	record.timestamp = record_ts;
	let action_string = str::from_utf8(&rest).unwrap();
	if action_string == "_O\n" {
		record.action = Action::PunchOut;
	}
	else if action_string == "_I\n" {
		record.action = Action::PunchIn;
	}
	else {
		return Err(format!("Could not determine action type from '{}'", action_string))
	}
	Ok(())
}

fn seek_to_record_offset(f: &mut File, record_offset: u64) -> Result<(), String> {
	let m = f.metadata().unwrap();
	let file_len = m.len();

	let record_length_in_bytes = RECORD_LENGTH as u64;
	let seek_offset = file_len - ((record_offset + 1) * record_length_in_bytes);

	if f.seek(SeekFrom::Start(seek_offset)).unwrap() != seek_offset {
		return Err(format!("Could not seek to record offset {}", seek_offset))
	}
	Ok(())
}

fn append_to_file(data: &[u8], f: &mut File) {
	match f.write_all(data) {
    	Ok(_) => {},
    	Err(e) => println!("Failed to write data to log: {}", e)
    }
}

fn ensure_log_file_exists() -> io::Result<()> {
    let mut conf_dir = PathBuf::new();
    conf_dir.push(env::home_dir().unwrap());
    conf_dir.push(".punch");
    let config_path = conf_dir.as_path();

    let mut conf_file_builder = PathBuf::from(config_path);
    conf_file_builder.push("punch.log");

    let mut dir_builder = DirBuilder::new();
    dir_builder.recursive(true);

    try!(dir_builder.create(config_path));

    let conf_file = conf_file_builder.as_path();
    match OpenOptions::new().create(true).write(true).open(conf_file) {
    	Ok(_) => Ok(()),
    	Err(e) => Err(e)
    }
}<commit_msg>track per-day summary<commit_after>extern crate clap;
extern crate chrono;

use std::env;
use std::fs::DirBuilder;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::Write;
use std::io::Read;
use std::io;
use std::io::Seek;
use std::io::SeekFrom;
use std::ops::Sub;
use std::ops::Add;
use std::path::PathBuf;
use std::process;
use std::str;

use clap::{Arg, App, AppSettings, SubCommand};

use chrono::DateTime;
use chrono::Timelike;
use chrono::TimeZone;
use chrono::UTC;
use chrono::date::Date;

const RECORD_LENGTH: usize = 22;

#[derive(Debug)]
#[derive(PartialEq)]
enum Action {
	PunchIn,
	PunchOut,
	Unset
}

struct Record {
	timestamp: DateTime<UTC>,
	action: Action
}

fn main() {
    match ensure_log_file_exists() {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't create punch log: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    let args = App::new("Punch").
	    about("A simple time tracker app").
	    version("0.1").
        setting(AppSettings::ArgRequiredElseHelp).
        subcommand(SubCommand::with_name("in").about("Punch in")).
        subcommand(SubCommand::with_name("out").about("Punch out")).
        subcommand(SubCommand::with_name("card").about("Display state").
	        arg(Arg::with_name("week").long("week").short("w").help("Display summary for the last week")).
	        arg(Arg::with_name("mtd").long("mtd").short("m").help("Display summary for the month to date"))).
        get_matches();

	match args.subcommand() {
		("card", Some(specifier)) => {
			if specifier.is_present("week") {
				print_weekly_summary()
			}
			else if specifier.is_present("mtd") {
				println!("Print month-to-date summary")
			}
			else {
				print_current_state();
			}
		},
		("in", _) => {
			ensure_last_record_is_of_action(Action::PunchOut);
			write_record_to_log(chrono::UTC::now(), Action::PunchIn);
		},
		("out", _) => {
			ensure_last_record_is_of_action(Action::PunchIn);
			write_record_to_log(chrono::UTC::now(), Action::PunchOut);
		},
		_ => {
			println!("Unknown command")
		}
	}
}

fn write_record_to_log(tm: DateTime<UTC>, action: Action) {
	let action_token = match action {
		Action::PunchIn => "I",
		Action::PunchOut => "O",
		Action::Unset => "U"
	};

    let mut config_file = get_conf_file(false, true).unwrap();
    let fmt = tm.format("%FT%T");
	let formatted_timestamp = fmt.to_string();
	append_to_file(format!("{}_{}\n", formatted_timestamp, action_token).as_bytes(), &mut config_file);
}

fn print_weekly_summary() {
	let start_of_week = chrono::UTC::now().with_second(0).
		map(|ts| ts.with_minute(0).
			map(|ts| ts.with_hour(0))
		).unwrap().unwrap().unwrap();

		print_daily_durations_since(start_of_week);
}

fn print_daily_durations_since(start_time: chrono::DateTime<UTC>) {
	let mut daily_durations: Vec<DailyDuration> = vec![];
	let mut record_offset = 0;
	let mut record = empty_record();
	let mut config_file = get_conf_file(true, false).unwrap();
	let &mut current_date: &mut chrono::Date<UTC> =
		&mut chrono::UTC::now().date().add(chrono::Duration::days(1));

	let mut day_count: i64 = 0;

	loop {
		populate_record_at_offset_from_end(&mut config_file, &mut record, record_offset);
		if record.timestamp.date() != current_date && day_count != 0 {

			daily_durations.push(DailyDuration {
					date: current_date,
					duration: chrono::Duration::days(1)
			});
			day_count += 1;
		}

		record_offset -= 1;
	}
}

struct DailyDuration {
	date: chrono::date::Date<UTC>,
	duration: chrono::Duration
}

fn print_current_state() {
    let mut config_file = get_conf_file(true, false).unwrap();
    let mut record = empty_record();

    match populate_record_at_offset_from_end(&mut config_file, &mut record, 0) {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't read entry: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    if record.action == Action::PunchIn {
    	let current_timestamp = chrono::UTC::now();
    	let time_punched_in = current_timestamp.sub(record.timestamp);
    	println!("Punched in since {} ({})", record.timestamp, format_duration(time_punched_in))
    }
    else {
    	let mut previous_record = empty_record();
    	match populate_record_at_offset_from_end(&mut config_file, &mut previous_record, 1) {
	    	Ok(_) => {},
	    	Err(e) => {
	    		println!("Couldn't read entry: {}.\nExiting.", e);
				process::exit(1)
	    	}
	    }

    	let delta = record.timestamp.sub(previous_record.timestamp);
    	println!("Previously punched in between {} and {} ({})",
    		previous_record.timestamp, record.timestamp, format_duration(delta))
    }
}

fn format_duration(duration: chrono::Duration) -> String {
	format!("{:02}h{:02}m", duration.num_hours(), duration.num_minutes())
}

fn ensure_last_record_is_of_action(expected_action: Action) {
	let mut config_file = get_conf_file(true, false).unwrap();
    let mut record = empty_record();

    match populate_record_at_offset_from_end(&mut config_file, &mut record, 0) {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't create punch log: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    if record.action != expected_action {
    	match expected_action {
    		Action::PunchIn => {
    			println!("Already punched out, punch in first!");
				process::exit(0)
    		}
    		Action::PunchOut => {
    			println!("Already punched in, punch out first!");
    			process::exit(0)
    		}
    		Action::Unset => {
    			println!("Found unset action, log file corrupt");
    			process::exit(1)
    		}
    	}
    }
}

fn get_conf_file(read: bool, append: bool) -> io::Result<File> {
	let mut conf_file = PathBuf::new();
    conf_file.push(env::home_dir().unwrap());
    conf_file.push(".punch");
    conf_file.push("punch.log");

    OpenOptions::new().read(read).append(append).open(conf_file)
}

fn empty_record() -> Record {
	Record {
    	action: Action::Unset,
    	timestamp: chrono::UTC::now()
    }
}

fn populate_record_at_offset_from_end(config_file: &mut File, record: &mut Record, offset_from_end: u64) -> Result<(), String> {
	return seek_to_record_offset(config_file, offset_from_end).
		and_then(|_| populate_record_at_current_offset(config_file, record))
}

fn populate_record_at_current_offset(f: &mut File, record: &mut Record) -> Result<(), String> {
	let mut data = [0 as u8; RECORD_LENGTH];
	let read = f.read(&mut data);
	if read.unwrap() != RECORD_LENGTH {
		panic!("Could not read complete record of {} bytes", RECORD_LENGTH)
	}
	let (ts_data, rest) = data.split_at(19);
	let timestamp = str::from_utf8(&ts_data).unwrap();
	let parse_result = chrono::UTC.datetime_from_str(&timestamp, "%FT%T");

	let record_ts = parse_result.unwrap().with_timezone(&chrono::UTC);
	record.timestamp = record_ts;
	let action_string = str::from_utf8(&rest).unwrap();
	if action_string == "_O\n" {
		record.action = Action::PunchOut;
	}
	else if action_string == "_I\n" {
		record.action = Action::PunchIn;
	}
	else {
		return Err(format!("Could not determine action type from '{}'", action_string))
	}
	Ok(())
}

fn seek_to_record_offset(f: &mut File, record_offset: u64) -> Result<(), String> {
	let m = f.metadata().unwrap();
	let file_len = m.len();

	if file_len < RECORD_LENGTH as u64 {
		return Err(String::from("No data in log - punch in first!"))
	}

	let record_length_in_bytes = RECORD_LENGTH as u64;
	let seek_offset = file_len - ((record_offset + 1) * record_length_in_bytes);

	if f.seek(SeekFrom::Start(seek_offset)).unwrap() != seek_offset {
		return Err(format!("Could not seek to record offset {}", seek_offset))
	}
	Ok(())
}

fn append_to_file(data: &[u8], f: &mut File) {
	match f.write_all(data) {
    	Ok(_) => {},
    	Err(e) => println!("Failed to write data to log: {}", e)
    }
}

fn ensure_log_file_exists() -> io::Result<()> {
    let mut conf_dir = PathBuf::new();
    conf_dir.push(env::home_dir().unwrap());
    conf_dir.push(".punch");
    let config_path = conf_dir.as_path();

    let mut conf_file_builder = PathBuf::from(config_path);
    conf_file_builder.push("punch.log");

    let mut dir_builder = DirBuilder::new();
    dir_builder.recursive(true);

    try!(dir_builder.create(config_path));

    let conf_file = conf_file_builder.as_path();
    match OpenOptions::new().create(true).write(true).open(conf_file) {
    	Ok(_) => Ok(()),
    	Err(e) => Err(e)
    }
}<|endoftext|>


<commit_before>//! # Triple buffering
//!
//! In this crate, we attempt to implement a triple buffering mechanism,
//! suitable for emulating shared memory cells in a thread-safe and
//! non-blocking fashion between one single writer and one single reader.

use std::cell::UnsafeCell;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Barrier};
use std::thread;
use std::time::Duration;

/// ## Indexing
///
/// These types are used to index into triple buffers
/// TODO: Switch to i8 / AtomicI8 once the later is stable
type TripleBufferIndex = usize;
type AtomicTripleBufferIndex = AtomicUsize;

/// ## Shared state
///
/// In a triple buffering communication protocol, the reader and writer share
/// the following storage:
///
/// - Three memory buffers suitable for storing the data at hand
/// - One index pointing to the "back" buffer, which no one is currently using
/// - One index pointing to the most recently updated buffer
///
#[derive(Debug)]
struct TripleBufferSharedState<T: Clone + PartialEq> {
    /// Three buffers of data
    buffers: [UnsafeCell<T>; 3],

    /// Index of the back-buffer (buffer which no one is currently accessing)
    back_idx: AtomicTripleBufferIndex,

    /// Index of the most recently updated buffer
    last_idx: AtomicTripleBufferIndex,
}
//
impl<T: Clone + PartialEq> Clone for TripleBufferSharedState<T> {
    fn clone(&self) -> Self {
        // The use of UnsafeCell makes buffers somwhat cumbersome to clone...
        let clone_buffer = | i: TripleBufferIndex | {
            UnsafeCell::new(
                unsafe { (*self.buffers[i].get()).clone() }
            )
        };

        // ...so better define a shortcut before we move on to actual cloning
        TripleBufferSharedState {
            buffers: [
                clone_buffer(0),
                clone_buffer(1),
                clone_buffer(2),
            ],
            back_idx: AtomicTripleBufferIndex::new(
                self.back_idx.load(Ordering::Relaxed)
            ),
            last_idx: AtomicTripleBufferIndex::new(
                self.last_idx.load(Ordering::Relaxed)
            ),
        }
    }
}
//
impl<T: Clone + PartialEq> PartialEq for TripleBufferSharedState<T> {
    fn eq(&self, other: &Self) -> bool {
        // The use of UnsafeCell makes buffers somwhat cumbersome to compare...
        let buffer_eq = | i: TripleBufferIndex | -> bool {
            unsafe { *self.buffers[i].get() == *other.buffers[i].get() }
        };

        // ...and atomics aren't much better...
        let atomics_eq = | x: &AtomicTripleBufferIndex,
                           y: &AtomicTripleBufferIndex | -> bool {
            x.load(Ordering::Relaxed) == y.load(Ordering::Relaxed)
        };

        // ...so better define some shortcuts before getting started:
        buffer_eq(0) && buffer_eq(1) && buffer_eq(2) &&
        atomics_eq(&self.back_idx, &other.back_idx) &&
        atomics_eq(&self.last_idx, &other.last_idx)
    }
}
//
unsafe impl<T: Clone + PartialEq> Sync for TripleBufferSharedState<T> {}

/// ## Producing data ("input")
///
/// The producer of data has exclusive write access to the so-called "write
/// buffer". To send an update, it writes it into the write buffer, then swaps
/// the write buffer with the back buffer, making the data accessible.
///
#[derive(Debug)]
struct TripleBufferInput<T: Clone + PartialEq> {
    shared: Arc<TripleBufferSharedState<T>>,
    write_idx: TripleBufferIndex,
}
//
impl<T: Clone + PartialEq> TripleBufferInput<T> {
    /// Write a new value into the triple buffer
    fn write(&mut self, value: T) {
        // Access the shared state
        let ref shared_state = *self.shared;

        // Determine which shared buffer is the write buffer
        let active_idx = self.write_idx;

        // Move the input value into the write buffer
        let write_ptr = shared_state.buffers[active_idx].get();
        unsafe { *write_ptr = value; }

        // Swap the back buffer and the write buffer. This makes the new data
        // block available to the reader and gives us a new buffer to write to.
        self.write_idx = shared_state.back_idx.swap(
            active_idx,
            Ordering::Release  // Need this for new buffer state to be visible
        );

        // Notify the reader that we submitted an update
        shared_state.last_idx.store(
            active_idx,
            Ordering::Release  // Need this for back_idx to be visible
        );
    }
}

/// ## Consuming data ("output")
///
/// The consumer of data has exclusive read access to the so-called "read
/// buffer". To access the latest data, it swaps the read buffer with the
/// back buffer if the later contains more recent data, then reads from
/// the (possibly new) read buffer.
///
#[derive(Debug)]
struct TripleBufferOutput<T: Clone + PartialEq> {
    shared: Arc<TripleBufferSharedState<T>>,
    read_idx: TripleBufferIndex,
}
//
impl<T: Clone + PartialEq> TripleBufferOutput<T> {
    /// Access the latest fully written value from the triple buffer
    fn read(&mut self) -> &T {
        // Access the shared state
        let ref shared_state = *self.shared;

        // Check if the writer has submitted an update
        let last_idx = shared_state.last_idx.load(Ordering::Acquire);

        // If an update is pending in the back buffer, make it our read buffer
        if self.read_idx != last_idx {
            // Swap the back buffer and the read buffer. We get exclusive read
            // access to the data, and the writer gets a new back buffer.
            self.read_idx = shared_state.back_idx.swap(
                self.read_idx,
                Ordering::Acquire  // Another update could have occured...
            );
        }

        // Access data from the current read buffer
        let read_ptr = shared_state.buffers[self.read_idx].get();
        unsafe { &*read_ptr }
    }
}

/// ## Triple buffer
///
/// A triple buffer is created as the combination of an input and an output.
///
#[derive(Debug)]
struct TripleBuffer<T: Clone + PartialEq> {
    input: TripleBufferInput<T>,
    output: TripleBufferOutput<T>,
}
//
impl<T: Clone + PartialEq> TripleBuffer<T> {
    /// Construct a triple buffer with a certain initial value
    fn new(initial: T) -> Self {
        // Start with the shared state...
        let shared_state = Arc::new(
            TripleBufferSharedState {
                buffers: [
                    UnsafeCell::new(initial.clone()),
                    UnsafeCell::new(initial.clone()),
                    UnsafeCell::new(initial)
                ],
                back_idx: AtomicTripleBufferIndex::new(0),
                last_idx: AtomicTripleBufferIndex::new(2),
            }
        );

        // ...then construct the input and output structs
        TripleBuffer {
            input: TripleBufferInput {
                shared: shared_state.clone(),
                write_idx: 1,
            },
            output: TripleBufferOutput {
                shared: shared_state,
                read_idx: 2,
            },
        }
    }
}
//
impl<T: Clone + PartialEq> Clone for TripleBuffer<T> {
    fn clone(&self) -> Self {
        // Clone the shared state...
        let shared_state = Arc::new(
            (*self.input.shared).clone()
        );

        // ...then the input and output structs
        TripleBuffer {
            input: TripleBufferInput {
                shared: shared_state.clone(),
                write_idx: self.input.write_idx,
            },
            output: TripleBufferOutput {
                shared: shared_state,
                read_idx: self.output.read_idx,
            },
        }
    }
}
//
impl<T: Clone + PartialEq> PartialEq for TripleBuffer<T> {
    fn eq(&self, other: &Self) -> bool {
        (*self.input.shared == *other.input.shared) &&
        (self.input.write_idx == other.input.write_idx) &&
        (self.output.read_idx == other.output.read_idx)
    }
}

/// ## Testing
///
/// Unit tests and benchmarks for triple buffers
///
#[cfg(test)]
mod tests {
    /// Test that triple buffers are properly initialized
    #[test]
    fn test_init() {
        // Let's create a triple buffer
        let buf = ::TripleBuffer::new(42);

        // Access the shared state
        let ref buf_shared = *buf.input.shared;
        let back_idx = buf_shared.back_idx.load(::Ordering::Relaxed);
        let last_idx = buf_shared.last_idx.load(::Ordering::Relaxed);

        // Write-/read-/back-buffer indexes must be in range
        assert!(index_in_range(buf.input.write_idx));
        assert!(index_in_range(buf.output.read_idx));
        assert!(index_in_range(back_idx));

        // Write-/read-/back-buffer indexes must be distinct
        assert!(buf.input.write_idx != buf.output.read_idx);
        assert!(buf.input.write_idx != back_idx);
        assert!(buf.output.read_idx != back_idx);

        // Read buffer must be properly initialized
        let read_ptr = buf_shared.buffers[buf.output.read_idx].get();
        assert!(unsafe { *read_ptr } == 42);

        // Last-written index must initially point to the read buffer
        assert_eq!(last_idx, buf.output.read_idx);
    }

    /// Test that (sequentially) writing to a triple buffer works
    #[test]
    fn test_seq_write() {
        // Let's create a triple buffer
        let mut buf = ::TripleBuffer::new(false);

        // Back up the initial buffer state
        let old_buf = buf.clone();
        let ref old_shared = old_buf.input.shared;

        // Perform a write
        buf.input.write(true);

        // Check new implementation state
        {
            // Starting from the old buffer state...
            let mut expected_buf = old_buf.clone();
            let ref expected_shared = expected_buf.input.shared;

            // We expect the former write buffer to have received the new value
            let old_write_idx = old_buf.input.write_idx;
            let write_buf_ptr = expected_shared.buffers[old_write_idx].get();
            unsafe { *write_buf_ptr = true; }

            // We expect the former write buffer to be the new back buffer
            expected_shared.back_idx.store(
                old_write_idx,
                ::Ordering::Relaxed
            );

            // We expect the last updated index to point to former write buffer
            expected_shared.last_idx.store(
                old_write_idx,
                ::Ordering::Relaxed
            );

            // We expect the old back buffer to become the new write buffer
            let old_back_idx = old_shared.back_idx.load(::Ordering::Relaxed);
            expected_buf.input.write_idx = old_back_idx;

            // Nothing else should have changed
            assert_eq!(buf, expected_buf);
        }
    }

    /// Check that (sequentially) reading from a triple buffer works
    #[test]
    fn test_seq_read() {
        // Let's create a triple buffer and write into it
        let mut buf = ::TripleBuffer::new(1.0);
        buf.input.write(4.2);

        // Test readout from dirty (freshly written) triple buffer
        {
            // Back up the initial buffer state
            let old_buf = buf.clone();
            let ref old_shared = old_buf.input.shared;

            // Read from the buffer
            let result = *buf.output.read();

            // Output value should be correct
            assert_eq!(result, 4.2);

            // Starting from the old buffer state...
            let mut expected_buf = old_buf.clone();
            let ref expected_shared = expected_buf.input.shared;

            // We expect the new back index to point to the former read buffer
            expected_shared.back_idx.store(
                old_buf.output.read_idx,
                ::Ordering::Relaxed
            );

            // We expect the new read index to point to the former back buffer
            let old_back_idx = old_shared.back_idx.load(::Ordering::Relaxed);
            expected_buf.output.read_idx = old_back_idx;

            // Nothing else should have changed
            assert_eq!(buf, expected_buf);
        }

        // Test readout from clean (unchanged) triple buffer
        {
            // Back up the initial buffer state
            let old_buf = buf.clone();

            // Read from the buffer
            let result = *buf.output.read();

            // Output value should be correct
            assert_eq!(result, 4.2);

            // Buffer state should be unchanged
            assert_eq!(buf, old_buf);
        }
    }

    /// Check that concurrent reads and writes work
    ///
    /// **WARNING:** This test unfortunately needs to have timing-dependent
    /// behaviour. If it fails for you, try the following:
    ///
    /// - Close running applications in the background
    /// - Re-run the tests with only one OS thread (RUST_TEST_THREADS=1)
    /// - Increase the writer sleep period below
    ///
    #[test]
    fn test_conc_access() {
        // We will stress the infrastructure by performing this many writes
        // as a reader continuously reads the latest value
        let test_write_count = 1000;

        // This is the buffer that our reader and writer will share
        let mut buf = ::TripleBuffer::new(0u64);

        // Extract the input stage so that we can send it to the writer
        let mut buf_input = buf.input;

        // Setup a barrier so that the reader & writer can start synchronously
        let barrier = ::Arc::new(::Barrier::new(2));
        let w_barrier = barrier.clone();

        // The writer continuously increments the buffered value, with some
        // rate limiting to ensure that the reader can see the updates
        let writer = ::thread::spawn(move || {
            w_barrier.wait();
            for value in 1 .. test_write_count+1 {
                buf_input.write(value);
                ::thread::yield_now();
                ::thread::sleep(::Duration::from_millis(1));
            }
        });

        // The reader continuously checks the buffered value, and should see
        // every update without any incoherent value
        let mut last_value = 0u64;
        barrier.wait();
        while last_value < test_write_count {
            let new_value = *buf.output.read();
            assert!(
                (new_value >= last_value) && (new_value-last_value <= 1)
            );
            last_value = new_value;
        }

        // Wait for the writer to finish
        writer.join().unwrap();
    }

    // TODO: Benchmark the performance of concurrent reads and writes

    /// Range check for triple buffer indexes
    #[allow(unused_comparisons)]
    fn index_in_range(idx: ::TripleBufferIndex) -> bool {
        (idx >= 0) & (idx <= 2)
    }
}

fn main() {
    println!("Hello, world!");

    let mut buf = TripleBuffer::new("Hello!");
    println!("Initial value is {}", buf.output.read());

    buf.input.write("World!");
    println!("New value is {}", buf.output.read())
}
<commit_msg>Made concurrent test longer, and ignored it by default<commit_after>//! # Triple buffering
//!
//! In this crate, we attempt to implement a triple buffering mechanism,
//! suitable for emulating shared memory cells in a thread-safe and
//! non-blocking fashion between one single writer and one single reader.

use std::cell::UnsafeCell;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Barrier};
use std::thread;
use std::time::Duration;

/// ## Indexing
///
/// These types are used to index into triple buffers
/// TODO: Switch to i8 / AtomicI8 once the later is stable
type TripleBufferIndex = usize;
type AtomicTripleBufferIndex = AtomicUsize;

/// ## Shared state
///
/// In a triple buffering communication protocol, the reader and writer share
/// the following storage:
///
/// - Three memory buffers suitable for storing the data at hand
/// - One index pointing to the "back" buffer, which no one is currently using
/// - One index pointing to the most recently updated buffer
///
#[derive(Debug)]
struct TripleBufferSharedState<T: Clone + PartialEq> {
    /// Three buffers of data
    buffers: [UnsafeCell<T>; 3],

    /// Index of the back-buffer (buffer which no one is currently accessing)
    back_idx: AtomicTripleBufferIndex,

    /// Index of the most recently updated buffer
    last_idx: AtomicTripleBufferIndex,
}
//
impl<T: Clone + PartialEq> Clone for TripleBufferSharedState<T> {
    fn clone(&self) -> Self {
        // The use of UnsafeCell makes buffers somwhat cumbersome to clone...
        let clone_buffer = | i: TripleBufferIndex | {
            UnsafeCell::new(
                unsafe { (*self.buffers[i].get()).clone() }
            )
        };

        // ...so better define a shortcut before we move on to actual cloning
        TripleBufferSharedState {
            buffers: [
                clone_buffer(0),
                clone_buffer(1),
                clone_buffer(2),
            ],
            back_idx: AtomicTripleBufferIndex::new(
                self.back_idx.load(Ordering::Relaxed)
            ),
            last_idx: AtomicTripleBufferIndex::new(
                self.last_idx.load(Ordering::Relaxed)
            ),
        }
    }
}
//
impl<T: Clone + PartialEq> PartialEq for TripleBufferSharedState<T> {
    fn eq(&self, other: &Self) -> bool {
        // The use of UnsafeCell makes buffers somwhat cumbersome to compare...
        let buffer_eq = | i: TripleBufferIndex | -> bool {
            unsafe { *self.buffers[i].get() == *other.buffers[i].get() }
        };

        // ...and atomics aren't much better...
        let atomics_eq = | x: &AtomicTripleBufferIndex,
                           y: &AtomicTripleBufferIndex | -> bool {
            x.load(Ordering::Relaxed) == y.load(Ordering::Relaxed)
        };

        // ...so better define some shortcuts before getting started:
        buffer_eq(0) && buffer_eq(1) && buffer_eq(2) &&
        atomics_eq(&self.back_idx, &other.back_idx) &&
        atomics_eq(&self.last_idx, &other.last_idx)
    }
}
//
unsafe impl<T: Clone + PartialEq> Sync for TripleBufferSharedState<T> {}

/// ## Producing data ("input")
///
/// The producer of data has exclusive write access to the so-called "write
/// buffer". To send an update, it writes it into the write buffer, then swaps
/// the write buffer with the back buffer, making the data accessible.
///
#[derive(Debug)]
struct TripleBufferInput<T: Clone + PartialEq> {
    shared: Arc<TripleBufferSharedState<T>>,
    write_idx: TripleBufferIndex,
}
//
impl<T: Clone + PartialEq> TripleBufferInput<T> {
    /// Write a new value into the triple buffer
    fn write(&mut self, value: T) {
        // Access the shared state
        let ref shared_state = *self.shared;

        // Determine which shared buffer is the write buffer
        let active_idx = self.write_idx;

        // Move the input value into the write buffer
        let write_ptr = shared_state.buffers[active_idx].get();
        unsafe { *write_ptr = value; }

        // Swap the back buffer and the write buffer. This makes the new data
        // block available to the reader and gives us a new buffer to write to.
        self.write_idx = shared_state.back_idx.swap(
            active_idx,
            Ordering::Release  // Need this for new buffer state to be visible
        );

        // Notify the reader that we submitted an update
        shared_state.last_idx.store(
            active_idx,
            Ordering::Release  // Need this for back_idx to be visible
        );
    }
}

/// ## Consuming data ("output")
///
/// The consumer of data has exclusive read access to the so-called "read
/// buffer". To access the latest data, it swaps the read buffer with the
/// back buffer if the later contains more recent data, then reads from
/// the (possibly new) read buffer.
///
#[derive(Debug)]
struct TripleBufferOutput<T: Clone + PartialEq> {
    shared: Arc<TripleBufferSharedState<T>>,
    read_idx: TripleBufferIndex,
}
//
impl<T: Clone + PartialEq> TripleBufferOutput<T> {
    /// Access the latest fully written value from the triple buffer
    fn read(&mut self) -> &T {
        // Access the shared state
        let ref shared_state = *self.shared;

        // Check if the writer has submitted an update
        let last_idx = shared_state.last_idx.load(Ordering::Acquire);

        // If an update is pending in the back buffer, make it our read buffer
        if self.read_idx != last_idx {
            // Swap the back buffer and the read buffer. We get exclusive read
            // access to the data, and the writer gets a new back buffer.
            self.read_idx = shared_state.back_idx.swap(
                self.read_idx,
                Ordering::Acquire  // Another update could have occured...
            );
        }

        // Access data from the current read buffer
        let read_ptr = shared_state.buffers[self.read_idx].get();
        unsafe { &*read_ptr }
    }
}

/// ## Triple buffer
///
/// A triple buffer is created as the combination of an input and an output.
///
#[derive(Debug)]
struct TripleBuffer<T: Clone + PartialEq> {
    input: TripleBufferInput<T>,
    output: TripleBufferOutput<T>,
}
//
impl<T: Clone + PartialEq> TripleBuffer<T> {
    /// Construct a triple buffer with a certain initial value
    fn new(initial: T) -> Self {
        // Start with the shared state...
        let shared_state = Arc::new(
            TripleBufferSharedState {
                buffers: [
                    UnsafeCell::new(initial.clone()),
                    UnsafeCell::new(initial.clone()),
                    UnsafeCell::new(initial)
                ],
                back_idx: AtomicTripleBufferIndex::new(0),
                last_idx: AtomicTripleBufferIndex::new(2),
            }
        );

        // ...then construct the input and output structs
        TripleBuffer {
            input: TripleBufferInput {
                shared: shared_state.clone(),
                write_idx: 1,
            },
            output: TripleBufferOutput {
                shared: shared_state,
                read_idx: 2,
            },
        }
    }
}
//
impl<T: Clone + PartialEq> Clone for TripleBuffer<T> {
    fn clone(&self) -> Self {
        // Clone the shared state...
        let shared_state = Arc::new(
            (*self.input.shared).clone()
        );

        // ...then the input and output structs
        TripleBuffer {
            input: TripleBufferInput {
                shared: shared_state.clone(),
                write_idx: self.input.write_idx,
            },
            output: TripleBufferOutput {
                shared: shared_state,
                read_idx: self.output.read_idx,
            },
        }
    }
}
//
impl<T: Clone + PartialEq> PartialEq for TripleBuffer<T> {
    fn eq(&self, other: &Self) -> bool {
        (*self.input.shared == *other.input.shared) &&
        (self.input.write_idx == other.input.write_idx) &&
        (self.output.read_idx == other.output.read_idx)
    }
}

/// ## Testing
///
/// Unit tests and benchmarks for triple buffers
///
#[cfg(test)]
mod tests {
    /// Test that triple buffers are properly initialized
    #[test]
    fn test_init() {
        // Let's create a triple buffer
        let buf = ::TripleBuffer::new(42);

        // Access the shared state
        let ref buf_shared = *buf.input.shared;
        let back_idx = buf_shared.back_idx.load(::Ordering::Relaxed);
        let last_idx = buf_shared.last_idx.load(::Ordering::Relaxed);

        // Write-/read-/back-buffer indexes must be in range
        assert!(index_in_range(buf.input.write_idx));
        assert!(index_in_range(buf.output.read_idx));
        assert!(index_in_range(back_idx));

        // Write-/read-/back-buffer indexes must be distinct
        assert!(buf.input.write_idx != buf.output.read_idx);
        assert!(buf.input.write_idx != back_idx);
        assert!(buf.output.read_idx != back_idx);

        // Read buffer must be properly initialized
        let read_ptr = buf_shared.buffers[buf.output.read_idx].get();
        assert!(unsafe { *read_ptr } == 42);

        // Last-written index must initially point to the read buffer
        assert_eq!(last_idx, buf.output.read_idx);
    }

    /// Test that (sequentially) writing to a triple buffer works
    #[test]
    fn test_seq_write() {
        // Let's create a triple buffer
        let mut buf = ::TripleBuffer::new(false);

        // Back up the initial buffer state
        let old_buf = buf.clone();
        let ref old_shared = old_buf.input.shared;

        // Perform a write
        buf.input.write(true);

        // Check new implementation state
        {
            // Starting from the old buffer state...
            let mut expected_buf = old_buf.clone();
            let ref expected_shared = expected_buf.input.shared;

            // We expect the former write buffer to have received the new value
            let old_write_idx = old_buf.input.write_idx;
            let write_buf_ptr = expected_shared.buffers[old_write_idx].get();
            unsafe { *write_buf_ptr = true; }

            // We expect the former write buffer to be the new back buffer
            expected_shared.back_idx.store(
                old_write_idx,
                ::Ordering::Relaxed
            );

            // We expect the last updated index to point to former write buffer
            expected_shared.last_idx.store(
                old_write_idx,
                ::Ordering::Relaxed
            );

            // We expect the old back buffer to become the new write buffer
            let old_back_idx = old_shared.back_idx.load(::Ordering::Relaxed);
            expected_buf.input.write_idx = old_back_idx;

            // Nothing else should have changed
            assert_eq!(buf, expected_buf);
        }
    }

    /// Check that (sequentially) reading from a triple buffer works
    #[test]
    fn test_seq_read() {
        // Let's create a triple buffer and write into it
        let mut buf = ::TripleBuffer::new(1.0);
        buf.input.write(4.2);

        // Test readout from dirty (freshly written) triple buffer
        {
            // Back up the initial buffer state
            let old_buf = buf.clone();
            let ref old_shared = old_buf.input.shared;

            // Read from the buffer
            let result = *buf.output.read();

            // Output value should be correct
            assert_eq!(result, 4.2);

            // Starting from the old buffer state...
            let mut expected_buf = old_buf.clone();
            let ref expected_shared = expected_buf.input.shared;

            // We expect the new back index to point to the former read buffer
            expected_shared.back_idx.store(
                old_buf.output.read_idx,
                ::Ordering::Relaxed
            );

            // We expect the new read index to point to the former back buffer
            let old_back_idx = old_shared.back_idx.load(::Ordering::Relaxed);
            expected_buf.output.read_idx = old_back_idx;

            // Nothing else should have changed
            assert_eq!(buf, expected_buf);
        }

        // Test readout from clean (unchanged) triple buffer
        {
            // Back up the initial buffer state
            let old_buf = buf.clone();

            // Read from the buffer
            let result = *buf.output.read();

            // Output value should be correct
            assert_eq!(result, 4.2);

            // Buffer state should be unchanged
            assert_eq!(buf, old_buf);
        }
    }

    /// Check that concurrent reads and writes work
    ///
    /// **WARNING:** This test unfortunately needs to have timing-dependent
    /// behaviour. If it fails for you, try the following:
    ///
    /// - Close running applications in the background
    /// - Re-run the tests with only one OS thread (RUST_TEST_THREADS=1)
    /// - Increase the writer sleep period below
    ///
    #[test]
    #[ignore]
    fn test_conc_access() {
        // We will stress the infrastructure by performing this many writes
        // as a reader continuously reads the latest value
        let test_write_count = 10000;

        // This is the buffer that our reader and writer will share
        let mut buf = ::TripleBuffer::new(0u64);

        // Extract the input stage so that we can send it to the writer
        let mut buf_input = buf.input;

        // Setup a barrier so that the reader & writer can start synchronously
        let barrier = ::Arc::new(::Barrier::new(2));
        let w_barrier = barrier.clone();

        // The writer continuously increments the buffered value, with some
        // rate limiting to ensure that the reader can see the updates
        let writer = ::thread::spawn(move || {
            w_barrier.wait();
            for value in 1 .. test_write_count+1 {
                buf_input.write(value);
                ::thread::yield_now();
                ::thread::sleep(::Duration::from_millis(1));
            }
        });

        // The reader continuously checks the buffered value, and should see
        // every update without any incoherent value
        let mut last_value = 0u64;
        barrier.wait();
        while last_value < test_write_count {
            let new_value = *buf.output.read();
            assert!(
                (new_value >= last_value) && (new_value-last_value <= 1)
            );
            last_value = new_value;
        }

        // Wait for the writer to finish
        writer.join().unwrap();
    }

    // TODO: Benchmark the performance of concurrent reads and writes

    /// Range check for triple buffer indexes
    #[allow(unused_comparisons)]
    fn index_in_range(idx: ::TripleBufferIndex) -> bool {
        (idx >= 0) & (idx <= 2)
    }
}

fn main() {
    println!("Hello, world!");

    let mut buf = TripleBuffer::new("Hello!");
    println!("Initial value is {}", buf.output.read());

    buf.input.write("World!");
    println!("New value is {}", buf.output.read())
}
<|endoftext|>


<commit_before>
#![feature(macro_rules)]

use std::collections::HashMap;
use std::comm::{Receiver, Sender};
use std::io::{Acceptor, BufferedReader, BufWriter, Listener, MemReader, MemWriter, TcpListener, TcpStream};
use std::io::stdin;
use std::rand::random;

type Id = u32;
type NullResult<T> = Result<T, ()>;
type Packet = Vec<u8>;

enum Message {
    RemovePlayer(Id),
    HandlePacket(Id, Packet),
    AddPlayer(TcpStream),
    ListPlayers,
}

struct Player {
    id: Id,
    tcp: TcpStream,
    name: String,
    send: Sender<Packet>,
}

struct Server {
    players: HashMap<Id, Player>,
    send: Sender<Message>,
    recv: Receiver<Message>,
}

fn main() {
    println!("NoLifePony Server");
    let mut server = Server::new();
    server.run();
    println!("Shutting down");
}

fn new_packet() -> MemWriter {
    let mut buf = MemWriter::new();
    buf.write([0, 0, 0, 0]).unwrap();
    buf
}

fn packet_sender(recv: Receiver<Packet>, mut tcp: TcpStream) {
    for mut msg in recv.iter() {
        let len = msg.len() as u32 - 4;
        {
            let mut buf = BufWriter::new(msg.mut_slice_to(4));
            buf.write_be_u32(len).unwrap();
        }
        let msg = msg;
        match tcp.write(msg.as_slice()) {
            Ok(_) => (),
            Err(_) => return,
        }
    }
}

fn packet_receiver(send: Sender<Message>, tcp: TcpStream, id: Id) {
    struct Packets {
        buf: BufferedReader<TcpStream>,
    }
    impl Iterator<Packet> for Packets {
        fn next(&mut self) -> Option<Packet> {
            self.buf.read_be_u32().and_then(|len| self.buf.read_exact(len as uint)).ok()
        }
    }
    let mut packets = Packets {
        buf: BufferedReader::new(tcp),
    };
    for packet in packets {
        send.send(HandlePacket(id, packet));
    }
    send.send(RemovePlayer(id));
}

fn listener(send: Sender<Message>) {
    let listen = TcpListener::bind("0.0.0.0", 273);
    let mut accept = listen.listen();
    for stream in accept.incoming() {
        match stream {
            Ok(stream) => send.send(AddPlayer(stream)),
            Err(_) => return,
        }
    }
}

fn commands(send: Sender<Message>) {
    let mut cin = stdin();
    for line in cin.lines() {
        let line = line.unwrap();
        let line: String = line.as_slice().chars().map(|c| c.to_lowercase())
            .filter(|c| *c != '\n' && *c != '\r').collect();
        match line.as_slice() {
            "list" => send.send(ListPlayers),
            _ => println!("Unknown command"),
        }
    }
}

impl Player {
    fn default_name(id: Id) -> String {
        format!("Pony{:08X}", id)
    }
    fn new(id: Id, mut tcp: TcpStream, send: Sender<Message>) -> Player {
        let tcp2 = tcp.clone();
        spawn(proc() packet_receiver(send, tcp2, id));
        let (send, recv) = channel::<Packet>();
        let tcp2 = tcp.clone();
        spawn(proc() packet_sender(recv, tcp2));
        let name = Player::default_name(id);
        match tcp.peer_name() {
            Ok(ip) => println!("{} connected from {}", name, ip),
            Err(_) => println!("{} connected from unknown", name),
        }
        Player {
            id: id,
            tcp: tcp,
            name: name,
            send: send,
        }
    }
    fn send_id(&self) {
        let mut p = new_packet();
        p.write_be_u16(0x4).unwrap();
        p.write_be_u32(self.id).unwrap();
        self.send.send(p.unwrap());
    }
    fn send_players_joined(&self, server: &Server) {
        let mut p = new_packet();
        p.write_be_u16(0xB).unwrap();
        p.write_be_u32(server.players.len() as u32).unwrap();
        server.players(|player| {
            p.write_be_u32(player.id).unwrap();
            p.write_be_u32(player.name.len() as u32).unwrap();
            p.write_str(player.name.as_slice()).unwrap();
        });
        self.send.send(p.unwrap());
    }
    fn send_player_joined(&self, player: &Player) {
        let mut p = new_packet();
        p.write_be_u16(0xB).unwrap();
        p.write_be_u32(1).unwrap();
        p.write_be_u32(player.id).unwrap();
        p.write_be_u32(player.name.len() as u32).unwrap();
        p.write_str(player.name.as_slice()).unwrap();
        self.send.send(p.unwrap());
    }
    fn send_player_left(&self, id: Id) {
        let mut p = new_packet();
        p.write_be_u16(0xF).unwrap();
        p.write_be_u32(1).unwrap();
        p.write_be_u32(id).unwrap();
        self.send.send(p.unwrap());
    }
    fn send_pong(&self, mut packet: MemReader) {
        let ping = match packet.read_be_u32() {
            Ok(ping) => ping,
            Err(_) => { println!("Failed to read ping from {}", self.name); return },
        };
        let mut p = new_packet();
        p.write_be_u16(0x2).unwrap();
        p.write_be_u32(ping).unwrap();
        self.send.send(p.unwrap());
    }
}

impl Server {
    fn new() -> Server {
        let (send, recv) = channel::<Message>();
        let send2 = send.clone();
        spawn(proc() listener(send2));
        let send2 = send.clone();
        spawn(proc() commands(send2));
        Server {
            players: HashMap::new(),
            send: send,
            recv: recv,
        }
    }
    fn player(&self, id: Id, func: |&Player|) {
        self.players.find(&id).map(func);
    }
    fn mut_player(&mut self, id: Id, func: |&mut Player|) {
        self.players.find_mut(&id).map(func);
    }
    fn players(&self, func: |&Player|) {
        for (_, player) in self.players.iter() { func(player) }
    }
    fn mut_players(&mut self, func: |&mut Player|) {
        for (_, player) in self.players.mut_iter() { func(player) }
    }
    fn gen_id(&self) -> Id {
        loop {
            let id = random();
            if self.players.find(&id).is_none() { return id }
        }
    }
    fn add_player(&mut self, tcp: TcpStream) {
        let id = self.gen_id();
        let player = Player::new(id, tcp, self.send.clone());
        self.players(|p| p.send_player_joined(&player));
        self.players.insert(player.id, player);
        let player = self.players.get(&id);
        player.send_id();
        player.send_players_joined(self);
    }
    fn remove_player(&mut self, id: Id) {
        {
            let player = match self.players.find_mut(&id) {
                Some(player) => player,
                None => return,
            };
            println!("{} disconnected", player.name);
            player.tcp.close_read().unwrap();
            player.tcp.close_write().unwrap();
        }
        self.players(|player| player.send_player_left(id));
    }
    fn handle_packet(&mut self, id: Id, packet: Packet) {
        let player = match self.players.find_mut(&id) {
            Some(player) => player,
            None => { println!("Packet from non-existant player: {}", id); return },
        };
        let mut packet = MemReader::new(packet);
        let opcode = match packet.read_be_u16() {
            Ok(opcode) => opcode,
            Err(_) => { println!("Failed to read opcode from player: {}", id); return },
        };
        match opcode {
            1 => player.send_pong(packet),
            _ => println!("Unknown opcode {} from {}", opcode, player.name),
        }
    }
    fn run(&mut self) {
        loop {
            let message = self.recv.recv();
            match message {
                AddPlayer(tcp) => self.add_player(tcp),
                RemovePlayer(id) => self.remove_player(id),
                HandlePacket(id, packet) => self.handle_packet(id, packet),
                ListPlayers => {
                    print!("Connected: ");
                    self.players(|player| print!("{}, ", player.name));
                    println!("");
                },
            }
        }
    }
}
<commit_msg>Fixed severe bug that caused server failure.<commit_after>
#![feature(macro_rules)]

use std::collections::HashMap;
use std::comm::{Receiver, Sender};
use std::io::{Acceptor, BufferedReader, BufWriter, Listener, MemReader, MemWriter, TcpListener, TcpStream};
use std::io::stdin;
use std::rand::random;

type Id = u32;
type NullResult<T> = Result<T, ()>;
type Packet = Vec<u8>;

enum Message {
    RemovePlayer(Id),
    HandlePacket(Id, Packet),
    AddPlayer(TcpStream),
    ListPlayers,
}

struct Player {
    id: Id,
    tcp: TcpStream,
    name: String,
    send: Sender<Packet>,
}

struct Server {
    players: HashMap<Id, Player>,
    send: Sender<Message>,
    recv: Receiver<Message>,
}

fn main() {
    println!("NoLifePony Server");
    let mut server = Server::new();
    server.run();
    println!("Shutting down");
}

fn new_packet() -> MemWriter {
    let mut buf = MemWriter::new();
    buf.write([0, 0, 0, 0]).unwrap();
    buf
}

fn packet_sender(recv: Receiver<Packet>, mut tcp: TcpStream) {
    for mut msg in recv.iter() {
        let len = msg.len() as u32 - 4;
        {
            let mut buf = BufWriter::new(msg.mut_slice_to(4));
            buf.write_be_u32(len).unwrap();
        }
        let msg = msg;
        match tcp.write(msg.as_slice()) {
            Ok(_) => (),
            Err(_) => return,
        }
    }
}

fn packet_receiver(send: Sender<Message>, tcp: TcpStream, id: Id) {
    struct Packets {
        buf: BufferedReader<TcpStream>,
    }
    impl Iterator<Packet> for Packets {
        fn next(&mut self) -> Option<Packet> {
            self.buf.read_be_u32().and_then(|len| self.buf.read_exact(len as uint)).ok()
        }
    }
    let mut packets = Packets {
        buf: BufferedReader::new(tcp),
    };
    for packet in packets {
        send.send(HandlePacket(id, packet));
    }
    send.send(RemovePlayer(id));
}

fn listener(send: Sender<Message>) {
    let listen = TcpListener::bind("0.0.0.0", 273);
    let mut accept = listen.listen();
    for stream in accept.incoming() {
        match stream {
            Ok(stream) => send.send(AddPlayer(stream)),
            Err(_) => return,
        }
    }
}

fn commands(send: Sender<Message>) {
    let mut cin = stdin();
    for line in cin.lines() {
        let line = line.unwrap();
        let line: String = line.as_slice().chars().map(|c| c.to_lowercase())
            .filter(|c| *c != '\n' && *c != '\r').collect();
        match line.as_slice() {
            "list" => send.send(ListPlayers),
            _ => println!("Unknown command"),
        }
    }
}

impl Player {
    fn default_name(id: Id) -> String {
        format!("Pony{:08X}", id)
    }
    fn new(id: Id, mut tcp: TcpStream, send: Sender<Message>) -> Player {
        let tcp2 = tcp.clone();
        spawn(proc() packet_receiver(send, tcp2, id));
        let (send, recv) = channel::<Packet>();
        let tcp2 = tcp.clone();
        spawn(proc() packet_sender(recv, tcp2));
        let name = Player::default_name(id);
        match tcp.peer_name() {
            Ok(ip) => println!("{} connected from {}", name, ip),
            Err(_) => println!("{} connected from unknown", name),
        }
        Player {
            id: id,
            tcp: tcp,
            name: name,
            send: send,
        }
    }
    fn send_id(&self) {
        let mut p = new_packet();
        p.write_be_u16(0x4).unwrap();
        p.write_be_u32(self.id).unwrap();
        self.send.send(p.unwrap());
    }
    fn send_players_joined(&self, server: &Server) {
        let mut p = new_packet();
        p.write_be_u16(0xB).unwrap();
        p.write_be_u32(server.players.len() as u32).unwrap();
        server.players(|player| {
            p.write_be_u32(player.id).unwrap();
            p.write_be_u32(player.name.len() as u32).unwrap();
            p.write_str(player.name.as_slice()).unwrap();
        });
        self.send.send(p.unwrap());
    }
    fn send_player_joined(&self, player: &Player) {
        let mut p = new_packet();
        p.write_be_u16(0xB).unwrap();
        p.write_be_u32(1).unwrap();
        p.write_be_u32(player.id).unwrap();
        p.write_be_u32(player.name.len() as u32).unwrap();
        p.write_str(player.name.as_slice()).unwrap();
        self.send.send(p.unwrap());
    }
    fn send_player_left(&self, id: Id) {
        let mut p = new_packet();
        p.write_be_u16(0xF).unwrap();
        p.write_be_u32(1).unwrap();
        p.write_be_u32(id).unwrap();
        self.send.send(p.unwrap());
    }
    fn send_pong(&self, mut packet: MemReader) {
        let ping = match packet.read_be_u32() {
            Ok(ping) => ping,
            Err(_) => { println!("Failed to read ping from {}", self.name); return },
        };
        let mut p = new_packet();
        p.write_be_u16(0x2).unwrap();
        p.write_be_u32(ping).unwrap();
        self.send.send(p.unwrap());
    }
}

impl Server {
    fn new() -> Server {
        let (send, recv) = channel::<Message>();
        let send2 = send.clone();
        spawn(proc() listener(send2));
        let send2 = send.clone();
        spawn(proc() commands(send2));
        Server {
            players: HashMap::new(),
            send: send,
            recv: recv,
        }
    }
    fn player(&self, id: Id, func: |&Player|) {
        self.players.find(&id).map(func);
    }
    fn mut_player(&mut self, id: Id, func: |&mut Player|) {
        self.players.find_mut(&id).map(func);
    }
    fn players(&self, func: |&Player|) {
        for (_, player) in self.players.iter() { func(player) }
    }
    fn mut_players(&mut self, func: |&mut Player|) {
        for (_, player) in self.players.mut_iter() { func(player) }
    }
    fn gen_id(&self) -> Id {
        loop {
            let id = random();
            if self.players.find(&id).is_none() { return id }
        }
    }
    fn add_player(&mut self, tcp: TcpStream) {
        let id = self.gen_id();
        let player = Player::new(id, tcp, self.send.clone());
        self.players(|p| p.send_player_joined(&player));
        self.players.insert(player.id, player);
        let player = self.players.get(&id);
        player.send_id();
        player.send_players_joined(self);
    }
    fn remove_player(&mut self, id: Id) {
        self.player(id, |player| {
            println!("{} disconnected", player.name);
            self.players(|player| player.send_player_left(id));
        });
        self.mut_player(id, |player| {
            player.tcp.close_read().unwrap();
            player.tcp.close_write().unwrap();
        });
        self.players.remove(&id);
    }
    fn handle_packet(&mut self, id: Id, packet: Packet) {
        let player = match self.players.find_mut(&id) {
            Some(player) => player,
            None => { println!("Packet from non-existant player: {}", id); return },
        };
        let mut packet = MemReader::new(packet);
        let opcode = match packet.read_be_u16() {
            Ok(opcode) => opcode,
            Err(_) => { println!("Failed to read opcode from player: {}", id); return },
        };
        match opcode {
            1 => player.send_pong(packet),
            _ => println!("Unknown opcode {} from {}", opcode, player.name),
        }
    }
    fn run(&mut self) {
        loop {
            let message = self.recv.recv();
            match message {
                AddPlayer(tcp) => self.add_player(tcp),
                RemovePlayer(id) => self.remove_player(id),
                HandlePacket(id, packet) => self.handle_packet(id, packet),
                ListPlayers => {
                    print!("Connected: ");
                    self.players(|player| print!("{}, ", player.name));
                    println!("");
                },
            }
        }
    }
}
<|endoftext|>


<commit_before>fn build_prefix_array(haplotypes: &[u8], n_haplo: usize, n_sites: usize) -> Vec<usize> {
    let mut prefix_order: Vec<usize> = vec![0; n_haplo];
    for i in 0..n_haplo {
        prefix_order[i] = i;
    }

    for k in 0..(n_sites-1) {
        let mut allele_0s: Vec<usize> = vec![];
        let mut allele_1s: Vec<usize> = vec![];
        for i in &prefix_order {
            if haplotypes[i*n_sites + k] == 0 {
                allele_0s.push(*i);
            } else {
                allele_1s.push(*i);
            }
        }
        prefix_order[0..allele_0s.len()].clone_from_slice(&allele_0s);
        prefix_order[allele_0s.len()..n_haplo].clone_from_slice(&allele_1s);
    }
    prefix_order
}

fn main() {
    let n_haplo: usize = 8; // M
    let n_sites: usize = 6; // N
    let haplotypes: Vec<u8> = vec![0, 1, 0, 1, 0, 1,
                                   1, 1, 0, 0, 0, 1,
                                   1, 1, 1, 1, 1, 1,
                                   0, 1, 1, 1, 1, 0,
                                   0, 0, 0, 0, 0, 0,
                                   1, 0, 0, 0, 1, 0,
                                   1, 1, 0, 0, 0, 1,
                                   0, 1, 0, 1, 1, 0];
    assert_eq!(n_haplo * n_sites, haplotypes.len());

    let prefix_order = build_prefix_array(&haplotypes, n_haplo, n_sites);
    println!("{:?}", prefix_order);
}

<commit_msg>Use an actual test<commit_after>fn build_prefix_array(haplotypes: &[u8], n_haplo: usize, n_sites: usize) -> Vec<usize> {
    let mut prefix_order: Vec<usize> = vec![0; n_haplo];
    for i in 0..n_haplo {
        prefix_order[i] = i;
    }

    for k in 0..(n_sites-1) {
        let mut allele_0s: Vec<usize> = vec![];
        let mut allele_1s: Vec<usize> = vec![];
        for i in &prefix_order {
            if haplotypes[i*n_sites + k] == 0 {
                allele_0s.push(*i);
            } else {
                allele_1s.push(*i);
            }
        }
        prefix_order[0..allele_0s.len()].clone_from_slice(&allele_0s);
        prefix_order[allele_0s.len()..n_haplo].clone_from_slice(&allele_1s);
    }
    prefix_order
}

fn main() {
    let n_haplo: usize = 8; // M
    let n_sites: usize = 6; // N
    let haplotypes: Vec<u8> = vec![0, 1, 0, 1, 0, 1,
                                   1, 1, 0, 0, 0, 1,
                                   1, 1, 1, 1, 1, 1,
                                   0, 1, 1, 1, 1, 0,
                                   0, 0, 0, 0, 0, 0,
                                   1, 0, 0, 0, 1, 0,
                                   1, 1, 0, 0, 0, 1,
                                   0, 1, 0, 1, 1, 0];
    assert_eq!(n_haplo * n_sites, haplotypes.len());

    let prefix_order = build_prefix_array(&haplotypes, n_haplo, n_sites);
    println!("{:?}", prefix_order);
}

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

    #[test]
    fn test_prefix_array() {
        let n_haplo: usize = 8;
        let n_sites: usize = 6;
        let haplotypes: Vec<u8> = vec![0, 1, 0, 1, 0, 1,
                                       1, 1, 0, 0, 0, 1,
                                       1, 1, 1, 1, 1, 1,
                                       0, 1, 1, 1, 1, 0,
                                       0, 0, 0, 0, 0, 0,
                                       1, 0, 0, 0, 1, 0,
                                       1, 1, 0, 0, 0, 1,
                                       0, 1, 0, 1, 1, 0];
        let expected: Vec<usize> = vec![4, 1, 6, 0, 5, 7, 3, 2];
        assert_eq!(&expected,
                   &build_prefix_array(&haplotypes, n_haplo, n_sites));
    }
}
<|endoftext|>