<commit_before>use geometry::Point;
use geometry::Rect;
use geometry::Size;

/**
 Elements that may be contained by a quadtree node.
 Either child nodes, a single rect, or nothing.
 */
pub enum Elements {
    /// Children are top left, top right, bottom right, and bottom left, respectively.
    Children(~QuadTree, ~QuadTree, ~QuadTree, ~QuadTree),
    /// A single rectangle.
    Member(Rect),
    /// Nothing.
    NoElements,
}

/**
 A quadtree node that can contain either one rectangle,
 or exactly four child nodes.
 */
pub struct QuadTree {
    rect: Rect,
    elements: Elements,
}

impl QuadTree {
    /**
     Create a quadtree with a root node with the given origin and size.
     */
    pub fn new(origin: Point, size: Size, elems: Elements) -> QuadTree {
        let tree =
        match elems {
            Children(tl, tr, br, bl) => QuadTree::newWithChildren(origin, size, tl, tr, br, bl),
            Member(rect) => QuadTree::newWithMember(origin, size, rect),
            NoElements => QuadTree::newWithSize(origin, size),
        };

        tree
    }

    /**
     Create a quadtree with a root node with the same origin and a square
     size with side length matching the longer dimension of `rect`.
     */
    pub fn newAutosized(rect: Rect) -> QuadTree {
        let largerDimen = if rect.size.width > rect.size.height {
            rect.size.width
        } else {
            rect.size.height
        };

        let size = Size::new(largerDimen, largerDimen);

        QuadTree::newWithMember(rect.origin, size, rect)
    }

    /**
     Create an empty quadtree with a zero-sized root node.
     */
    pub fn newEmpty() -> QuadTree {
        let origin = Point::new(0., 0.);
        let size = Size::new(0., 0.);
        let tree = QuadTree::new(origin, size, NoElements);

        tree
    }

    /**
     Create a quadtree with a root node with the given origin, size, and child rectangles.
     Child nodes `tl`, `tr`, `br`, and `bl` should form the rect specified by `origin` and `size`.
     */
    fn newWithChildren(origin: Point, size: Size, tl: ~QuadTree, tr: ~QuadTree, br: ~QuadTree, bl: ~QuadTree) -> QuadTree {
        let nodeRect = Rect::new(origin, size);

        // Assert that our rect and our childrens' rects match up.
        assert!(tl.rect.minX() == bl.rect.minX(), "Top left and bottom left children should have same minX coordinate.");
        assert!(tl.rect.maxX() == bl.rect.maxX(), "Top left and bottom left children should have same maxX coordinate.");
        assert!(tl.rect.maxY() == bl.rect.minY(), "Top left and bottom left children should have same maxY and minY coordinates, respectively.");

        assert!(tl.rect.maxX() == tr.rect.minX(), "Top left and top right children should share their maxX and minX coordinates, respectively.");
        assert!(tl.rect.minY() == tr.rect.minY(), "Top left and top right children should have same minY coordinate.");
        assert!(tl.rect.maxY() == tr.rect.maxY(), "Top left and top right children should have same maxY coordinate.");

        assert!(bl.rect.maxX() == br.rect.minX(), "Bottom left and bottom right children should share their maxX and minX coordinates, respectively.");
        assert!(bl.rect.minY() == br.rect.minY(), "Bottom left and bottom right children should have same minY coordinate.");
        assert!(bl.rect.maxY() == br.rect.maxY(), "Bottom left and bottom right children should have same maxY coordinate.");

        assert!(tr.rect.minX() == br.rect.minX(), "Top right and bottom right children should have same minX coordinate.");
        assert!(tr.rect.maxX() == br.rect.maxX(), "Top right and bottom right children should have same maxX coordinate.");
        assert!(tr.rect.maxY() == br.rect.minY(), "Top right and bottom right children should have same maxY and minY coordinates, respectively.");

        assert!(nodeRect.minX() == tl.rect.minX(), "Tree node's minX should match its top left child's minX coordinate.");
        assert!(nodeRect.maxX() == tr.rect.maxX(), "Tree node's maxX should match its top right child's maxX coordinate.");
        assert!(nodeRect.minY() == tl.rect.minY(), "Tree node's minY should match its top left child's minY coordinate.");
        assert!(nodeRect.maxY() == bl.rect.maxY(), "Tree node's maxY should match its top left child's maxY coordinate.");

        let tree = QuadTree { rect: nodeRect, elements: Children(tl, tr, br, bl) };

        tree
    }

    /**
     Create a quadtree with a root node with the given origin, size, and member rectangle.
     */
    fn newWithMember(origin: Point, size: Size, insertRect: Rect) -> QuadTree {
        let node = QuadTree::newWithSize(origin, size);

        let (success, tree) = node.insertRect(insertRect);
        assert!(success, "Failed inserting a node into an empty quadtree.");

        tree
    }

    /**
     Create a quadtree with only a specified size and position.
     */
    fn newWithSize(origin: Point, size: Size) -> QuadTree {
        let nodeRect = Rect::new(origin, size);
        let tree = QuadTree { rect: nodeRect, elements: NoElements };

        tree
    }

    /**
     Insert a rectangle into the quadtree. If `toInsert` overlaps another rectangle
     already in the tree, the return value will be (false, self).
     If the root node is zero-sized, the resulting tree will have a square root node
     large enough to hold `toInsert`.
     */
    pub fn insertRect(self, toInsert: Rect) -> (bool, QuadTree) {
        if self.rect.width() == 0.0 {
            return (true, QuadTree::newAutosized(toInsert))
        }

        let rectsInChildren = self.rectsInChildNodesIntersectedByRect(&toInsert);
        if rectsInChildren.len() > 0 {
            return (false, self)
        }

        let mut node = self;
        let mut bigEnough = node.rect.contains(&toInsert);

        while !bigEnough {
            let width = node.rect.width();
            let height = node.rect.height();
            let origin = node.rect.origin;
            let size = node.rect.size;

            let wPoint = Point::new(width, 0.);
            let hPoint = Point::new(0., height);

            // Check if the rect to insert extends to the left or "above" our origin,
            // i.e. has a lower x or y coordinate in its origin.
            // Use this information to determine if we must grow the tree left, up, right, or down.
            let left = node.rect.minX() < toInsert.minX();
            let top = node.rect.minX() < toInsert.minY();

            let (tl, tr, bl, br) =
            match (left, top) {
                (true, true) => (QuadTree::newWithSize(origin.subtract(wPoint).add(hPoint), size),
                                 QuadTree::newWithSize(origin.subtract(hPoint), size),
                                 QuadTree::newWithSize(origin.subtract(wPoint), size),
                                 node),
                (true, false) => (QuadTree::newWithSize(origin.subtract(wPoint), size),
                                  node,
                                  QuadTree::newWithSize(origin.subtract(wPoint).subtract(hPoint), size),
                                  QuadTree::newWithSize(origin.subtract(hPoint), size)),
                (false, true) => (QuadTree::newWithSize(origin.add(hPoint), size),
                                  QuadTree::newWithSize(origin.add(hPoint).add(wPoint), size),
                                  node,
                                  QuadTree::newWithSize(origin.add(wPoint), size)),
                (false, false) => (node,
                                   QuadTree::newWithSize(origin.add(wPoint), size),
                                   QuadTree::newWithSize(origin.add(hPoint), size),
                                   QuadTree::newWithSize(origin.add(wPoint).add(hPoint), size)),
            };

            let (tl, tr, bl, br) = (tl.insertRectIfIntersects(toInsert),
                                    tr.insertRectIfIntersects(toInsert),
                                    bl.insertRectIfIntersects(toInsert),
                                    br.insertRectIfIntersects(toInsert),);

            node = QuadTree::newWithChildren(tl.rect.origin,
                Size::new(width * 2., height * 2.),
                ~tl, ~tr, ~br, ~bl);

            bigEnough = node.rect.contains(&toInsert);
        }

        (true, node)
    }

    /**
     Insert a rectangle into the node IFF the rectangle intersects the node.
     Does nothing if `toInsert` intersects our existing member rect.
     */
    fn insertRectIfIntersects(self, toInsert: Rect) -> QuadTree {
        if self.rect.intersects(&toInsert) {
            let origin = self.rect.origin;
            let size = self.rect.size;
            match self.elements {
                Children(~tl, ~tr, ~br, ~bl) => {
                    let (tl, tr, br, bl) = (tl.insertRectIfIntersects(toInsert),
                                            tr.insertRectIfIntersects(toInsert),
                                            br.insertRectIfIntersects(toInsert),
                                            bl.insertRectIfIntersects(toInsert),);
                    QuadTree::newWithChildren(origin, size, ~tl, ~tr, ~br, ~bl)
                },
                Member(rect) => {
                    if rect.intersects(&toInsert) {
                        self
                    } else {
                        let (tl, tr, br, bl) = QuadTree::makeChildrenForRect(&self.rect);

                        let (tl, tr, br, bl) = (tl.insertRectIfIntersects(rect),
                                                tr.insertRectIfIntersects(rect),
                                                br.insertRectIfIntersects(rect),
                                                bl.insertRectIfIntersects(rect),);
                        let (tl, tr, br, bl) = (tl.insertRectIfIntersects(toInsert),
                                                tr.insertRectIfIntersects(toInsert),
                                                br.insertRectIfIntersects(toInsert),
                                                bl.insertRectIfIntersects(toInsert),);

                        QuadTree::newWithChildren(origin, size, ~tl, ~tr, ~br, ~bl)
                    }
                },
                NoElements => QuadTree::newWithMember(origin, size, toInsert),
            }
        } else {
            self
        }
    }

    /**
     Create four nodes suitable for use as children, covering the passed in rect.
     */
    fn makeChildrenForRect(rect: &Rect) -> (~QuadTree, ~QuadTree, ~QuadTree, ~QuadTree,) {
        let origin = rect.origin;
        let size = rect.size;

        let newSize = Size::new(size.width / 2., size.height / 2.);
        let wPoint = Point::new(newSize.width, 0.);
        let hPoint = Point::new(0., newSize.height);

        let (tl, tr, br, bl) = (QuadTree::newWithSize(origin, newSize),
                                QuadTree::newWithSize(origin.add(wPoint), newSize),
                                QuadTree::newWithSize(origin.add(wPoint).add(hPoint), newSize),
                                QuadTree::newWithSize(origin.add(hPoint), newSize),);

        (~tl, ~tr, ~br, ~bl)
    }

    /**
     Find all of the rects in `self`, or its children, that are in nodes
     intersected by the given rect.
     */
    pub fn rectsInChildNodesIntersectedByRect(&self, testRect: &Rect) -> ~[Rect] {
        // If the test rect doesn't intersect us, then it can't intersect
        // any rects that we have.
        match self.rect.intersect(testRect) {
            Some(intersection) => {
                let mut rects = ~[];
                let mut nodesToCheck = ~[self];

                while nodesToCheck.len() > 0 {
                    let mut newNodesToCheck = ~[];

                    for node in nodesToCheck.iter() {
                        match node.elements {
                            Children(~ref tl, ~ref tr, ~ref br, ~ref bl) => {
                                let mut check = ~[];
                                let intersection = &intersection;
                                if tl.rect.intersects(intersection) {
                                    check.push(tl);
                                }
                                if tr.rect.intersects(intersection) {
                                    check.push(tr);
                                }
                                if br.rect.intersects(intersection) {
                                    check.push(br);
                                }
                                if bl.rect.intersects(intersection) {
                                    check.push(bl);
                                }
                                newNodesToCheck.push_all(check);
                            }
                            Member(memberRect) => rects.push(memberRect),
                            NoElements => ()
                        };
                    }

                    nodesToCheck = newNodesToCheck;
                }

                rects
            },
            None => ~[],
        }
    }
}
<commit_msg>Logic fixes for inserting rects.<commit_after>use geometry::Point;
use geometry::Rect;
use geometry::Size;

/**
 Elements that may be contained by a quadtree node.
 Either child nodes, a single rect, or nothing.
 */
#[deriving(Show)]
pub enum Elements {
    /// Children are top left, top right, bottom right, and bottom left, respectively.
    Children(~QuadTree, ~QuadTree, ~QuadTree, ~QuadTree),
    /// A single rectangle.
    Member(Rect),
    /// Nothing.
    NoElements,
}

/**
 A quadtree node that can contain either one rectangle,
 or exactly four child nodes.
 */
#[deriving(Show)]
pub struct QuadTree {
    rect: Rect,
    elements: Elements,
}

impl QuadTree {
    /**
     Create a quadtree with a root node with the given origin and size.
     */
    pub fn new(origin: Point, size: Size, elems: Elements) -> QuadTree {
        let tree =
        match elems {
            Children(tl, tr, br, bl) => QuadTree::newWithChildren(origin, size, tl, tr, br, bl),
            Member(rect) => QuadTree::newWithMember(origin, size, rect),
            NoElements => QuadTree::newWithSize(origin, size),
        };

        tree
    }

    /**
     Create a quadtree with a root node with the same origin and a square
     size with side length matching the longer dimension of `rect`.
     */
    pub fn newAutosized(rect: Rect) -> QuadTree {
        let largerDimen = if rect.size.width > rect.size.height {
            rect.size.width
        } else {
            rect.size.height
        };

        let size = Size::new(largerDimen, largerDimen);

        QuadTree::newWithMember(rect.origin, size, rect)
    }

    /**
     Create an empty quadtree with a zero-sized root node.
     */
    pub fn newEmpty() -> QuadTree {
        let origin = Point::new(0., 0.);
        let size = Size::new(0., 0.);
        let tree = QuadTree::new(origin, size, NoElements);

        tree
    }

    /**
     Create a quadtree with a root node with the given origin, size, and child rectangles.
     Child nodes `tl`, `tr`, `br`, and `bl` should form the rect specified by `origin` and `size`.
     */
    fn newWithChildren(origin: Point, size: Size, tl: ~QuadTree, tr: ~QuadTree, br: ~QuadTree, bl: ~QuadTree) -> QuadTree {
        let nodeRect = Rect::new(origin, size);

        // Assert that our rect and our childrens' rects match up.
        assert!(tl.rect.minX() == bl.rect.minX(), "Top left and bottom left children should have same minX coordinate.");
        assert!(tl.rect.maxX() == bl.rect.maxX(), "Top left and bottom left children should have same maxX coordinate.");
        assert!(tl.rect.maxY() == bl.rect.minY(), "Top left and bottom left children should have same maxY and minY coordinates, respectively.");

        assert!(tl.rect.maxX() == tr.rect.minX(), "Top left and top right children should share their maxX and minX coordinates, respectively.");
        assert!(tl.rect.minY() == tr.rect.minY(), "Top left and top right children should have same minY coordinate.");
        assert!(tl.rect.maxY() == tr.rect.maxY(), "Top left and top right children should have same maxY coordinate.");

        assert!(bl.rect.maxX() == br.rect.minX(), "Bottom left and bottom right children should share their maxX and minX coordinates, respectively.");
        assert!(bl.rect.minY() == br.rect.minY(), "Bottom left and bottom right children should have same minY coordinate.");
        assert!(bl.rect.maxY() == br.rect.maxY(), "Bottom left and bottom right children should have same maxY coordinate.");

        assert!(tr.rect.minX() == br.rect.minX(), "Top right and bottom right children should have same minX coordinate.");
        assert!(tr.rect.maxX() == br.rect.maxX(), "Top right and bottom right children should have same maxX coordinate.");
        assert!(tr.rect.maxY() == br.rect.minY(), "Top right and bottom right children should have same maxY and minY coordinates, respectively.");

        assert!(nodeRect.minX() == tl.rect.minX(), "Tree node's minX should match its top left child's minX coordinate.");
        assert!(nodeRect.maxX() == tr.rect.maxX(), "Tree node's maxX should match its top right child's maxX coordinate.");
        assert!(nodeRect.minY() == tl.rect.minY(), "Tree node's minY should match its top left child's minY coordinate.");
        assert!(nodeRect.maxY() == bl.rect.maxY(), "Tree node's maxY should match its top left child's maxY coordinate.");

        let tree = QuadTree { rect: nodeRect, elements: Children(tl, tr, br, bl) };

        tree
    }

    /**
     Create a quadtree with a root node with the given origin, size, and member rectangle.
     */
    fn newWithMember(origin: Point, size: Size, insertRect: Rect) -> QuadTree {
        let qtRect = Rect::new(origin, size);
        assert!(qtRect.contains(&insertRect),
            "QuadTree node constructed by newWithMember not able to contain the rect it is passed in.");
        let tree = QuadTree { rect: qtRect, elements: Member(insertRect) };

        tree
    }

    /**
     Create a quadtree with only a specified size and position.
     */
    fn newWithSize(origin: Point, size: Size) -> QuadTree {
        let nodeRect = Rect::new(origin, size);
        let tree = QuadTree { rect: nodeRect, elements: NoElements };

        tree
    }

    /**
     Insert a rectangle into the quadtree. If `toInsert` overlaps another rectangle
     already in the tree, the return value will be (false, self).
     If the root node is zero-sized, the resulting tree will have a square root node
     large enough to hold `toInsert`.
     */
    pub fn insertRect(self, toInsert: Rect) -> (bool, QuadTree) {
        if self.rect.width() == 0.0 {
            return (true, QuadTree::newAutosized(toInsert))
        }

        let rectsInChildren = self.rectsInChildNodesIntersectedByRect(&toInsert);
        if rectsInChildren.len() > 0 {
            return (false, self)
        }

        let mut node = self;
        let mut bigEnough = node.rect.contains(&toInsert);

        while !bigEnough {
            let width = node.rect.width();
            let height = node.rect.height();
            let origin = node.rect.origin;
            let size = node.rect.size;

            let wPoint = Point::new(width, 0.);
            let hPoint = Point::new(0., height);

            // Check if the rects to insert extends to the left or "above" our origin,
            // i.e. has a lower x or y coordinate in its origin.
            // Use this information to determine if we must grow the tree left, up, right, or down.
            let left = node.rect.minX() < toInsert.minX();
            let top = node.rect.minX() < toInsert.minY();

            let (tl, tr, bl, br) =
            match (left, top) {
                (true, true) => (QuadTree::newWithSize(origin.subtract(wPoint).add(hPoint), size),
                                 QuadTree::newWithSize(origin.subtract(hPoint), size),
                                 QuadTree::newWithSize(origin.subtract(wPoint), size),
                                 node),
                (true, false) => (QuadTree::newWithSize(origin.subtract(wPoint), size),
                                  node,
                                  QuadTree::newWithSize(origin.subtract(wPoint).subtract(hPoint), size),
                                  QuadTree::newWithSize(origin.subtract(hPoint), size)),
                (false, true) => (QuadTree::newWithSize(origin.add(hPoint), size),
                                  QuadTree::newWithSize(origin.add(hPoint).add(wPoint), size),
                                  node,
                                  QuadTree::newWithSize(origin.add(wPoint), size)),
                (false, false) => (node,
                                   QuadTree::newWithSize(origin.add(wPoint), size),
                                   QuadTree::newWithSize(origin.add(hPoint), size),
                                   QuadTree::newWithSize(origin.add(wPoint).add(hPoint), size)),
            };

            node = QuadTree::newWithChildren(tl.rect.origin,
                Size::new(width * 2., height * 2.),
                ~tl, ~tr, ~br, ~bl);

            bigEnough = node.rect.contains(&toInsert);
        }

        let origin = node.rect.origin;
        let size = node.rect.size;
        node = match(node.elements) {
            Children(tl, tr, br, bl) => QuadTree::newWithChildren(
                origin,
                size,
                ~tl.insertRectIfIntersects(toInsert),
                ~tr.insertRectIfIntersects(toInsert),
                ~bl.insertRectIfIntersects(toInsert),
                ~br.insertRectIfIntersects(toInsert)),
            Member(rect) => {
                let hw = size.width / 2.;
                let hh = size.height / 2.;
                let wp = Point::new(hw, 0.);
                let hp = Point::new(0., hh);
                let (tlo, tro, bro, blo) = (
                    origin,
                    origin.add(wp),
                    origin.add(hp),
                    origin.add(wp).add(hp),
                    );
                let hSize = Size::new(hw, hh);
                QuadTree::newWithChildren(
                    origin,
                    size,
                    ~QuadTree::newWithSize(tlo, hSize).insertRectIfIntersects(rect).insertRectIfIntersects(toInsert),
                    ~QuadTree::newWithSize(tro, hSize).insertRectIfIntersects(rect).insertRectIfIntersects(toInsert),
                    ~QuadTree::newWithSize(bro, hSize).insertRectIfIntersects(rect).insertRectIfIntersects(toInsert),
                    ~QuadTree::newWithSize(blo, hSize).insertRectIfIntersects(rect).insertRectIfIntersects(toInsert),)
            }
            NoElements => QuadTree::newWithMember(origin, size, toInsert),
        };

        (true, node)
    }

    /**
     Insert a rectangle into the node IFF the rectangle intersects the node.
     Does nothing if `toInsert` intersects our existing member rect.
     */
    fn insertRectIfIntersects(self, toInsert: Rect) -> QuadTree {
        if self.rect.intersects(&toInsert) {
            let origin = self.rect.origin;
            let size = self.rect.size;
            match self.elements {
                Children(~tl, ~tr, ~br, ~bl) => {
                    let (tl, tr, br, bl) = (tl.insertRectIfIntersects(toInsert),
                                            tr.insertRectIfIntersects(toInsert),
                                            br.insertRectIfIntersects(toInsert),
                                            bl.insertRectIfIntersects(toInsert),);
                    QuadTree::newWithChildren(origin, size, ~tl, ~tr, ~br, ~bl)
                },
                Member(rect) => {
                    if rect.intersects(&toInsert) {
                        self
                    } else {
                        let (tl, tr, br, bl) = QuadTree::makeChildrenForRect(&self.rect);

                        let (tl, tr, br, bl) = (tl.insertRectIfIntersects(rect),
                                                tr.insertRectIfIntersects(rect),
                                                br.insertRectIfIntersects(rect),
                                                bl.insertRectIfIntersects(rect),);
                        let (tl, tr, br, bl) = (tl.insertRectIfIntersects(toInsert),
                                                tr.insertRectIfIntersects(toInsert),
                                                br.insertRectIfIntersects(toInsert),
                                                bl.insertRectIfIntersects(toInsert),);

                        QuadTree::newWithChildren(origin, size, ~tl, ~tr, ~br, ~bl)
                    }
                },
                NoElements => QuadTree::newWithMember(origin, size, toInsert),
            }
        } else {
            self
        }
    }

    /**
     Create four nodes suitable for use as children, covering the passed in rect.
     */
    fn makeChildrenForRect(rect: &Rect) -> (~QuadTree, ~QuadTree, ~QuadTree, ~QuadTree,) {
        let origin = rect.origin;
        let size = rect.size;

        let newSize = Size::new(size.width / 2., size.height / 2.);
        let wPoint = Point::new(newSize.width, 0.);
        let hPoint = Point::new(0., newSize.height);

        let (tl, tr, br, bl) = (QuadTree::newWithSize(origin, newSize),
                                QuadTree::newWithSize(origin.add(wPoint), newSize),
                                QuadTree::newWithSize(origin.add(wPoint).add(hPoint), newSize),
                                QuadTree::newWithSize(origin.add(hPoint), newSize),);

        (~tl, ~tr, ~br, ~bl)
    }

    /**
     Find all of the rects in `self`, or its children, that are in nodes
     intersected by the given rect.
     */
    pub fn rectsInChildNodesIntersectedByRect(&self, testRect: &Rect) -> ~[Rect] {
        // If the test rect doesn't intersect us, then it can't intersect
        // any rects that we have.
        match self.rect.intersect(testRect) {
            Some(intersection) => {
                let mut rects = ~[];
                let mut nodesToCheck = ~[self];

                while nodesToCheck.len() > 0 {
                    let mut newNodesToCheck = ~[];

                    for node in nodesToCheck.iter() {
                        match node.elements {
                            Children(~ref tl, ~ref tr, ~ref br, ~ref bl) => {
                                let mut check = ~[];
                                let intersection = &intersection;
                                if tl.rect.intersects(intersection) {
                                    check.push(tl);
                                }
                                if tr.rect.intersects(intersection) {
                                    check.push(tr);
                                }
                                if br.rect.intersects(intersection) {
                                    check.push(br);
                                }
                                if bl.rect.intersects(intersection) {
                                    check.push(bl);
                                }
                                newNodesToCheck.push_all(check);
                            }
                            Member(memberRect) => rects.push(memberRect),
                            NoElements => ()
                        };
                    }

                    nodesToCheck = newNodesToCheck;
                }

                rects
            },
            None => ~[],
        }
    }
}
<|endoftext|>


<commit_before>extern crate prometheus;
extern crate hyper;

use prometheus::{Registry, Gauge, Encoder, TextEncoder};

use super::*;
pub struct PrometheusRenderer<'a> {
    pub buffer: &'a mut Write,
    registry: prometheus::Registry,
    encoder: prometheus::TextEncoder,
    count: prometheus::Gauge,
}

impl<'a> PrometheusRenderer<'a> {
    pub fn new(stream: &'a mut Write) -> PrometheusRenderer<'a> {
        let registry = prometheus::Registry::new();

        let count = prometheus::Gauge::new("count", "The number of responses observed").unwrap();

        registry.register(Box::new(count.clone()));

        PrometheusRenderer {
            registry: registry,
            buffer: stream,
            encoder: prometheus::TextEncoder::new(),
            count: count,
        }
    }
}

impl<'a> Renderer for PrometheusRenderer<'a> {
    fn render(&mut self, result: analyzer::RequestLogAnalyzerResult) {
        self.count.set(result.count as f64);

        let metric_familys = self.registry.gather();

        self.encoder.encode(&metric_familys, self.buffer);
    }
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::prelude::*;
    use std::str;

    use super::*;

    struct MockBuffer {
        write_calls: Vec<String>,
    }

    impl Write for MockBuffer {
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
            self.write_calls.push(str::from_utf8(buf).unwrap().to_string());
            Ok(buf.len())
        }

        fn flush(&mut self) -> io::Result<()> {
            Ok(())
        }
    }

    fn get_result_fixture() -> analyzer::RequestLogAnalyzerResult {
        analyzer::RequestLogAnalyzerResult {
            count: 3,
            max: 100,
            min: 1,
            avg: 37,
            median: 10,
            percentile90: 100,
        }
    }

    #[test]
    fn test_instantiation() {
        let mut mock_buffer = MockBuffer { write_calls: vec![] };

        let renderer = PrometheusRenderer::new(&mut mock_buffer);
    }

    #[test]
    fn test_render() {
        let mut mock_buffer = MockBuffer { write_calls: vec![] };

        let result = get_result_fixture();

        {
            let mut renderer = PrometheusRenderer::new(&mut mock_buffer);

            renderer.render(result);
        }

        println!("{:?}", mock_buffer.write_calls);

        assert_eq!(&mock_buffer.write_calls[0], "# HELP ");
        assert_eq!(&mock_buffer.write_calls[1], "count");
        assert_eq!(&mock_buffer.write_calls[2], " ");
        assert_eq!(&mock_buffer.write_calls[3],
                   "The number of responses observed");
        assert_eq!(&mock_buffer.write_calls[4], "\n");
        assert_eq!(&mock_buffer.write_calls[5], "# TYPE ");
        assert_eq!(&mock_buffer.write_calls[6], "count");
        assert_eq!(&mock_buffer.write_calls[7], " ");
        assert_eq!(&mock_buffer.write_calls[8], "gauge");
        assert_eq!(&mock_buffer.write_calls[9], "\n");
        assert_eq!(&mock_buffer.write_calls[10], "count");
        assert_eq!(&mock_buffer.write_calls[11], " ");
        assert_eq!(&mock_buffer.write_calls[12], "3");
        assert_eq!(&mock_buffer.write_calls[13], "\n");
    }
}
<commit_msg>Rename to a non-reserved ID<commit_after>use prometheus::{Registry, Gauge, Encoder, TextEncoder};

use super::*;
pub struct PrometheusRenderer<'a> {
    pub buffer: &'a mut Write,
    registry: prometheus::Registry,
    encoder: prometheus::TextEncoder,
    count: prometheus::Gauge,
}

impl<'a> PrometheusRenderer<'a> {
    pub fn new(stream: &'a mut Write) -> PrometheusRenderer<'a> {
        let registry = prometheus::Registry::new();

        let count = prometheus::Gauge::new("request_count", "The number of responses observed")
            .unwrap();

        registry.register(Box::new(count.clone()));

        PrometheusRenderer {
            registry: registry,
            buffer: stream,
            encoder: prometheus::TextEncoder::new(),
            count: count,
        }
    }
}

impl<'a> Renderer for PrometheusRenderer<'a> {
    fn render(&mut self, result: analyzer::RequestLogAnalyzerResult) {
        self.count.set(result.count as f64);

        let metric_familys = self.registry.gather();

        self.encoder.encode(&metric_familys, self.buffer);
    }
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::prelude::*;
    use std::str;

    use super::*;

    struct MockBuffer {
        write_calls: Vec<String>,
    }

    impl Write for MockBuffer {
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
            self.write_calls.push(str::from_utf8(buf).unwrap().to_string());
            Ok(buf.len())
        }

        fn flush(&mut self) -> io::Result<()> {
            Ok(())
        }
    }

    fn get_result_fixture() -> analyzer::RequestLogAnalyzerResult {
        analyzer::RequestLogAnalyzerResult {
            count: 3,
            max: 100,
            min: 1,
            avg: 37,
            median: 10,
            percentile90: 100,
        }
    }

    #[test]
    fn test_instantiation() {
        let mut mock_buffer = MockBuffer { write_calls: vec![] };

        let renderer = PrometheusRenderer::new(&mut mock_buffer);
    }

    #[test]
    fn test_render() {
        let mut mock_buffer = MockBuffer { write_calls: vec![] };

        let result = get_result_fixture();

        {
            let mut renderer = PrometheusRenderer::new(&mut mock_buffer);

            renderer.render(result);
        }

        println!("{:?}", mock_buffer.write_calls);

        assert_eq!(&mock_buffer.write_calls[0], "# HELP ");
        assert_eq!(&mock_buffer.write_calls[1], "request_count");
        assert_eq!(&mock_buffer.write_calls[2], " ");
        assert_eq!(&mock_buffer.write_calls[3],
                   "The number of responses observed");
        assert_eq!(&mock_buffer.write_calls[4], "\n");
        assert_eq!(&mock_buffer.write_calls[5], "# TYPE ");
        assert_eq!(&mock_buffer.write_calls[6], "request_count");
        assert_eq!(&mock_buffer.write_calls[7], " ");
        assert_eq!(&mock_buffer.write_calls[8], "gauge");
        assert_eq!(&mock_buffer.write_calls[9], "\n");
        assert_eq!(&mock_buffer.write_calls[10], "request_count");
        assert_eq!(&mock_buffer.write_calls[11], " ");
        assert_eq!(&mock_buffer.write_calls[12], "3");
        assert_eq!(&mock_buffer.write_calls[13], "\n");
    }
}
<|endoftext|>


<commit_before>use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{BuildHasherDefault, Hash};

use utils::HashIter;

/// Abstract, but safe counter.
pub trait Counter: Copy + fmt::Debug + Ord + Sized {
    /// Add self to another counter.
    ///
    /// Returns `Some(Self)` when the addition was successfull (i.e. no overflow occured) and
    /// `None` in case of an error.
    fn checked_add(self, other: Self) -> Option<Self>;

    /// Return a counter representing zero.
    fn zero() -> Self;

    /// Return a counter representing one.
    fn one() -> Self;

    /// Checks whether the counter is zero.
    fn is_zero(&self) -> bool;
}

macro_rules! impl_counter {
    ($t:ty) => {
        impl Counter for $t {
            #[inline]
            fn checked_add(self, other: Self) -> Option<Self> {
                self.checked_add(other)
            }

            #[inline]
            fn zero() -> Self {
                0
            }

            #[inline]
            fn one() -> Self {
                1
            }

            #[inline]
            fn is_zero(&self) -> bool {
                *self == 0
            }
        }
    }
}

impl_counter!(usize);
impl_counter!(u64);
impl_counter!(u32);
impl_counter!(u16);
impl_counter!(u8);

/// Simple implementation of a
/// [Count-min sketch](https://en.wikipedia.org/wiki/Count%E2%80%93min_sketch)
///
/// The type parameter `C` sets the type of the counter in the internal table and can be used to
/// reduce memory consumption when low counts are expected.
#[derive(Clone)]
pub struct CountMinSketch<C = usize>
where
    C: Counter,
{
    table: Vec<C>,
    w: usize,
    d: usize,
}

impl<C> CountMinSketch<C>
where
    C: Counter,
{
    /// Create new CountMinSketch based on table size.
    ///
    /// - `w` sets the number of columns
    /// - `d` sets the number of rows
    pub fn with_params(w: usize, d: usize) -> CountMinSketch<C> {
        let table = vec![C::zero(); w.checked_mul(d).unwrap()];
        CountMinSketch {
            table: table,
            w: w,
            d: d,
        }
    }

    /// Get number of columns of internal counter table.
    pub fn w(&self) -> usize {
        self.w
    }

    /// Get number of rows of internal counter table.
    pub fn d(&self) -> usize {
        self.d
    }

    /// Check whether the CountMinSketch is empty (i.e. no elements seen yet).
    pub fn is_empty(&self) -> bool {
        self.table.iter().all(|x| x.is_zero())
    }

    /// Add one to the counter of the given element.
    pub fn add<T>(&mut self, obj: &T)
    where
        T: Hash,
    {
        self.add_n(&obj, C::one())
    }

    /// Add `n` to the counter of the given element.
    pub fn add_n<T>(&mut self, obj: &T, n: C)
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        for (i, pos) in HashIter::new(self.w, self.d, obj, bh).enumerate() {
            let x = i * self.w + pos;
            self.table[x] = self.table[x].checked_add(n).unwrap();
        }
    }

    /// Runs a point query, i.e. a query for the count of a single object.
    pub fn query_point<T>(&self, obj: &T) -> C
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        HashIter::new(self.w, self.d, obj, bh)
            .enumerate()
            .map(|(i, pos)| i * self.w + pos)
            .map(|x| self.table[x])
            .min()
            .unwrap()
    }

    /// Merge self with another CountMinSketch.
    ///
    /// After this operation `self` will be in the same state as when it would have seen all
    /// elements from `self` and `other`.
    ///
    /// Panics when `d` and `w` from `self` and `other` differ.
    pub fn merge(&mut self, other: &CountMinSketch<C>) {
        assert_eq!(self.d, other.d);
        assert_eq!(self.w, other.w);

        self.table = self.table
            .iter()
            .zip(other.table.iter())
            .map(|x| x.0.checked_add(*x.1).unwrap())
            .collect();
    }

    /// Clear internal counters to a fresh state (i.e. no objects seen).
    pub fn clear(&mut self) {
        self.table = vec![C::zero(); self.w.checked_mul(self.d).unwrap()];
    }
}

impl fmt::Debug for CountMinSketch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "CountMinSketch {{ w: {}, d: {} }}", self.w, self.d)
    }
}

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

    #[test]
    fn getter() {
        let cms = CountMinSketch::<usize>::with_params(10, 20);
        assert_eq!(cms.w(), 10);
        assert_eq!(cms.d(), 20);
    }

    #[test]
    fn empty() {
        let cms = CountMinSketch::<usize>::with_params(10, 10);
        assert_eq!(cms.query_point(&1), 0);
        assert!(cms.is_empty());
    }

    #[test]
    fn add_1() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2_1a() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&2);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 1);
        assert_eq!(cms.query_point(&3), 0);
    }

    #[test]
    fn add_2_1b() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add_n(&1, 2);
        cms.add(&2);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 1);
        assert_eq!(cms.query_point(&3), 0);
    }

    #[test]
    fn merge() {
        let mut cms1 = CountMinSketch::<usize>::with_params(10, 10);
        let mut cms2 = CountMinSketch::<usize>::with_params(10, 10);

        cms1.add_n(&1, 1);
        cms1.add_n(&2, 2);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 2);
        assert_eq!(cms1.query_point(&3), 0);
        assert_eq!(cms1.query_point(&4), 0);

        cms2.add_n(&2, 20);
        cms2.add_n(&3, 30);
        assert_eq!(cms2.query_point(&1), 0);
        assert_eq!(cms2.query_point(&2), 20);
        assert_eq!(cms2.query_point(&3), 30);
        assert_eq!(cms2.query_point(&4), 0);

        cms1.merge(&cms2);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 22);
        assert_eq!(cms1.query_point(&3), 30);
        assert_eq!(cms1.query_point(&4), 0);
    }

    #[test]
    fn clear() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert!(!cms.is_empty());

        cms.clear();
        assert_eq!(cms.query_point(&1), 0);
        assert!(cms.is_empty());
    }

    #[test]
    fn clone() {
        let mut cms1 = CountMinSketch::<usize>::with_params(10, 10);

        cms1.add(&1);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 0);

        let cms2 = cms1.clone();
        assert_eq!(cms2.query_point(&1), 1);
        assert_eq!(cms2.query_point(&2), 0);

        cms1.add(&1);
        assert_eq!(cms1.query_point(&1), 2);
        assert_eq!(cms1.query_point(&2), 0);
        assert_eq!(cms2.query_point(&1), 1);
        assert_eq!(cms2.query_point(&2), 0);
    }

    #[test]
    fn debug() {
        let cms = CountMinSketch::<usize>::with_params(10, 20);
        assert_eq!(format!("{:?}", cms), "CountMinSketch { w: 10, d: 20 }");
    }
}
<commit_msg>countminsketch: impl parameter calculation<commit_after>use std::collections::hash_map::DefaultHasher;
use std::f64;
use std::fmt;
use std::hash::{BuildHasherDefault, Hash};

use utils::HashIter;

/// Abstract, but safe counter.
pub trait Counter: Copy + fmt::Debug + Ord + Sized {
    /// Add self to another counter.
    ///
    /// Returns `Some(Self)` when the addition was successfull (i.e. no overflow occured) and
    /// `None` in case of an error.
    fn checked_add(self, other: Self) -> Option<Self>;

    /// Return a counter representing zero.
    fn zero() -> Self;

    /// Return a counter representing one.
    fn one() -> Self;

    /// Checks whether the counter is zero.
    fn is_zero(&self) -> bool;
}

macro_rules! impl_counter {
    ($t:ty) => {
        impl Counter for $t {
            #[inline]
            fn checked_add(self, other: Self) -> Option<Self> {
                self.checked_add(other)
            }

            #[inline]
            fn zero() -> Self {
                0
            }

            #[inline]
            fn one() -> Self {
                1
            }

            #[inline]
            fn is_zero(&self) -> bool {
                *self == 0
            }
        }
    }
}

impl_counter!(usize);
impl_counter!(u64);
impl_counter!(u32);
impl_counter!(u16);
impl_counter!(u8);

/// Simple implementation of a
/// [Count-min sketch](https://en.wikipedia.org/wiki/Count%E2%80%93min_sketch)
///
/// The type parameter `C` sets the type of the counter in the internal table and can be used to
/// reduce memory consumption when low counts are expected.
#[derive(Clone)]
pub struct CountMinSketch<C = usize>
where
    C: Counter,
{
    table: Vec<C>,
    w: usize,
    d: usize,
}

impl<C> CountMinSketch<C>
where
    C: Counter,
{
    /// Create new CountMinSketch based on table size.
    ///
    /// - `w` sets the number of columns
    /// - `d` sets the number of rows
    pub fn with_params(w: usize, d: usize) -> CountMinSketch<C> {
        let table = vec![C::zero(); w.checked_mul(d).unwrap()];
        CountMinSketch {
            table: table,
            w: w,
            d: d,
        }
    }

    /// Create new CountMinSketch with the following properties for a point query:
    ///
    /// - `a` is the real count of observed objects
    /// - `a'` is the guessed count of observed objects
    /// - `N` is the total count in the internal table
    /// - `a <= a'` always holds
    /// - `a' <= a + epsilon * N` holds with `p > 1 - delta`
    ///
    /// The following conditions must hold:
    ///
    /// - `epsilon > 0`
    /// - `delta > 0` and `delta < 1`
    ///
    /// Panics when the input conditions do not hold.
    pub fn with_point_query_properties(epsilon: f64, delta: f64) -> CountMinSketch<C> {
        assert!(epsilon > 0.);
        assert!(delta > 0.);
        assert!(delta < 1.);

        let w = (f64::consts::E / epsilon).ceil() as usize;
        let d = (1. / delta).ln().ceil() as usize;
        CountMinSketch::<C>::with_params(w, d)
    }

    /// Get number of columns of internal counter table.
    pub fn w(&self) -> usize {
        self.w
    }

    /// Get number of rows of internal counter table.
    pub fn d(&self) -> usize {
        self.d
    }

    /// Check whether the CountMinSketch is empty (i.e. no elements seen yet).
    pub fn is_empty(&self) -> bool {
        self.table.iter().all(|x| x.is_zero())
    }

    /// Add one to the counter of the given element.
    pub fn add<T>(&mut self, obj: &T)
    where
        T: Hash,
    {
        self.add_n(&obj, C::one())
    }

    /// Add `n` to the counter of the given element.
    pub fn add_n<T>(&mut self, obj: &T, n: C)
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        for (i, pos) in HashIter::new(self.w, self.d, obj, bh).enumerate() {
            let x = i * self.w + pos;
            self.table[x] = self.table[x].checked_add(n).unwrap();
        }
    }

    /// Runs a point query, i.e. a query for the count of a single object.
    pub fn query_point<T>(&self, obj: &T) -> C
    where
        T: Hash,
    {
        let bh = BuildHasherDefault::<DefaultHasher>::default();
        HashIter::new(self.w, self.d, obj, bh)
            .enumerate()
            .map(|(i, pos)| i * self.w + pos)
            .map(|x| self.table[x])
            .min()
            .unwrap()
    }

    /// Merge self with another CountMinSketch.
    ///
    /// After this operation `self` will be in the same state as when it would have seen all
    /// elements from `self` and `other`.
    ///
    /// Panics when `d` and `w` from `self` and `other` differ.
    pub fn merge(&mut self, other: &CountMinSketch<C>) {
        assert_eq!(self.d, other.d);
        assert_eq!(self.w, other.w);

        self.table = self.table
            .iter()
            .zip(other.table.iter())
            .map(|x| x.0.checked_add(*x.1).unwrap())
            .collect();
    }

    /// Clear internal counters to a fresh state (i.e. no objects seen).
    pub fn clear(&mut self) {
        self.table = vec![C::zero(); self.w.checked_mul(self.d).unwrap()];
    }
}

impl fmt::Debug for CountMinSketch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "CountMinSketch {{ w: {}, d: {} }}", self.w, self.d)
    }
}

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

    #[test]
    fn getter() {
        let cms = CountMinSketch::<usize>::with_params(10, 20);
        assert_eq!(cms.w(), 10);
        assert_eq!(cms.d(), 20);
    }

    #[test]
    fn properties() {
        let cms = CountMinSketch::<usize>::with_point_query_properties(0.01, 0.1);
        assert_eq!(cms.w(), 272);
        assert_eq!(cms.d(), 3);
    }

    #[test]
    fn empty() {
        let cms = CountMinSketch::<usize>::with_params(10, 10);
        assert_eq!(cms.query_point(&1), 0);
        assert!(cms.is_empty());
    }

    #[test]
    fn add_1() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 0);
    }

    #[test]
    fn add_2_1a() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        cms.add(&2);
        cms.add(&1);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 1);
        assert_eq!(cms.query_point(&3), 0);
    }

    #[test]
    fn add_2_1b() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add_n(&1, 2);
        cms.add(&2);
        assert_eq!(cms.query_point(&1), 2);
        assert_eq!(cms.query_point(&2), 1);
        assert_eq!(cms.query_point(&3), 0);
    }

    #[test]
    fn merge() {
        let mut cms1 = CountMinSketch::<usize>::with_params(10, 10);
        let mut cms2 = CountMinSketch::<usize>::with_params(10, 10);

        cms1.add_n(&1, 1);
        cms1.add_n(&2, 2);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 2);
        assert_eq!(cms1.query_point(&3), 0);
        assert_eq!(cms1.query_point(&4), 0);

        cms2.add_n(&2, 20);
        cms2.add_n(&3, 30);
        assert_eq!(cms2.query_point(&1), 0);
        assert_eq!(cms2.query_point(&2), 20);
        assert_eq!(cms2.query_point(&3), 30);
        assert_eq!(cms2.query_point(&4), 0);

        cms1.merge(&cms2);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 22);
        assert_eq!(cms1.query_point(&3), 30);
        assert_eq!(cms1.query_point(&4), 0);
    }

    #[test]
    fn clear() {
        let mut cms = CountMinSketch::<usize>::with_params(10, 10);

        cms.add(&1);
        assert_eq!(cms.query_point(&1), 1);
        assert!(!cms.is_empty());

        cms.clear();
        assert_eq!(cms.query_point(&1), 0);
        assert!(cms.is_empty());
    }

    #[test]
    fn clone() {
        let mut cms1 = CountMinSketch::<usize>::with_params(10, 10);

        cms1.add(&1);
        assert_eq!(cms1.query_point(&1), 1);
        assert_eq!(cms1.query_point(&2), 0);

        let cms2 = cms1.clone();
        assert_eq!(cms2.query_point(&1), 1);
        assert_eq!(cms2.query_point(&2), 0);

        cms1.add(&1);
        assert_eq!(cms1.query_point(&1), 2);
        assert_eq!(cms1.query_point(&2), 0);
        assert_eq!(cms2.query_point(&1), 1);
        assert_eq!(cms2.query_point(&2), 0);
    }

    #[test]
    fn debug() {
        let cms = CountMinSketch::<usize>::with_params(10, 20);
        assert_eq!(format!("{:?}", cms), "CountMinSketch { w: 10, d: 20 }");
    }
}
<|endoftext|>


<commit_before>use clap::Arg;
use clap::App;
use clap::ArgMatches;
use autoconf;

pub fn cli_clap(number: &u32) -> ArgMatches {

    let application = App::new(autoconf::package())
        .about("Parses an input file to do awesome things")
        .version(autoconf::version_cli())
        .author("Owen Synge <osynge@googlemail.com>")
        .arg(
            Arg::with_name("verbose")
                .help("Increase log output.")
                .short("v")
                .multiple(true)
                .long("verbose"),
        )
        .arg(
            Arg::with_name("quiet")
                .help("Decrease log output.")
                .short("q")
                .multiple(true)
                .long("quiet"),
        )
        .arg(
            Arg::with_name("rdbms")
                .long("rdbms")
                .value_name("FILE_RDBMS")
                .help("sqlite rdbms file.")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("env")
                .short("e")
                .long("env")
                .value_name("ENVIROMENT_VARIABLE")
                .help("Which enviroment variables to process")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("dir-jobs")
                .long("dir-jobs")
                .value_name("DIR_JOB")
                .help("directory storing json jobs.")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("dir-sh")
                .long("dir-sh")
                .value_name("DIR_SHELL")
                .help("directory storing jobs shell scripts.")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("dir-py")
                .long("dir-py")
                .value_name("DIR_PYTHON")
                .help("directory storing jobs python scripts.")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("config")
                .short("c")
                .long("config")
                .value_name("FILE")
                .help("Sets a custom config file")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("target")
                .short("t")
                .long("target")
                .value_name("TARGET")
                .help("Sets the provider to be selected.")
                .takes_value(true),
        )
        .arg(Arg::with_name("list-provides").long("list-provides").help(
            "list-provides",
        ))
        .arg(Arg::with_name("session").long("session").help("session"));
    let matches = application.get_matches();
    return matches;
}
<commit_msg>Feature add list-target<commit_after>use clap::Arg;
use clap::App;
use clap::ArgMatches;
use autoconf;

pub fn cli_clap(number: &u32) -> ArgMatches {

    let application = App::new(autoconf::package())
        .about("Parses an input file to do awesome things")
        .version(autoconf::version_cli())
        .author("Owen Synge <osynge@googlemail.com>")
        .arg(
            Arg::with_name("verbose")
                .help("Increase log output.")
                .short("v")
                .multiple(true)
                .long("verbose"),
        )
        .arg(
            Arg::with_name("quiet")
                .help("Decrease log output.")
                .short("q")
                .multiple(true)
                .long("quiet"),
        )
        .arg(
            Arg::with_name("rdbms")
                .long("rdbms")
                .value_name("FILE_RDBMS")
                .help("sqlite rdbms file.")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("env")
                .short("e")
                .long("env")
                .value_name("ENVIROMENT_VARIABLE")
                .help("Which enviroment variables to process")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("dir-jobs")
                .long("dir-jobs")
                .value_name("DIR_JOB")
                .help("directory storing json jobs.")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("dir-sh")
                .long("dir-sh")
                .value_name("DIR_SHELL")
                .help("directory storing jobs shell scripts.")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("dir-py")
                .long("dir-py")
                .value_name("DIR_PYTHON")
                .help("directory storing jobs python scripts.")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("config")
                .short("c")
                .long("config")
                .value_name("FILE")
                .help("Sets a custom config file")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("target")
                .short("t")
                .long("target")
                .value_name("TARGET")
                .help("Sets the provider to be selected.")
                .takes_value(true),
        )
        .arg(Arg::with_name("list-provides").long("list-provides").help(
            "list-provides",
        ))
        .arg(Arg::with_name("list-target").long("list-target").help(
            "list all targets",
        ))
        .arg(Arg::with_name("session").long("session").help("session"));
    let matches = application.get_matches();
    return matches;
}
<|endoftext|>


<commit_before>use std::borrow::Cow::Borrowed;
use std::borrow::Cow;
use std::fmt;

#[derive(Debug, Clone, PartialEq)]
pub struct NumberValue<'a> {
    pub scalar:   f32,
    pub unit:     Option<Cow<'a, str>>,
    pub computed: bool,
}

impl<'a, 'b> NumberValue<'a> {
    pub fn from_scalar(num: f32) -> NumberValue<'a> {
        NumberValue {
            scalar:   num,
            unit:     None,
            computed: false,
        }
    }

    #[cfg(test)]
    pub fn computed(num: f32) -> NumberValue<'a> {
        NumberValue {
            scalar:   num,
            unit:     None,
            computed: true,
        }
    }

    pub fn with_units(num: f32, unit: Cow<'a, str>) -> NumberValue<'a> {
        NumberValue {
            scalar:   num,
            unit:     Some(unit),
            computed: false,
        }
    }

    pub fn into_owned(self) -> NumberValue<'b> {
        NumberValue {
            scalar: self.scalar,
            unit: match self.unit {
                Some(u) => Some(u.into_owned().into()),
                None => None,
            },
            computed: self.computed,
        }
    }

}

impl<'a> fmt::Display for NumberValue<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{}", self.scalar, self.unit.clone().unwrap_or(Borrowed("")))
    }
}
<commit_msg>Make printing number values a bit nicer<commit_after>use std::borrow::Cow::*;
use std::borrow::Cow;
use std::fmt;

#[derive(Debug, Clone, PartialEq)]
pub struct NumberValue<'a> {
    pub scalar:   f32,
    pub unit:     Option<Cow<'a, str>>,
    pub computed: bool,
}

impl<'a, 'b> NumberValue<'a> {
    pub fn from_scalar(num: f32) -> NumberValue<'a> {
        NumberValue {
            scalar:   num,
            unit:     None,
            computed: false,
        }
    }

    #[cfg(test)]
    pub fn computed(num: f32) -> NumberValue<'a> {
        NumberValue {
            scalar:   num,
            unit:     None,
            computed: true,
        }
    }

    pub fn with_units(num: f32, unit: Cow<'a, str>) -> NumberValue<'a> {
        NumberValue {
            scalar:   num,
            unit:     Some(unit),
            computed: false,
        }
    }

    pub fn into_owned(self) -> NumberValue<'b> {
        NumberValue {
            scalar: self.scalar,
            unit: match self.unit {
                Some(u) => Some(u.into_owned().into()),
                None => None,
            },
            computed: self.computed,
        }
    }

    pub fn unit_string(&self) -> &str {
        match self.unit {
            Some(Borrowed(ref b)) => b,
            Some(Owned(ref o))    => o,
            None                  => "",
        }
    }
}

impl<'a> fmt::Display for NumberValue<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{}", self.scalar, self.unit_string())
    }
}
<|endoftext|>


<commit_before>// use std::io;
// use std::io::Write;

use rustbox::{RustBox};
use termbox_sys::tb_change_cell;
use termbox_sys;

use tui::style;

/// A single line added to the widget. May be rendered as multiple lines on the
/// screen.
#[derive(Debug)]
pub struct Line {
    /// Note that this String may not be directly renderable - TODO: explain.
    str       : String,

    /// Number of _visible_ (i.e. excludes color encodings) characters in the
    /// line.
    len_chars : i32,

    /// Visible char indexes (not counting color encodings) of split positions
    /// of the string - when the line doesn't fit into the screen we split it
    /// into multiple lines using these.
    ///
    /// It's important that these are really indices ignoring invisible chars,
    /// as we use difference between two indices in this vector as length of
    /// substrings.
    splits    : Vec<i32>,
}

impl Line {
    pub fn new() -> Line {
        Line {
            str: String::new(),
            len_chars: 0,
            splits: Vec::new(),
        }
    }

    pub fn add_text(&mut self, str : &str) {
        self.str.reserve(str.len());

        let mut iter = str.chars();
        while let Some(mut char) = iter.next() {
            if char == style::COLOR_PREFIX {
                self.str.push(char);
                // read fg
                self.str.push(iter.next().unwrap());
                self.str.push(iter.next().unwrap());
                if let Some(mb_comma) = iter.next() {
                    if mb_comma == ',' {
                        self.str.push(mb_comma);
                        // read bg
                        self.str.push(iter.next().unwrap());
                        self.str.push(iter.next().unwrap());
                        continue;
                    } else {
                        char = mb_comma;
                    }
                } else {
                    break;
                }
            }

            if char == style::TERMBOX_COLOR_PREFIX {
                self.str.push(char);
                // read fg
                self.str.push(iter.next().unwrap());
                // read bg
                self.str.push(iter.next().unwrap());
            }

            else if char == style::RESET_PREFIX || char == style::BOLD_PREFIX {
                self.str.push(char);
            }

            // Ignore some chars that break the rendering. These are used by the
            // protocol.
            else if char > '\x07' {
                self.str.push(char);
                if char.is_whitespace() {
                    self.splits.push(self.len_chars);
                }
                self.len_chars += 1;
            }
        }
    }

    pub fn add_char(&mut self, char : char) {
        assert!(char != style::COLOR_PREFIX);
        if char.is_whitespace() {
            self.splits.push(self.len_chars);
        }
        self.str.push(char);
        self.len_chars += 1;
    }

    pub fn len_chars(&self) -> i32 {
        self.len_chars
    }

    /// How many lines does this take when rendered? O(n) where n = number of
    /// split positions in the lines (i.e.  whitespaces).
    pub fn rendered_height(&self, width : i32) -> i32 {
        let mut lines : i32 = 1;
        let mut line_start : i32 = 0;

        for split_idx in 0 .. self.splits.len() {
            let char_idx = *unsafe { self.splits.get_unchecked(split_idx) };
            // writeln!(io::stderr(), "rendered_height: char_idx: {}", char_idx);
            let col = char_idx - line_start;

            // How many more chars can we render in this line?
            let slots_in_line : i32 = width - (col + 1);

            // How many chars do we need to render if until the next split
            // point?
            let chars_until_next_split : i32 =
                // -1 because we don't need to render the space or EOL.
                *self.splits.get(split_idx + 1).unwrap_or(&self.len_chars) - 1 - char_idx;

            // writeln!(io::stderr(),
            //          "rendered_height: slots_in_line: {}, chars_until_next_split: {}",
            //          slots_in_line, chars_until_next_split);

            if (chars_until_next_split as i32) > slots_in_line {
                // writeln!(io::stderr(), "splitting at {}", char_idx);
                lines += 1;
                line_start = char_idx + 1;
            }
        }

        lines
    }

    #[inline]
    pub fn draw(&self, rustbox : &RustBox, pos_x : i32, pos_y : i32, width : i32) {
        self.draw_from(rustbox, pos_x, pos_y, 0, width);
    }

    pub fn draw_from(&self, _ : &RustBox, pos_x : i32, pos_y : i32, first_line : i32, width : i32) {
        let mut col = pos_x;
        let mut line = 0;

        let mut next_split_idx : usize = 0;

        let mut char_idx : i32 = 0;

        let mut fg : u16 = 0;
        let mut bg : u16 = 0;

        let mut iter = self.str.chars();
        while let Some(mut char) = iter.next() {
            if char == style::COLOR_PREFIX {
                let fg_1 = to_dec(iter.next().unwrap()) as u16;
                let fg_2 = to_dec(iter.next().unwrap()) as u16;
                // We 'or' here as 'fg' can have 'bold' value
                fg |= irc_color_to_termbox(fg_1 * 10 + fg_2);

                if let Some(char_) = iter.next() {
                    if char_ == ',' {
                        let bg_1 = to_dec(iter.next().unwrap()) as u16;
                        let bg_2 = to_dec(iter.next().unwrap()) as u16;
                        bg = irc_color_to_termbox(bg_1 * 10 + bg_2);
                        continue;
                    } else {
                        bg = 0;
                        char = char_;
                    }
                }
            } else if char == style::TERMBOX_COLOR_PREFIX {
                fg = iter.next().unwrap() as u16;
                bg = iter.next().unwrap() as u16;
                continue;
            } else if char == style::BOLD_PREFIX {
                fg |= termbox_sys::TB_BOLD;
                continue;
            } else if char == style::RESET_PREFIX {
                fg = 0;
                bg = 0;
                continue;
            }

            if char.is_whitespace() {
                // We may want to move to the next line
                next_split_idx += 1;
                let next_split = self.splits.get(next_split_idx).unwrap_or(&self.len_chars);

                // How many more chars can we render in this line?
                let slots_in_line = width - (col - pos_x);

                // How many chars do we need to render if until the next
                // split point?
                assert!(*next_split > char_idx);
                let chars_until_next_split : i32 = *next_split - char_idx;

                // writeln!(io::stderr(), "chars_until_next_split: {}, slots_in_line: {}",
                //          chars_until_next_split, slots_in_line);

                if (chars_until_next_split as i32) <= slots_in_line {
                    // keep rendering chars
                    if line >= first_line {
                        unsafe { tb_change_cell(col, pos_y + line, char as u32, fg, bg); }
                    }
                    col += 1;
                } else {
                    // need to split here. ignore whitespace char.
                    line += 1;
                    col = pos_x;
                }

                char_idx += 1;
            }

            else {
                // Not possible to split. Need to make sure we don't render out
                // of bounds.
                if col - pos_x < width {
                    if line >= first_line {
                        unsafe { tb_change_cell(col, pos_y + line, char as u32, fg, bg); }
                    }
                    col += 1;
                }

                char_idx += 1;
            }
        }
    }
}

#[inline]
pub fn to_dec(ch : char) -> i8 {
    ((ch as u32) - ('0' as u32)) as i8
}

// IRC colors: http://en.wikichip.org/wiki/irc/colors
// Termbox colors: http://www.calmar.ws/vim/256-xterm-24bit-rgb-color-chart.html
fn irc_color_to_termbox(irc_color : u16) -> u16 {
    match irc_color {
         0 => 15,  // white
         1 => 0,   // black
         2 => 17,  // navy
         3 => 2,   // green
         4 => 9,   // red
         5 => 88,  // maroon
         6 => 5,   // purple
         7 => 130, // olive
         8 => 11,  // yellow
         9 => 10,  // light green
        10 => 6,   // teal
        11 => 14,  // cyan
        12 => 12,  // awful blue
        13 => 13,  // magenta
        14 => 8,   // gray
        15 => 7,   // light gray

        // The rest is directly mapped to termbox colors.
        _  => irc_color,
    }
}

////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {

extern crate test;

use self::test::Bencher;
use std::fs::File;
use std::io::Read;
use super::*;

#[test]
fn height_test_1() {
    let mut line = Line::new();
    line.add_text("a b c d e");
    assert_eq!(line.rendered_height(1), 5);
    assert_eq!(line.rendered_height(2), 5);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 3);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 2);
    assert_eq!(line.rendered_height(8), 2);
    assert_eq!(line.rendered_height(9), 1);
}

#[test]
fn height_test_2() {
    let mut line = Line::new();
    line.add_text("ab c d e");
    assert_eq!(line.rendered_height(1), 4);
    assert_eq!(line.rendered_height(2), 4);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 2);
    assert_eq!(line.rendered_height(8), 1);
}

#[test]
fn height_test_3() {
    let mut line = Line::new();
    line.add_text("ab cd e");
    assert_eq!(line.rendered_height(1), 3);
    assert_eq!(line.rendered_height(2), 3);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 1);
}

#[test]
fn height_test_4() {
    let mut line = Line::new();
    line.add_text("ab cde");
    assert_eq!(line.rendered_height(1), 2);
    assert_eq!(line.rendered_height(2), 2);
    assert_eq!(line.rendered_height(3), 2);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 1);
}

#[test]
fn height_test_5() {
    let mut line = Line::new();
    line.add_text("abcde");
    for i in 0 .. 6 {
        assert_eq!(line.rendered_height(i), 1);
    }
}

#[bench]
fn bench_rendered_height(b : &mut Bencher) {

    // 1160 words, 2,237 ns/iter (+/- 150)

    let mut text = String::new();
    {
        let mut file = File::open("test/lipsum.txt").unwrap();
        file.read_to_string(&mut text).unwrap();
    }

    let mut line = Line::new();
    line.add_text(&text);
    b.iter(|| {
        line.rendered_height(1)
    });
}

} // mod tests
<commit_msg>fix color code rendering logic<commit_after>// use std::io;
// use std::io::Write;

use rustbox::{RustBox};
use termbox_sys::tb_change_cell;
use termbox_sys;

use tui::style;

/// A single line added to the widget. May be rendered as multiple lines on the
/// screen.
#[derive(Debug)]
pub struct Line {
    /// Note that this String may not be directly renderable - TODO: explain.
    str       : String,

    /// Number of _visible_ (i.e. excludes color encodings) characters in the
    /// line.
    len_chars : i32,

    /// Visible char indexes (not counting color encodings) of split positions
    /// of the string - when the line doesn't fit into the screen we split it
    /// into multiple lines using these.
    ///
    /// It's important that these are really indices ignoring invisible chars,
    /// as we use difference between two indices in this vector as length of
    /// substrings.
    splits    : Vec<i32>,
}

impl Line {
    pub fn new() -> Line {
        Line {
            str: String::new(),
            len_chars: 0,
            splits: Vec::new(),
        }
    }

    pub fn add_text(&mut self, str : &str) {
        self.str.reserve(str.len());

        let mut iter = str.chars();
        while let Some(mut char) = iter.next() {
            if char == style::COLOR_PREFIX {
                self.str.push(char);
                // read fg
                self.str.push(iter.next().unwrap());
                self.str.push(iter.next().unwrap());
                if let Some(mb_comma) = iter.next() {
                    if mb_comma == ',' {
                        self.str.push(mb_comma);
                        // read bg
                        self.str.push(iter.next().unwrap());
                        self.str.push(iter.next().unwrap());
                        continue;
                    } else {
                        char = mb_comma;
                    }
                } else {
                    break;
                }
            }

            if char == style::TERMBOX_COLOR_PREFIX {
                self.str.push(char);
                // read fg
                self.str.push(iter.next().unwrap());
                // read bg
                self.str.push(iter.next().unwrap());
            }

            else if char == style::RESET_PREFIX || char == style::BOLD_PREFIX {
                self.str.push(char);
            }

            // Ignore some chars that break the rendering. These are used by the
            // protocol.
            else if char > '\x07' {
                self.str.push(char);
                if char.is_whitespace() {
                    self.splits.push(self.len_chars);
                }
                self.len_chars += 1;
            }
        }
    }

    pub fn add_char(&mut self, char : char) {
        assert!(char != style::COLOR_PREFIX);
        if char.is_whitespace() {
            self.splits.push(self.len_chars);
        }
        self.str.push(char);
        self.len_chars += 1;
    }

    pub fn len_chars(&self) -> i32 {
        self.len_chars
    }

    /// How many lines does this take when rendered? O(n) where n = number of
    /// split positions in the lines (i.e.  whitespaces).
    pub fn rendered_height(&self, width : i32) -> i32 {
        let mut lines : i32 = 1;
        let mut line_start : i32 = 0;

        for split_idx in 0 .. self.splits.len() {
            let char_idx = *unsafe { self.splits.get_unchecked(split_idx) };
            // writeln!(io::stderr(), "rendered_height: char_idx: {}", char_idx);
            let col = char_idx - line_start;

            // How many more chars can we render in this line?
            let slots_in_line : i32 = width - (col + 1);

            // How many chars do we need to render if until the next split
            // point?
            let chars_until_next_split : i32 =
                // -1 because we don't need to render the space or EOL.
                *self.splits.get(split_idx + 1).unwrap_or(&self.len_chars) - 1 - char_idx;

            // writeln!(io::stderr(),
            //          "rendered_height: slots_in_line: {}, chars_until_next_split: {}",
            //          slots_in_line, chars_until_next_split);

            if (chars_until_next_split as i32) > slots_in_line {
                // writeln!(io::stderr(), "splitting at {}", char_idx);
                lines += 1;
                line_start = char_idx + 1;
            }
        }

        lines
    }

    #[inline]
    pub fn draw(&self, rustbox : &RustBox, pos_x : i32, pos_y : i32, width : i32) {
        self.draw_from(rustbox, pos_x, pos_y, 0, width);
    }

    pub fn draw_from(&self, _ : &RustBox, pos_x : i32, pos_y : i32, first_line : i32, width : i32) {
        let mut col = pos_x;
        let mut line = 0;

        let mut next_split_idx : usize = 0;

        let mut char_idx : i32 = 0;

        let mut fg : u16 = 0;
        let mut bg : u16 = 0;

        let mut iter = self.str.chars();
        while let Some(mut char) = iter.next() {
            if char == style::COLOR_PREFIX {
                let fg_1 = to_dec(iter.next().unwrap()) as u16;
                let fg_2 = to_dec(iter.next().unwrap()) as u16;
                // We 'or' here as 'fg' can have 'bold' value
                fg |= irc_color_to_termbox(fg_1 * 10 + fg_2);

                if let Some(char_) = iter.next() {
                    if char_ == ',' {
                        let bg_1 = to_dec(iter.next().unwrap()) as u16;
                        let bg_2 = to_dec(iter.next().unwrap()) as u16;
                        bg = irc_color_to_termbox(bg_1 * 10 + bg_2);
                        continue;
                    } else {
                        bg = 0;
                        char = char_;
                    }
                } else {
                    break;
                }
            }

            if char == style::TERMBOX_COLOR_PREFIX {
                fg = iter.next().unwrap() as u16;
                bg = iter.next().unwrap() as u16;
                continue;
            } else if char == style::BOLD_PREFIX {
                fg |= termbox_sys::TB_BOLD;
                continue;
            } else if char == style::RESET_PREFIX {
                fg = 0;
                bg = 0;
                continue;
            }

            if char.is_whitespace() {
                // We may want to move to the next line
                next_split_idx += 1;
                let next_split = self.splits.get(next_split_idx).unwrap_or(&self.len_chars);

                // How many more chars can we render in this line?
                let slots_in_line = width - (col - pos_x);

                // How many chars do we need to render if until the next
                // split point?
                assert!(*next_split > char_idx);
                let chars_until_next_split : i32 = *next_split - char_idx;

                // writeln!(io::stderr(), "chars_until_next_split: {}, slots_in_line: {}",
                //          chars_until_next_split, slots_in_line);

                if (chars_until_next_split as i32) <= slots_in_line {
                    // keep rendering chars
                    if line >= first_line {
                        unsafe { tb_change_cell(col, pos_y + line, char as u32, fg, bg); }
                    }
                    col += 1;
                } else {
                    // need to split here. ignore whitespace char.
                    line += 1;
                    col = pos_x;
                }

                char_idx += 1;
            }

            else {
                // Not possible to split. Need to make sure we don't render out
                // of bounds.
                if col - pos_x < width {
                    if line >= first_line {
                        unsafe { tb_change_cell(col, pos_y + line, char as u32, fg, bg); }
                    }
                    col += 1;
                }

                char_idx += 1;
            }
        }
    }
}

#[inline]
pub fn to_dec(ch : char) -> i8 {
    ((ch as u32) - ('0' as u32)) as i8
}

// IRC colors: http://en.wikichip.org/wiki/irc/colors
// Termbox colors: http://www.calmar.ws/vim/256-xterm-24bit-rgb-color-chart.html
fn irc_color_to_termbox(irc_color : u16) -> u16 {
    match irc_color {
         0 => 15,  // white
         1 => 0,   // black
         2 => 17,  // navy
         3 => 2,   // green
         4 => 9,   // red
         5 => 88,  // maroon
         6 => 5,   // purple
         7 => 130, // olive
         8 => 11,  // yellow
         9 => 10,  // light green
        10 => 6,   // teal
        11 => 14,  // cyan
        12 => 12,  // awful blue
        13 => 13,  // magenta
        14 => 8,   // gray
        15 => 7,   // light gray

        // The rest is directly mapped to termbox colors.
        _  => irc_color,
    }
}

////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {

extern crate test;

use self::test::Bencher;
use std::fs::File;
use std::io::Read;
use super::*;

#[test]
fn height_test_1() {
    let mut line = Line::new();
    line.add_text("a b c d e");
    assert_eq!(line.rendered_height(1), 5);
    assert_eq!(line.rendered_height(2), 5);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 3);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 2);
    assert_eq!(line.rendered_height(8), 2);
    assert_eq!(line.rendered_height(9), 1);
}

#[test]
fn height_test_2() {
    let mut line = Line::new();
    line.add_text("ab c d e");
    assert_eq!(line.rendered_height(1), 4);
    assert_eq!(line.rendered_height(2), 4);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 2);
    assert_eq!(line.rendered_height(8), 1);
}

#[test]
fn height_test_3() {
    let mut line = Line::new();
    line.add_text("ab cd e");
    assert_eq!(line.rendered_height(1), 3);
    assert_eq!(line.rendered_height(2), 3);
    assert_eq!(line.rendered_height(3), 3);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 2);
    assert_eq!(line.rendered_height(7), 1);
}

#[test]
fn height_test_4() {
    let mut line = Line::new();
    line.add_text("ab cde");
    assert_eq!(line.rendered_height(1), 2);
    assert_eq!(line.rendered_height(2), 2);
    assert_eq!(line.rendered_height(3), 2);
    assert_eq!(line.rendered_height(4), 2);
    assert_eq!(line.rendered_height(5), 2);
    assert_eq!(line.rendered_height(6), 1);
}

#[test]
fn height_test_5() {
    let mut line = Line::new();
    line.add_text("abcde");
    for i in 0 .. 6 {
        assert_eq!(line.rendered_height(i), 1);
    }
}

#[bench]
fn bench_rendered_height(b : &mut Bencher) {

    // 1160 words, 2,237 ns/iter (+/- 150)

    let mut text = String::new();
    {
        let mut file = File::open("test/lipsum.txt").unwrap();
        file.read_to_string(&mut text).unwrap();
    }

    let mut line = Line::new();
    line.add_text(&text);
    b.iter(|| {
        line.rendered_height(1)
    });
}

} // mod tests
<|endoftext|>


<commit_before>macro_rules! unwrap_or_return_none{
    ($operand:expr) => {
        if let Some(x) = $operand {
            x
        } else {
            return None;
        }
    }
}

pub fn vbyte_encode(mut number: usize) -> Vec<u8> {
    let mut result = Vec::new();
    loop {
        result.insert(0, (number % 128) as u8);
        if number < 128 {
            break;
        } else {
            number /= 128;
        }
    }
    let len = result.len();
    result[len - 1] += 128;
    result
}

pub struct VByteDecoder<'a> {
    bytes: Box<Iterator<Item=u8> + 'a>
}

impl<'a> VByteDecoder<'a> {
    pub fn new<T: Iterator<Item=u8> + 'a>(bytes: T) -> Self {
        VByteDecoder { bytes: Box::new(bytes) }
    }

    pub fn underlying_iterator(&mut self) -> &mut Iterator<Item=u8> {
       &mut self.bytes
    }
}

impl<'a> Iterator for VByteDecoder<'a> {
    type Item = usize;
    fn next(&mut self) -> Option<Self::Item> {

        let mut result: usize = 0;
        loop {
            result *= 128;
            let val = unwrap_or_return_none!(self.bytes.next());
            result += val as usize;
            if val >= 128 {
                result -= 128;
                break;
            }
        }
        Some(result)
    }
}

#[test]
fn test_vbyte_encode() {
    assert_eq!(vbyte_encode(0), vec![0x80]);
    assert_eq!(vbyte_encode(5), vec![0x85]);
    assert_eq!(vbyte_encode(127), vec![0xFF]);
    assert_eq!(vbyte_encode(128), vec![0x01, 0x80]);
    assert_eq!(vbyte_encode(130), vec![0x01, 0x82]);
    assert_eq!(vbyte_encode(255), vec![0x01, 0xFF]);
    assert_eq!(vbyte_encode(20_000), vec![0x01, 0x1C, 0xA0]);
    assert_eq!(vbyte_encode(0xFFFF), vec![0x03, 0x7F, 0xFF]);
}

#[test]
fn test_vbyte_decode() {
    assert_eq!(VByteDecoder::new(vec![0x80].into_iter()).collect::<Vec<_>>(),
               vec![0]);
    assert_eq!(VByteDecoder::new(vec![0x85].into_iter()).collect::<Vec<_>>(),
               vec![5]);
    assert_eq!(VByteDecoder::new(vec![0xFF].into_iter()).collect::<Vec<_>>(),
               vec![127]);
    assert_eq!(VByteDecoder::new(vec![0x80, 0x81].into_iter()).collect::<Vec<_>>(),
               vec![0, 1]);
    assert_eq!(VByteDecoder::new(vec![0x03, 0x7F, 0xFF, 0x01, 0x82, 0x85].into_iter())
                   .collect::<Vec<_>>(),
               vec![0xFFFF, 130, 5]);
    assert_eq!(VByteDecoder::new(vec![0x80].into_iter()).collect::<Vec<_>>(),
               vec![0]);
}
<commit_msg>Add Documentation for variable byte encoding<commit_after>//! This module provides utility methods and structs for variable byte encoding
//!
//! Encode unsigned integers by using the `vbyte_encode` method
//! Decode a bytestream by instatiating a `VByteDecoder` and using its iterator implementation
//!
//! #Example
//!
//! ```
//! use perlin::utils::compression::*;
//!
//! let bytes = vbyte_encode(3);
//! let three = VByteDecoder::new(bytes.into_iter()).next().unwrap();
//! assert_eq!(3, three);
//! ```

///Encode an usigned integer as a variable number of bytes
///as described in the [IR-Book|http://nlp.stanford.edu/IR-book/html/htmledition/variable-byte-codes-1.html]
pub fn vbyte_encode(mut number: usize) -> Vec<u8> {
    let mut result = Vec::new();
    loop {
        result.insert(0, (number % 128) as u8);
        if number < 128 {
            break;
        } else {
            number /= 128;
        }
    }
    let len = result.len();
    result[len - 1] += 128;
    result
}

///Iterator that decodes a bytestream to unsigned integers
pub struct VByteDecoder<'a> {
    bytes: Box<Iterator<Item=u8> + 'a>
}

impl<'a> VByteDecoder<'a> {

    ///Create a new VByteDecoder by passing a bytestream
    pub fn new<T: Iterator<Item=u8> + 'a>(bytes: T) -> Self {
        VByteDecoder { bytes: Box::new(bytes) }
    }

    ///Sometimes it is convenient to look at the original bytestream itself
    ///(e.g. when not only vbyte encoded integers are in the bytestream)
    ///This method provides access to the underlying bytestream in form of a mutable borrow
    pub fn underlying_iterator(&mut self) -> &mut Iterator<Item=u8> {
       &mut self.bytes
    }
}

impl<'a> Iterator for VByteDecoder<'a> {
    type Item = usize;

    ///Returns the next unsigned integer which is encoded in the underlying bytestream
    ///May iterate the underlying bytestream an arbitrary number of times
    ///Returns None when the underlying bytream returns None
    fn next(&mut self) -> Option<Self::Item> {

        let mut result: usize = 0;
        loop {
            result *= 128;
            let val = try_option!(self.bytes.next());
            result += val as usize;
            if val >= 128 {
                result -= 128;
                break;
            }
        }
        Some(result)
    }
}

#[test]
fn test_vbyte_encode() {
    assert_eq!(vbyte_encode(0), vec![0x80]);
    assert_eq!(vbyte_encode(5), vec![0x85]);
    assert_eq!(vbyte_encode(127), vec![0xFF]);
    assert_eq!(vbyte_encode(128), vec![0x01, 0x80]);
    assert_eq!(vbyte_encode(130), vec![0x01, 0x82]);
    assert_eq!(vbyte_encode(255), vec![0x01, 0xFF]);
    assert_eq!(vbyte_encode(20_000), vec![0x01, 0x1C, 0xA0]);
    assert_eq!(vbyte_encode(0xFFFF), vec![0x03, 0x7F, 0xFF]);
}

#[test]
fn test_vbyte_decode() {
    assert_eq!(VByteDecoder::new(vec![0x80].into_iter()).collect::<Vec<_>>(),
               vec![0]);
    assert_eq!(VByteDecoder::new(vec![0x85].into_iter()).collect::<Vec<_>>(),
               vec![5]);
    assert_eq!(VByteDecoder::new(vec![0xFF].into_iter()).collect::<Vec<_>>(),
               vec![127]);
    assert_eq!(VByteDecoder::new(vec![0x80, 0x81].into_iter()).collect::<Vec<_>>(),
               vec![0, 1]);
    assert_eq!(VByteDecoder::new(vec![0x03, 0x7F, 0xFF, 0x01, 0x82, 0x85].into_iter())
                   .collect::<Vec<_>>(),
               vec![0xFFFF, 130, 5]);
    assert_eq!(VByteDecoder::new(vec![0x80].into_iter()).collect::<Vec<_>>(),
               vec![0]);
}
<|endoftext|>


<commit_before>use super::super::grid_loop::GridLoopField;
use super::super::{Grid, D, P};
use super::*;

use rand::Rng;
use FOUR_NEIGHBOURS;

pub fn generate<R: Rng>(
    height: i32,
    width: i32,
    disallow_dead_ends: bool,
    rng: &mut R,
) -> Option<Grid<Clue>> {
    let mut problem = Grid::new(height, width, Clue::NoClue);
    let mut current_score = 0i32;

    let n_steps = height * width * 10;
    let mut temperature = 10f64;
    let mut n_clues = 0;
    let mut has_clue = Grid::new(height, width, false);

    for _ in 0..n_steps {
        let mut update_cand = vec![];
        for y in 0..height {
            for x in 0..width {
                let pos = P(y, x);
                for i in 1..((y + 3) / 2) {
                    update_cand.push((pos, Clue::Up(i)));
                }
                for i in 1..((x + 3) / 2) {
                    update_cand.push((pos, Clue::Left(i)));
                }
                for i in 1..((height - y) / 2) {
                    update_cand.push((pos, Clue::Down(i)));
                }
                for i in 1..((width - x + 2) / 2) {
                    update_cand.push((pos, Clue::Right(i)));
                }
                if problem[pos] != Clue::NoClue {
                    update_cand.push((pos, Clue::NoClue));
                }
            }
        }
        rng.shuffle(&mut update_cand);

        let mut updated = false;

        for &(loc, clue) in &update_cand {
            let previous_clue = problem[loc];
            has_clue[loc] = clue != Clue::NoClue;
            if disallow_dead_ends && has_dead_end_nearby(loc, &has_clue) {
                has_clue[loc] = previous_clue != Clue::NoClue;
                continue;
            }

            problem[loc] = clue;

            let mut next_field = Field::new(&problem);
            next_field.trial_and_error(2);

            let new_n_clues = n_clues - if previous_clue == Clue::NoClue { 0 } else { 1 }
                + if clue == Clue::NoClue { 0 } else { 1 };

            let score = next_field.grid_loop().num_decided_edges() - new_n_clues * 25;
            let update = !next_field.inconsistent()
                && (current_score < score
                    || rng.gen::<f64>() < ((score - current_score) as f64 / temperature).exp());
            if update {
                current_score = score;
                updated = true;
                n_clues = new_n_clues;

                if next_field.fully_solved() {
                    return Some(problem);
                }
                break;
            } else {
                problem[loc] = previous_clue;
                has_clue[loc] = previous_clue != Clue::NoClue;
            }
        }

        if !updated {
            break;
        }

        temperature *= 0.995f64;
    }

    None
}

fn has_dead_end_nearby(loc: P, has_clue: &Grid<bool>) -> bool {
    return is_dead_end(loc, has_clue)
        || is_dead_end(loc + D(-1, 0), has_clue)
        || is_dead_end(loc + D(1, 0), has_clue)
        || is_dead_end(loc + D(0, -1), has_clue)
        || is_dead_end(loc + D(0, 1), has_clue);
}
fn is_dead_end(pos: P, has_clue: &Grid<bool>) -> bool {
    if !has_clue.is_valid_p(pos) {
        return false;
    }
    let mut neighbour_count = 0;
    for &d in &FOUR_NEIGHBOURS {
        if !has_clue.get_or_default_p(pos + d, true) {
            neighbour_count += 1;
        }
    }
    return neighbour_count <= 1;
}
<commit_msg>Yajilin: add GeneratorOption<commit_after>use super::super::grid_loop::GridLoopField;
use super::super::{Grid, D, P};
use super::*;

use rand::Rng;
use FOUR_NEIGHBOURS;

pub struct GeneratorOption {
    pub disallow_dead_ends: bool,
    pub disallow_adjacent_clues: bool,
    pub technique: Technique,
    pub search_depth: i32,
    pub clue_lower_bound: Option<i32>,
    pub clue_upper_bound: Option<i32>,
}

fn check_clue_range(i: i32, options: &GeneratorOption) -> bool {
    if let Some(n) = options.clue_lower_bound {
        if !(n <= i) {
            return false;
        }
    }
    if let Some(n) = options.clue_upper_bound {
        if !(i <= n) {
            return false;
        }
    }
    true
}

pub fn generate<R: Rng>(
    height: i32,
    width: i32,
    options: &GeneratorOption,
    rng: &mut R,
) -> Option<Grid<Clue>> {
    let mut problem = Grid::new(height, width, Clue::NoClue);
    let mut current_score = 0i32;

    let n_steps = height * width * 10;
    let mut temperature = 10f64;
    let mut n_clues = 0;
    let mut has_clue = Grid::new(height, width, false);

    for _ in 0..n_steps {
        let mut update_cand = vec![];
        for y in 0..height {
            for x in 0..width {
                let pos = P(y, x);

                if options.disallow_adjacent_clues {
                    let mut flg = false;
                    for dy in -1..2 {
                        for dx in -1..2 {
                            if (dy != 0 || dx != 0)
                                && problem.get_or_default_p(pos + D(dy, dx), Clue::NoClue)
                                    != Clue::NoClue
                            {
                                flg = true;
                            }
                        }
                    }
                    if flg {
                        continue;
                    }
                }
                for i in 0..((y + 3) / 2) {
                    if !check_clue_range(i, options) {
                        continue;
                    }
                    update_cand.push((pos, Clue::Up(i)));
                }
                for i in 0..((x + 3) / 2) {
                    if !check_clue_range(i, options) {
                        continue;
                    }
                    update_cand.push((pos, Clue::Left(i)));
                }
                for i in 0..((height - y) / 2) {
                    if !check_clue_range(i, options) {
                        continue;
                    }
                    update_cand.push((pos, Clue::Down(i)));
                }
                for i in 0..((width - x + 2) / 2) {
                    if !check_clue_range(i, options) {
                        continue;
                    }
                    update_cand.push((pos, Clue::Right(i)));
                }
                if problem[pos] != Clue::NoClue {
                    update_cand.push((pos, Clue::NoClue));
                }
            }
        }
        rng.shuffle(&mut update_cand);

        let mut updated = false;

        for &(loc, clue) in &update_cand {
            let previous_clue = problem[loc];
            has_clue[loc] = clue != Clue::NoClue;
            if options.disallow_dead_ends && has_dead_end_nearby(loc, &has_clue) {
                has_clue[loc] = previous_clue != Clue::NoClue;
                continue;
            }

            problem[loc] = clue;

            let mut next_field = Field::new(&problem);
            next_field.set_technique(options.technique);
            next_field.trial_and_error(options.search_depth);

            let new_n_clues = n_clues - if previous_clue == Clue::NoClue { 0 } else { 1 }
                + if clue == Clue::NoClue { 0 } else { 1 };

            let score = next_field.grid_loop().num_decided_edges() - new_n_clues * 25;
            let update = !next_field.inconsistent()
                && (current_score < score
                    || rng.gen::<f64>() < ((score - current_score) as f64 / temperature).exp());
            if update {
                current_score = score;
                updated = true;
                n_clues = new_n_clues;

                if next_field.fully_solved() {
                    return Some(problem);
                }
                break;
            } else {
                problem[loc] = previous_clue;
                has_clue[loc] = previous_clue != Clue::NoClue;
            }
        }

        if !updated {
            break;
        }

        temperature *= 0.995f64;
    }

    None
}

fn has_dead_end_nearby(loc: P, has_clue: &Grid<bool>) -> bool {
    return is_dead_end(loc, has_clue)
        || is_dead_end(loc + D(-1, 0), has_clue)
        || is_dead_end(loc + D(1, 0), has_clue)
        || is_dead_end(loc + D(0, -1), has_clue)
        || is_dead_end(loc + D(0, 1), has_clue);
}
fn is_dead_end(pos: P, has_clue: &Grid<bool>) -> bool {
    if !has_clue.is_valid_p(pos) {
        return false;
    }
    let mut neighbour_count = 0;
    for &d in &FOUR_NEIGHBOURS {
        if !has_clue.get_or_default_p(pos + d, true) {
            neighbour_count += 1;
        }
    }
    return neighbour_count <= 1;
}
<|endoftext|>