<commit_before>// extern crate euclid;

use std::collections::BTreeMap;
use std::collections::VecDeque;

use rug::Integer;
use euclid::{TypedRect, TypedVector2D};

use defs::*;
use math;
use delta::*;
use polyomino::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ShapeId(u32);

#[derive(Debug)]
pub struct Shape {
    // Gameplay:
    pub id: ShapeId,

    //TODO: use a faster hash table or just a vec https://github.com/servo/rust-fnv
    pub parent_ids: BTreeMap<ShapeId, ChildPoint>,
    // TODO: instead store a distinguished parent?
    pub polyomino: Polyomino,

    // Drawing:
    pub fill_color: [f32; 3],
    pub outline_color: [f32; 3],
}

impl Shape {
    pub fn has_position(&self, p: UPoint) -> bool {
        self.polyomino.has_position(p)
    }

    pub fn has_parent(&self, parent: &Shape) -> bool {
        self.parent_ids.contains_key(&parent.id)
    }

    pub fn first_parent_id(&self) -> ShapeId {
        let (&first_key, _) = self.parent_ids.iter().next().unwrap();
        first_key
    }

    pub fn position_on(&self, parent: &Shape) -> ChildPoint {
        self.parent_ids[&parent.id]
    }

    pub fn delta_from_parent(&self, parent: &Shape) -> Delta {
        Delta::from(self.position_on(parent).to_vector())
    }

    pub fn delta_to_child(&self, child: &Shape) -> Delta {
        child.delta_from_parent(self)
    }

    pub fn delta_to_parent(&self, parent: &Shape) -> FractionalDelta {
        let coords = self.parent_ids[&parent.id].to_vector();
        FractionalDelta {
            zdelta: 1,
            scale: 0,
            coords: TypedVector2D::new(Integer::from(coords.x), Integer::from(coords.y))
        }
    }
}

impl PartialEq for Shape {
    fn eq(&self, other: &Shape) -> bool {
        self.id == other.id
    }
}

impl Eq for Shape {}

pub struct Universe {
    pub shapes: BTreeMap<ShapeId, Shape>, // Should probably just be a Vec
}

impl Universe {
    pub fn minimal() -> Universe {
        let id1 = ShapeId(1);
        let id2 = ShapeId(2);
        let shape1 = Shape {
            id: id1,
            parent_ids: btreemap!{ id2 => ChildPoint::new(0, 0) },
            polyomino: Polyomino::monomino(),
            fill_color: [0.5, 0.5, 1.0],
            outline_color: [0.5, 0.5, 0.5],
        };
        let shape2 = Shape {
            id: id2,
            parent_ids: btreemap!{ id1 => ChildPoint::new(0, 0) },
            polyomino: Polyomino::monomino(),
            fill_color: [1.0, 0.5, 0.5],
            outline_color: [0.5, 0.25, 0.25],
        };

        let mut shapes = BTreeMap::new();
        shapes.insert(id1, shape1);
        shapes.insert(id2, shape2);

        Universe { shapes: shapes }
    }

    pub fn parents_of<'a>(&'a self, shape: &'a Shape) -> impl Iterator<Item = &'a Shape> + 'a {
        shape.parent_ids.keys().map(move |id| &self.shapes[id])
    }

    pub fn parents_of_id<'a>(&'a self, shape_id: ShapeId) -> impl Iterator<Item = &'a Shape> {
        self.parents_of(&self.shapes[&shape_id])
    }

    pub fn children_of<'a>(&'a self, parent: &'a Shape) -> impl Iterator<Item = &'a Shape> {
        self.shapes.values().filter(move |s| s.has_parent(parent))
    }

    pub fn children_of_id<'a>(&'a self, parent_id: ShapeId) -> impl Iterator<Item = &'a Shape> {
        self.shapes
            .values()
            .filter(move |s| s.parent_ids.contains_key(&parent_id))
    }

    pub fn parents_with_position_of(&self, shape: &Shape) -> Vec<(&Shape, ChildPoint)> {
        shape
            .parent_ids
            .iter()
            .map(|(id, pos)| (&self.shapes[id], *pos))
            .collect()
    }

    // canPushChunk :: Universe -> Direction -> Chunk -> Bool
    //     canPushChunk u d c = not (oob || any (isInhabited u) fr)
    // where (fr, oob) = fringe u d c

    pub fn can_shove(&self, chunk: TopChunk, d: Direction) -> bool {
        unimplemented!();
    }

    pub fn do_shove(&mut self, chunk: TopChunk, d: Direction) -> () {}
}

pub struct Square {
    pub shape_id: ShapeId,
    pub position: UPoint,
}

impl Square {
    fn location_on(&self, universe: &Universe, parent_id: ShapeId) -> Option<Location> {
        let pos_on = universe.shapes[&self.shape_id].parent_ids.get(&parent_id)?;
        let new_shape = &universe.shapes[&parent_id];
        let offset = self.position.to_vector() + math::coerce_up(pos_on.to_vector());
        let (new_pos, new_subp) = math::split_up(math::coerce_down(offset));

        Some(Location {
            square: Square {
                shape_id: parent_id,
                position: new_pos.to_point(),
            },
            subposition: new_subp,
        })
    }

    fn location(&self, universe: &Universe) -> Location {
        // TODO: This sort of sanity checking is slower, probably doesn't matter
        let mut locations: Vec<Location> = universe.shapes[&self.shape_id]
            .parent_ids
            .keys()
            .filter_map(|s| self.location_on(universe, *s))
            .collect();

        match locations.len() {
            0 => panic!("A square is not sitting on a location!"),
            1 => locations.pop().unwrap(),
            _ => panic!("A square is sitting on multiple locations!"),
        }
    }
}

pub struct Location {
    pub square: Square,
    pub subposition: ChildVec,
}

impl Location {
    pub fn inhabitant(&self, universe: &Universe) -> Option<Square> {
        let c = self.to_coordinate();
        let shape = &universe.shapes[&self.square.shape_id];

        let mut inhabitants: Vec<Square> = universe
            .parents_with_position_of(shape)
            .into_iter()
            .filter(|&(s, pos)| {
                let cpos = math::coerce_up(c - pos.to_vector());
                s.has_position(cpos.to_point())
            })
            .map(|(s, pos)| {
                let cpos = math::coerce_up(c - pos.to_vector());
                Square {
                    shape_id: s.id,
                    position: cpos.to_point(),
                }
            })
            .collect();

        if inhabitants.len() > 1 {
            // TODO: This sort of sanity checking is probably a bit slower
            panic!("A location has multiple inhabitants!");
        } else {
            inhabitants.pop()
        }
    }

    fn to_coordinate(&self) -> ChildVec {
        math::shift_down(self.square.position.to_vector()) + self.subposition
    }
}

// This stores offsets of each shape in the chunk

// TODO: these offsets may be too small, need a vec of offsets, one
// for each level (that can be converted to a normal form, if we want)
#[derive(Clone)]
pub struct TotalChunk {
    pub origin_id: ShapeId,
    pub top_shape_ids: BTreeMap<ShapeId, UVec>,
    pub lower_shape_ids: BTreeMap<ShapeId, Delta>,
}

impl TotalChunk {}

type ExploreResult = BTreeMap<ShapeId, Delta>;
type ExploreQueue = VecDeque<(ShapeId, Delta)>;

impl Universe {
    fn explore_step(&self, result: &mut ExploreResult, queue: &mut ExploreQueue) -> () {
        while !queue.is_empty() {
            let (sid, delta) = queue.pop_front().unwrap();
            let s = &self.shapes[&sid];

            let needs_update: bool = match result.get(&sid) {
                None => true,
                Some(existing) => delta.zdelta > existing.zdelta,
            };

            if !needs_update {
                continue;
            }

            result.insert(sid, delta.clone());

            if delta.zdelta < 0 {
                for p in self.parents_of_id(sid) {
                    queue.push_front((p.id, delta.revert(&s.delta_from_parent(p)))); // TODO: check this logic
                }
            }

            for c in self.children_of_id(sid) {
                queue.push_back((c.id, delta.append(&s.delta_to_child(c))));
            }
        }
    }

    fn explore(&self, shape_id: ShapeId) -> TotalChunk {
        let mut result = BTreeMap::new();
        let mut queue = VecDeque::new();

        queue.push_back((shape_id, Delta::zero()));

        self.explore_step(&mut result, &mut queue);

        let top = result
            .iter()
            .filter_map(|(s, d)| {
                if d.zdelta == 0 {
                    Some((*s, d.to_uvec()))
                } else {
                    None
                }
            })
            .collect();
        let lower = result
            .iter()
            .filter_map(
                |(s, d)| {
                    if d.zdelta < 0 {
                        Some((*s, d.clone()))
                    } else {
                        None
                    }
                }, // More copying than necessary?
            )
            .collect();

        TotalChunk {
            origin_id: shape_id,
            top_shape_ids: top,
            lower_shape_ids: lower,
        }
    }

    // fn explore_parent_of(&self, shape_ids: BTreeMap<ShapeId, IVec2>) -> Chunk {
    // }

    pub fn chunk_of(&self, shape: &Shape) -> TotalChunk {
        self.explore(shape.id)
    }

    pub fn parent_of(&self, chunk: &TopChunk) -> TopChunk {
        let origin_parent_id = self.shapes[&chunk.origin_id].first_parent_id();
        self.explore(origin_parent_id).into()
    }
}

#[derive(Debug, Clone)]
pub struct TopChunk {
    pub origin_id: ShapeId,
    pub top_shape_ids: BTreeMap<ShapeId, UVec>,
}

impl TopChunk {
    pub fn bounding_box(&self, universe: &Universe) -> TypedRect<i32, UniverseSpace> {
        let poly_bounds: Vec<TypedRect<i32, UniverseSpace>> = self
            .top_shape_ids
            .keys()
            .map(|shape_id| universe.shapes[shape_id].polyomino.bounding_box())
            .collect();
        poly_bounds.iter().fold(poly_bounds[0], |a, b| a.union(b))
    }
}

impl From<TotalChunk> for TopChunk {
    fn from(t: TotalChunk) -> TopChunk {
        let TotalChunk {
            origin_id,
            top_shape_ids,
            ..
        } = t;
        TopChunk {
            origin_id,
            top_shape_ids,
        }
    }
}

pub struct GameState {
    pub universe: Universe,
    pub player_chunk: TopChunk,
}

impl GameState {
    pub fn minimal() -> GameState {
        let u = Universe::minimal();

        GameState {
            universe: u,
            player_chunk: TopChunk {
                origin_id: ShapeId(1),
                top_shape_ids: btreemap![ShapeId(1) => UVec::zero()],
                //                lower_shape_ids: btreemap![ShapeId(2) => Delta::zero().shift_target_down()],
            },
        }
    }

    pub fn do_zoom(&mut self) -> () {
        self.player_chunk = self.universe.parent_of(&self.player_chunk);
    }
}

// This has to represent a monotone path between chunks
pub enum MonotonePath {
    Zero,
    Up { distance: u32 },
    Down { path: Vec<ShapeId> },
}

impl MonotonePath {
    pub fn up_target(&self) -> MonotonePath {
        use MonotonePath::*;
        match *self {
            Zero => Up { distance: 1 },
            Up { distance } => Up {
                distance: distance + 1,
            },
            Down { ref path } => if path.len() == 1 {
                Zero
            } else {
                let mut new_path = path.clone();
                new_path.pop();
                Down { path: new_path }
            },
        }
    }

    // Also returns the target shape of the delta
    pub fn as_delta_from(&self, universe: &Universe, id: ShapeId) -> (FractionalDelta, ShapeId) {
        use MonotonePath::*;
        match *self {
            Zero => (FractionalDelta::zero(), id),
            Up { distance } => {
                let mut result = FractionalDelta::zero();
                let mut current_shape_id = id;
                for _ in 0..distance {
                    let next_shape_id = universe.shapes[&id].first_parent_id();
                    let parent = &universe.shapes[&next_shape_id];
                    result = result.append(&universe.shapes[&id].delta_to_parent(parent));
                    current_shape_id = next_shape_id;
                }
                (result, current_shape_id)
            },
            Down { ref path } => unimplemented!()
        }
    }
}
<commit_msg>Implement nudging<commit_after>// extern crate euclid;

use std::collections::BTreeMap;
use std::collections::VecDeque;

use rug::Integer;
use euclid::{TypedRect, TypedVector2D};

use defs::*;
use math;
use delta::*;
use polyomino::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ShapeId(u32);

#[derive(Debug)]
pub struct Shape {
    // Gameplay:
    pub id: ShapeId,

    //TODO: use a faster hash table or just a vec https://github.com/servo/rust-fnv
    pub parent_ids: BTreeMap<ShapeId, ChildPoint>,
    // TODO: instead store a distinguished parent?
    pub polyomino: Polyomino,

    // Drawing:
    pub fill_color: [f32; 3],
    pub outline_color: [f32; 3],
}

impl Shape {
    pub fn has_position(&self, p: UPoint) -> bool {
        self.polyomino.has_position(p)
    }

    pub fn has_parent(&self, parent: &Shape) -> bool {
        self.parent_ids.contains_key(&parent.id)
    }

    pub fn first_parent_id(&self) -> ShapeId {
        let (&first_key, _) = self.parent_ids.iter().next().unwrap();
        first_key
    }

    pub fn position_on(&self, parent: &Shape) -> ChildPoint {
        self.parent_ids[&parent.id]
    }

    pub fn delta_from_parent(&self, parent: &Shape) -> Delta {
        Delta::from(self.position_on(parent).to_vector())
    }

    pub fn delta_to_child(&self, child: &Shape) -> Delta {
        child.delta_from_parent(self)
    }

    pub fn delta_to_parent(&self, parent: &Shape) -> FractionalDelta {
        let coords = self.parent_ids[&parent.id].to_vector();
        FractionalDelta {
            zdelta: 1,
            scale: 0,
            coords: TypedVector2D::new(Integer::from(coords.x), Integer::from(coords.y))
        }
    }
}

impl PartialEq for Shape {
    fn eq(&self, other: &Shape) -> bool {
        self.id == other.id
    }
}

impl Eq for Shape {}

pub struct Universe {
    pub shapes: BTreeMap<ShapeId, Shape>, // Should probably just be a Vec
}

impl Universe {
    pub fn minimal() -> Universe {
        let id1 = ShapeId(1);
        let id2 = ShapeId(2);
        let shape1 = Shape {
            id: id1,
            parent_ids: btreemap!{ id2 => ChildPoint::new(0, 0) },
            polyomino: Polyomino::monomino(),
            fill_color: [0.5, 0.5, 1.0],
            outline_color: [0.5, 0.5, 0.5],
        };
        let shape2 = Shape {
            id: id2,
            parent_ids: btreemap!{ id1 => ChildPoint::new(0, 0) },
            polyomino: Polyomino::monomino(),
            fill_color: [1.0, 0.5, 0.5],
            outline_color: [0.5, 0.25, 0.25],
        };

        let mut shapes = BTreeMap::new();
        shapes.insert(id1, shape1);
        shapes.insert(id2, shape2);

        Universe { shapes: shapes }
    }

    pub fn parents_of<'a>(&'a self, shape: &'a Shape) -> impl Iterator<Item = &'a Shape> + 'a {
        shape.parent_ids.keys().map(move |id| &self.shapes[id])
    }

    pub fn parents_of_id<'a>(&'a self, shape_id: ShapeId) -> impl Iterator<Item = &'a Shape> {
        self.parents_of(&self.shapes[&shape_id])
    }

    pub fn children_of<'a>(&'a self, parent: &'a Shape) -> impl Iterator<Item = &'a Shape> {
        self.shapes.values().filter(move |s| s.has_parent(parent))
    }

    pub fn children_of_id<'a>(&'a self, parent_id: ShapeId) -> impl Iterator<Item = &'a Shape> {
        self.shapes
            .values()
            .filter(move |s| s.parent_ids.contains_key(&parent_id))
    }

    pub fn parents_with_position_of(&self, shape: &Shape) -> Vec<(&Shape, ChildPoint)> {
        shape
            .parent_ids
            .iter()
            .map(|(id, pos)| (&self.shapes[id], *pos))
            .collect()
    }

    // canPushChunk :: Universe -> Direction -> Chunk -> Bool
    //     canPushChunk u d c = not (oob || any (isInhabited u) fr)
    // where (fr, oob) = fringe u d c

    pub fn can_shove(&self, chunk: TopChunk, d: Direction) -> bool {
        unimplemented!();
    }

    pub fn do_shove(&mut self, chunk: TopChunk, d: Direction) -> () {
        unimplemented!();
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Square {
    pub shape_id: ShapeId,
    pub position: UPoint,
}

impl Square {
    fn location_on(&self, universe: &Universe, parent_id: ShapeId) -> Option<Location> {
        let pos_on = universe.shapes[&self.shape_id].parent_ids.get(&parent_id)?;
        let new_shape = &universe.shapes[&parent_id];
        let offset = self.position.to_vector() + math::coerce_up(pos_on.to_vector());
        let (new_pos, new_subp) = math::split_up(math::coerce_down(offset));

        Some(Location {
            square: Square {
                shape_id: parent_id,
                position: new_pos.to_point(),
            },
            subposition: new_subp,
        })
    }

    fn location(&self, universe: &Universe) -> Location {
        // TODO: This sort of sanity checking is slower, probably doesn't matter
        let mut locations: Vec<Location> = universe.shapes[&self.shape_id]
            .parent_ids
            .keys()
            .filter_map(|s| self.location_on(universe, *s))
            .collect();

        match locations.len() {
            0 => panic!("A square is not sitting on a location!"),
            1 => locations.pop().unwrap(),
            _ => panic!("A square is sitting on multiple locations!"),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Location {
    pub square: Square,
    pub subposition: ChildVec,
}

impl Location {
    pub fn inhabitant(&self, universe: &Universe) -> Option<Square> {
        let c = self.to_coordinate();
        let shape = &universe.shapes[&self.square.shape_id];

        let mut inhabitants: Vec<Square> = universe
            .parents_with_position_of(shape)
            .into_iter()
            .filter(|&(s, pos)| {
                let cpos = math::coerce_up(c - pos.to_vector());
                s.has_position(cpos.to_point())
            })
            .map(|(s, pos)| {
                let cpos = math::coerce_up(c - pos.to_vector());
                Square {
                    shape_id: s.id,
                    position: cpos.to_point(),
                }
            })
            .collect();

        if inhabitants.len() > 1 {
            // TODO: This sort of sanity checking is probably a bit slower
            panic!("A location has multiple inhabitants!");
        } else {
            inhabitants.pop()
        }
    }

    fn to_coordinate(&self) -> ChildVec {
        math::shift_down(self.square.position.to_vector()) + self.subposition
    }

    pub fn all_subpositions() -> Vec<ChildVec> {
        (0..ZOOM_SCALE)
            .cartesian_product(0..ZOOM_SCALE)
            .map(|(x, y)| ChildVec::new(x as i32, y as i32))
            .collect()
    }

    fn wrap_subposition(v: ChildVec) -> ChildVec {
        ChildVec::new(v.x % ZOOM_SCALE as i32, v.y % ZOOM_SCALE as i32)
    }
}

impl Square {
    fn nudge_easy(&self, u: &Universe, d: Direction) -> Option<Square> {
        let newpos = self.position + d.to_vect();
        if u.shapes[&self.shape_id].polyomino.squares.contains(&newpos) {
            Some(Square {
                shape_id: self.shape_id,
                position: newpos,
            })
        } else {
            None
        }
    }

    fn nudge_recurse(
        &self,
        universe: &Universe,
        d: Direction,
        mut seen: HashSet<(Location, Direction)>,
    ) -> Option<Square> {
        if let Some(easy) = self.nudge_easy(universe, d) {
            return Some(easy);
        }

        self.location(universe)
            .nudge_recurse(universe, d, seen)?
            .inhabitant(universe)
    }

    pub fn nudge(&self, universe: &Universe, d: Direction) -> Option<Square> {
        self.nudge_recurse(universe, d, HashSet::new())
    }
}

impl Location {
    fn nudge_easy(&self, d: Direction) -> Option<Location> {
        let newpos = self.subposition + d.to_vect();
        if newpos.x >= 0
            && newpos.x < ZOOM_SCALE as i32
            && newpos.y >= 0
            && newpos.y < ZOOM_SCALE as i32
        {
            Some(Location {
                square: self.square.clone(),
                subposition: newpos,
            })
        } else {
            None
        }
    }

    fn nudge_recurse(
        &self,
        universe: &Universe,
        d: Direction,
        mut seen: HashSet<(Location, Direction)>,
    ) -> Option<Location> {
        if seen.contains(&(*self, d)) {
            return None;
        }
        if let Some(easy) = self.nudge_easy(d) {
            return Some(easy);
        }

        seen.insert((self.clone(), d));
        let newsquare = self.square.nudge_recurse(universe, d, seen)?;
        let newsubpos = self.subposition + d.to_vect();
        Some(Location {
            square: newsquare,
            subposition: newsubpos,
        })
    }

    pub fn nudge(&self, universe: &Universe, d: Direction) -> Option<Location> {
        self.nudge_recurse(universe, d, HashSet::new())
    }
}

// This stores offsets of each shape in the chunk

// TODO: these offsets may be too small, need a vec of offsets, one
// for each level (that can be converted to a normal form, if we want)
#[derive(Clone)]
pub struct TotalChunk {
    pub origin_id: ShapeId,
    pub top_shape_ids: BTreeMap<ShapeId, UVec>,
    pub lower_shape_ids: BTreeMap<ShapeId, Delta>,
}

impl TotalChunk {}

type ExploreResult = BTreeMap<ShapeId, Delta>;
type ExploreQueue = VecDeque<(ShapeId, Delta)>;

impl Universe {
    fn explore_step(&self, result: &mut ExploreResult, queue: &mut ExploreQueue) -> () {
        while !queue.is_empty() {
            let (sid, delta) = queue.pop_front().unwrap();
            let s = &self.shapes[&sid];

            let needs_update: bool = match result.get(&sid) {
                None => true,
                Some(existing) => delta.zdelta > existing.zdelta,
            };

            if !needs_update {
                continue;
            }

            result.insert(sid, delta.clone());

            if delta.zdelta < 0 {
                for p in self.parents_of_id(sid) {
                    queue.push_front((p.id, delta.revert(&s.delta_from_parent(p)))); // TODO: check this logic
                }
            }

            for c in self.children_of_id(sid) {
                queue.push_back((c.id, delta.append(&s.delta_to_child(c))));
            }
        }
    }

    fn explore(&self, shape_id: ShapeId) -> TotalChunk {
        let mut result = BTreeMap::new();
        let mut queue = VecDeque::new();

        queue.push_back((shape_id, Delta::zero()));

        self.explore_step(&mut result, &mut queue);

        let top = result
            .iter()
            .filter_map(|(s, d)| {
                if d.zdelta == 0 {
                    Some((*s, d.to_uvec()))
                } else {
                    None
                }
            })
            .collect();
        let lower = result
            .iter()
            .filter_map(
                |(s, d)| {
                    if d.zdelta < 0 {
                        Some((*s, d.clone()))
                    } else {
                        None
                    }
                }, // More copying than necessary?
            )
            .collect();

        TotalChunk {
            origin_id: shape_id,
            top_shape_ids: top,
            lower_shape_ids: lower,
        }
    }

    // fn explore_parent_of(&self, shape_ids: BTreeMap<ShapeId, IVec2>) -> Chunk {
    // }

    pub fn chunk_of(&self, shape: &Shape) -> TotalChunk {
        self.explore(shape.id)
    }

    pub fn parent_of(&self, chunk: &TopChunk) -> TopChunk {
        let origin_parent_id = self.shapes[&chunk.origin_id].first_parent_id();
        self.explore(origin_parent_id).into()
    }
}

#[derive(Debug, Clone)]
pub struct TopChunk {
    pub origin_id: ShapeId,
    pub top_shape_ids: BTreeMap<ShapeId, UVec>,
}

impl TopChunk {
    pub fn bounding_box(&self, universe: &Universe) -> TypedRect<i32, UniverseSpace> {
        let poly_bounds: Vec<TypedRect<i32, UniverseSpace>> = self
            .top_shape_ids
            .keys()
            .map(|shape_id| universe.shapes[shape_id].polyomino.bounding_box())
            .collect();
        poly_bounds.iter().fold(poly_bounds[0], |a, b| a.union(b))
    }
}

impl From<TotalChunk> for TopChunk {
    fn from(t: TotalChunk) -> TopChunk {
        let TotalChunk {
            origin_id,
            top_shape_ids,
            ..
        } = t;
        TopChunk {
            origin_id,
            top_shape_ids,
        }
    }
}

pub struct GameState {
    pub universe: Universe,
    pub player_chunk: TopChunk,
}

impl GameState {
    pub fn minimal() -> GameState {
        let u = Universe::minimal();

        GameState {
            universe: u,
            player_chunk: TopChunk {
                origin_id: ShapeId(1),
                top_shape_ids: btreemap![ShapeId(1) => UVec::zero()],
                //                lower_shape_ids: btreemap![ShapeId(2) => Delta::zero().shift_target_down()],
            },
        }
    }

    pub fn do_zoom(&mut self) -> () {
        self.player_chunk = self.universe.parent_of(&self.player_chunk);
    }

    pub fn do_move(&mut self, d: Direction) -> () {
        unimplemented!();
    }
}

// This has to represent a monotone path between chunks
pub enum MonotonePath {
    Zero,
    Up { distance: u32 },
    Down { path: Vec<ShapeId> },
}

impl MonotonePath {
    pub fn up_target(&self) -> MonotonePath {
        use MonotonePath::*;
        match *self {
            Zero => Up { distance: 1 },
            Up { distance } => Up {
                distance: distance + 1,
            },
            Down { ref path } => if path.len() == 1 {
                Zero
            } else {
                let mut new_path = path.clone();
                new_path.pop();
                Down { path: new_path }
            },
        }
    }

    // Also returns the target shape of the delta
    pub fn as_delta_from(&self, universe: &Universe, id: ShapeId) -> (FractionalDelta, ShapeId) {
        use MonotonePath::*;
        match *self {
            Zero => (FractionalDelta::zero(), id),
            Up { distance } => {
                let mut result = FractionalDelta::zero();
                let mut current_shape_id = id;
                for _ in 0..distance {
                    let next_shape_id = universe.shapes[&id].first_parent_id();
                    let parent = &universe.shapes[&next_shape_id];
                    result = result.append(&universe.shapes[&id].delta_to_parent(parent));
                    current_shape_id = next_shape_id;
                }
                (result, current_shape_id)
            }
            Down { ref path } => unimplemented!(),
        }
    }
}
<|endoftext|>


<commit_before>use std::{ u16, u32 };
use std::num::Int;
use std::slice::BinarySearchResult::{ Found, NotFound };

use store::Store::{ Array, Bitmap };

pub enum Store {
    Array(Vec<u16>),
    Bitmap([u32; 2048]),
}

fn bitmap_location(index: u16) -> (uint, uint) {
    ((index / (u32::BITS as u16)) as uint, (index % (u32::BITS as u16)) as uint)
}

fn insert_array(vec: &mut Vec<u16>, index: u16) -> bool {
    match vec.binary_search(|elem| elem.cmp(&index)) {
        NotFound(loc) => { vec.insert(loc, index); true },
        _ => false,
    }
}

fn remove_array(vec: &mut Vec<u16>, index: u16) -> bool {
    match vec.binary_search(|elem| elem.cmp(&index)) {
        Found(loc) => { vec.remove(loc); true },
        _ => false,
    }
}

fn insert_bitmap(bits: &mut [u32; 2048], index: u16) -> bool {
    let (key, bit) = bitmap_location(index);
    if bits[key] & (1 << bit) == 0 {
        bits[key] |= 1 << bit;
        true
    } else {
        false
    }
}

fn remove_bitmap(bits: &mut [u32; 2048], index: u16) -> bool {
    let (key, bit) = bitmap_location(index);
    if bits[key] & (1 << bit) != 0 {
        bits[key] &= !(1 << bit);
        true
    } else {
        false
    }
}

fn contains_array(vec: &Vec<u16>, index: u16) -> bool {
    match vec.binary_search(|elem| elem.cmp(&index)) {
        Found(_) => true,
        NotFound(_) => false,
    }
}

fn contains_bitmap(bits: &[u32; 2048], index: u16) -> bool {
    let (key, bit) = bitmap_location(index);
    bits[key] & (1 << bit) != 0
}

fn bitmap_to_array(bits: &[u32; 2048]) -> Vec<u16> {
    let mut vec = Vec::new();
    for (key, val) in bits.iter().map(|v| *v).enumerate() {
        if val == 0 {
            continue
        }
        for bit in 0..(u32::BITS) {
            if (val & (1 << bit)) != 0 {
                vec.push((key * u32::BITS + bit) as u16);
            }
        }
    }
    vec
}

fn array_to_bitmap(vec: &Vec<u16>) -> [u32; 2048] {
    let mut bits = [0; 2048];
    for index in vec.iter() {
        let (key, bit) = bitmap_location(*index);
        bits[key] |= 1 << bit;
    }
    bits
}

fn is_disjoint_array(vec1: &Vec<u16>, vec2: &Vec<u16>) -> bool {
    let (mut i1, mut i2) = (vec1.iter(), vec2.iter());
    let (mut value1, mut value2) = (i1.next(), i2.next());
    loop {
        match (value1, value2) {
            (None, _) | (_, None) => return true,
            (v1, v2) if v1 == v2 => return false,
            (v1, v2) if v1 < v2 => value1 = i1.next(),
            (v1, v2) if v1 > v2 => value2 = i2.next(),
            (_, _) => panic!(),
        }
    }
}

fn is_disjoint_bitmap(bits1: &[u32; 2048], bits2: &[u32; 2048]) -> bool {
    for (index1, index2) in bits1.iter().zip(bits2.iter()) {
        if *index1 & *index2 != 0 {
            return false;
        }
    }
    return true;
}

fn is_disjoint_array_bitmap(vec: &Vec<u16>, bits: &[u32; 2048]) -> bool {
    for index in vec.iter() {
        if contains_bitmap(bits, *index) {
            return false;
        }
    }
    return true;
}

fn is_subset_array(vec1: &Vec<u16>, vec2: &Vec<u16>) -> bool {
    let (mut i1, mut i2) = (vec1.iter(), vec2.iter());
    let (mut value1, mut value2) = (i1.next(), i2.next());
    loop {
        match (value1, value2) {
            (None, _) => return true,
            (_, None) => return false,
            (v1, v2) if v1 == v2 => {
                value1 = i1.next();
                value2 = i2.next();
            },
            (v1, v2) if v1 < v2 => return false,
            (v1, v2) if v1 > v2 => value2 = i2.next(),
            (_, _) => panic!(),
        }
    }
}

fn is_subset_bitmap(bits1: &[u32; 2048], bits2: &[u32; 2048]) -> bool {
    for (index1, index2) in bits1.iter().zip(bits2.iter()) {
        if *index1 & *index2 != *index1 {
            return false;
        }
    }
    return true;
}

fn is_subset_array_bitmap(vec: &Vec<u16>, bits: &[u32; 2048]) -> bool {
    for index in vec.iter() {
        if !contains_bitmap(bits, *index) {
            return false;
        }
    }
    return true;
}

fn union_with_array(vec1: &mut Vec<u16>, vec2: &Vec<u16>) {
    for index in vec2.iter() {
        insert_array(vec1, *index);
    }
}

fn union_with_bitmap(bits1: &mut [u32; 2048], bits2: &[u32; 2048]) {
    for (index1, index2) in bits1.iter_mut().zip(bits2.iter()) {
        *index1 &= *index2;
    }
}

fn union_with_bitmap_array(bits: &mut [u32; 2048], vec: &Vec<u16>) {
    for index in vec.iter() {
        insert_bitmap(bits, *index);
    }
}

fn union_with(mut this: &mut Store, other: &Store) {
    match (&mut this, other) {
        (& &Array(ref mut vec1), &Array(ref vec2)) => union_with_array(vec1, vec2),
        (& &Bitmap(ref mut bits1), &Bitmap(ref bits2)) => union_with_bitmap(bits1, bits2),
        (& &Bitmap(ref mut bits), &Array(ref vec)) => union_with_bitmap_array(bits, vec),
        (& &Array(_), &Bitmap(ref bits2)) => {
            *this = this.to_bitmap();
            this.union_with(other);
        },
    }
}

impl Store {
    pub fn insert(&mut self, index: u16) -> bool {
        match self {
            &Array(ref mut vec) => insert_array(vec, index),
            &Bitmap(ref mut bits) => insert_bitmap(bits, index),
        }
    }

    pub fn remove(&mut self, index: u16) -> bool {
        match self {
            &Array(ref mut vec) => remove_array(vec, index),
            &Bitmap(ref mut bits) => remove_bitmap(bits, index),
        }
    }

    pub fn contains(&self, index: u16) -> bool {
        match self {
            &Array(ref vec) => contains_array(vec, index),
            &Bitmap(ref bits) => contains_bitmap(bits, index),
        }
    }

    pub fn is_disjoint(&self, other: &Self) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => is_disjoint_array(vec1, vec2),
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => is_disjoint_bitmap(bits1, bits2),
            (&Array(ref vec), &Bitmap(ref bits)) => is_disjoint_array_bitmap(vec, bits),
            (&Bitmap(ref bits), &Array(ref vec)) => is_disjoint_array_bitmap(vec, bits),
        }
    }

    pub fn is_subset(&self, other: &Self) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => is_subset_array(vec1, vec2),
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => is_subset_bitmap(bits1, bits2),
            (&Array(ref vec), &Bitmap(ref bits)) => is_subset_array_bitmap(vec, bits),
            (&Bitmap(..), &Array(..)) => false,
        }
    }

    pub fn to_array(&self) -> Self {
        match self {
            &Array(_) => panic!("Cannot convert array to array"),
            &Bitmap(ref bits) => Array(bitmap_to_array(bits)),
        }
    }

    pub fn to_bitmap(&self) -> Self {
        match self {
            &Array(ref vec) => Bitmap(array_to_bitmap(vec)),
            &Bitmap(_) => panic!("Cannot convert bitmap to bitmap"),
        }
    }

    pub fn union_with(&mut self, other: &Self) {
        union_with(self, other);
    }

    pub fn len(&self) -> u16 {
        match self {
            &Array(ref vec) => vec.len() as u16,
            &Bitmap(ref bits) => {
                let mut len = u32::BITS * 2048;
                for bit in bits.iter() {
                    len -= bit.count_zeros()
                }
                len as u16
            },
        }
    }

    pub fn min(&self) -> u16 {
        match self {
            &Array(ref vec) => vec[0],
            &Bitmap(ref bits) => {
                for (index, bit) in bits.iter().enumerate() {
                    if *bit != 0 {
                        return (index * u32::BITS + bit.leading_zeros()) as u16;
                    }
                }
                return u16::MIN;
            },
        }
    }

    pub fn max(&self) -> u16 {
        match self {
            &Array(ref vec) => vec[vec.len() - 1],
            &Bitmap(ref bits) => {
                for (index, bit) in bits.iter().enumerate().rev() {
                    if *bit != 0 {
                        return ((index + 1) * u32::BITS - bit.trailing_zeros()) as u16;
                    }
                }
                return u16::MAX;
            },
        }
    }
}

impl PartialEq for Store {
    fn eq(&self, other: &Store) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => {
                vec1 == vec2
            },
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => {
                bits1.iter().zip(bits2.iter()).map(|(i1, i2)| i1 == i2).fold(true, |acc, n| acc & n)
            },
            _ => false,
        }
    }
}
<commit_msg>Count up with count_ones instead of down<commit_after>use std::{ u16, u32 };
use std::num::Int;
use std::slice::BinarySearchResult::{ Found, NotFound };

use store::Store::{ Array, Bitmap };

pub enum Store {
    Array(Vec<u16>),
    Bitmap([u32; 2048]),
}

fn bitmap_location(index: u16) -> (uint, uint) {
    ((index / (u32::BITS as u16)) as uint, (index % (u32::BITS as u16)) as uint)
}

fn insert_array(vec: &mut Vec<u16>, index: u16) -> bool {
    match vec.binary_search(|elem| elem.cmp(&index)) {
        NotFound(loc) => { vec.insert(loc, index); true },
        _ => false,
    }
}

fn remove_array(vec: &mut Vec<u16>, index: u16) -> bool {
    match vec.binary_search(|elem| elem.cmp(&index)) {
        Found(loc) => { vec.remove(loc); true },
        _ => false,
    }
}

fn insert_bitmap(bits: &mut [u32; 2048], index: u16) -> bool {
    let (key, bit) = bitmap_location(index);
    if bits[key] & (1 << bit) == 0 {
        bits[key] |= 1 << bit;
        true
    } else {
        false
    }
}

fn remove_bitmap(bits: &mut [u32; 2048], index: u16) -> bool {
    let (key, bit) = bitmap_location(index);
    if bits[key] & (1 << bit) != 0 {
        bits[key] &= !(1 << bit);
        true
    } else {
        false
    }
}

fn contains_array(vec: &Vec<u16>, index: u16) -> bool {
    match vec.binary_search(|elem| elem.cmp(&index)) {
        Found(_) => true,
        NotFound(_) => false,
    }
}

fn contains_bitmap(bits: &[u32; 2048], index: u16) -> bool {
    let (key, bit) = bitmap_location(index);
    bits[key] & (1 << bit) != 0
}

fn bitmap_to_array(bits: &[u32; 2048]) -> Vec<u16> {
    let mut vec = Vec::new();
    for (key, val) in bits.iter().map(|v| *v).enumerate() {
        if val == 0 {
            continue
        }
        for bit in 0..(u32::BITS) {
            if (val & (1 << bit)) != 0 {
                vec.push((key * u32::BITS + bit) as u16);
            }
        }
    }
    vec
}

fn array_to_bitmap(vec: &Vec<u16>) -> [u32; 2048] {
    let mut bits = [0; 2048];
    for index in vec.iter() {
        let (key, bit) = bitmap_location(*index);
        bits[key] |= 1 << bit;
    }
    bits
}

fn is_disjoint_array(vec1: &Vec<u16>, vec2: &Vec<u16>) -> bool {
    let (mut i1, mut i2) = (vec1.iter(), vec2.iter());
    let (mut value1, mut value2) = (i1.next(), i2.next());
    loop {
        match (value1, value2) {
            (None, _) | (_, None) => return true,
            (v1, v2) if v1 == v2 => return false,
            (v1, v2) if v1 < v2 => value1 = i1.next(),
            (v1, v2) if v1 > v2 => value2 = i2.next(),
            (_, _) => panic!(),
        }
    }
}

fn is_disjoint_bitmap(bits1: &[u32; 2048], bits2: &[u32; 2048]) -> bool {
    for (index1, index2) in bits1.iter().zip(bits2.iter()) {
        if *index1 & *index2 != 0 {
            return false;
        }
    }
    return true;
}

fn is_disjoint_array_bitmap(vec: &Vec<u16>, bits: &[u32; 2048]) -> bool {
    for index in vec.iter() {
        if contains_bitmap(bits, *index) {
            return false;
        }
    }
    return true;
}

fn is_subset_array(vec1: &Vec<u16>, vec2: &Vec<u16>) -> bool {
    let (mut i1, mut i2) = (vec1.iter(), vec2.iter());
    let (mut value1, mut value2) = (i1.next(), i2.next());
    loop {
        match (value1, value2) {
            (None, _) => return true,
            (_, None) => return false,
            (v1, v2) if v1 == v2 => {
                value1 = i1.next();
                value2 = i2.next();
            },
            (v1, v2) if v1 < v2 => return false,
            (v1, v2) if v1 > v2 => value2 = i2.next(),
            (_, _) => panic!(),
        }
    }
}

fn is_subset_bitmap(bits1: &[u32; 2048], bits2: &[u32; 2048]) -> bool {
    for (index1, index2) in bits1.iter().zip(bits2.iter()) {
        if *index1 & *index2 != *index1 {
            return false;
        }
    }
    return true;
}

fn is_subset_array_bitmap(vec: &Vec<u16>, bits: &[u32; 2048]) -> bool {
    for index in vec.iter() {
        if !contains_bitmap(bits, *index) {
            return false;
        }
    }
    return true;
}

fn union_with_array(vec1: &mut Vec<u16>, vec2: &Vec<u16>) {
    for index in vec2.iter() {
        insert_array(vec1, *index);
    }
}

fn union_with_bitmap(bits1: &mut [u32; 2048], bits2: &[u32; 2048]) {
    for (index1, index2) in bits1.iter_mut().zip(bits2.iter()) {
        *index1 &= *index2;
    }
}

fn union_with_bitmap_array(bits: &mut [u32; 2048], vec: &Vec<u16>) {
    for index in vec.iter() {
        insert_bitmap(bits, *index);
    }
}

fn union_with(mut this: &mut Store, other: &Store) {
    match (&mut this, other) {
        (& &Array(ref mut vec1), &Array(ref vec2)) => union_with_array(vec1, vec2),
        (& &Bitmap(ref mut bits1), &Bitmap(ref bits2)) => union_with_bitmap(bits1, bits2),
        (& &Bitmap(ref mut bits), &Array(ref vec)) => union_with_bitmap_array(bits, vec),
        (& &Array(_), &Bitmap(ref bits2)) => {
            *this = this.to_bitmap();
            this.union_with(other);
        },
    }
}

impl Store {
    pub fn insert(&mut self, index: u16) -> bool {
        match self {
            &Array(ref mut vec) => insert_array(vec, index),
            &Bitmap(ref mut bits) => insert_bitmap(bits, index),
        }
    }

    pub fn remove(&mut self, index: u16) -> bool {
        match self {
            &Array(ref mut vec) => remove_array(vec, index),
            &Bitmap(ref mut bits) => remove_bitmap(bits, index),
        }
    }

    pub fn contains(&self, index: u16) -> bool {
        match self {
            &Array(ref vec) => contains_array(vec, index),
            &Bitmap(ref bits) => contains_bitmap(bits, index),
        }
    }

    pub fn is_disjoint(&self, other: &Self) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => is_disjoint_array(vec1, vec2),
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => is_disjoint_bitmap(bits1, bits2),
            (&Array(ref vec), &Bitmap(ref bits)) => is_disjoint_array_bitmap(vec, bits),
            (&Bitmap(ref bits), &Array(ref vec)) => is_disjoint_array_bitmap(vec, bits),
        }
    }

    pub fn is_subset(&self, other: &Self) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => is_subset_array(vec1, vec2),
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => is_subset_bitmap(bits1, bits2),
            (&Array(ref vec), &Bitmap(ref bits)) => is_subset_array_bitmap(vec, bits),
            (&Bitmap(..), &Array(..)) => false,
        }
    }

    pub fn to_array(&self) -> Self {
        match self {
            &Array(_) => panic!("Cannot convert array to array"),
            &Bitmap(ref bits) => Array(bitmap_to_array(bits)),
        }
    }

    pub fn to_bitmap(&self) -> Self {
        match self {
            &Array(ref vec) => Bitmap(array_to_bitmap(vec)),
            &Bitmap(_) => panic!("Cannot convert bitmap to bitmap"),
        }
    }

    pub fn union_with(&mut self, other: &Self) {
        union_with(self, other);
    }

    pub fn len(&self) -> u16 {
        match self {
            &Array(ref vec) => vec.len() as u16,
            &Bitmap(ref bits) => {
                let mut len = 0;
                for bit in bits.iter() {
                    len += bit.count_ones()
                }
                len as u16
            },
        }
    }

    pub fn min(&self) -> u16 {
        match self {
            &Array(ref vec) => vec[0],
            &Bitmap(ref bits) => {
                for (index, bit) in bits.iter().enumerate() {
                    if *bit != 0 {
                        return (index * u32::BITS + bit.leading_zeros()) as u16;
                    }
                }
                return u16::MIN;
            },
        }
    }

    pub fn max(&self) -> u16 {
        match self {
            &Array(ref vec) => vec[vec.len() - 1],
            &Bitmap(ref bits) => {
                for (index, bit) in bits.iter().enumerate().rev() {
                    if *bit != 0 {
                        return ((index + 1) * u32::BITS - bit.trailing_zeros()) as u16;
                    }
                }
                return u16::MAX;
            },
        }
    }
}

impl PartialEq for Store {
    fn eq(&self, other: &Store) -> bool {
        match (self, other) {
            (&Array(ref vec1), &Array(ref vec2)) => {
                vec1 == vec2
            },
            (&Bitmap(ref bits1), &Bitmap(ref bits2)) => {
                bits1.iter().zip(bits2.iter()).map(|(i1, i2)| i1 == i2).fold(true, |acc, n| acc & n)
            },
            _ => false,
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

#[derive(PartialEq,Eq,Debug,Hash,Clone)]
pub enum BasicValue {
    Byte(u8),
    Boolean(bool),
    Int16(i16),
    Uint16(u16),
    Int32(i32),
    Uint32(u32),
    Int64(i64),
    Uint64(u64),
    String(String),
    ObjectPath(Path),
    Signature(Signature),
}

#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub struct Path(pub String);

#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub struct Signature(pub String);

#[derive(PartialEq,Debug,Clone)]
pub struct Struct {
    pub objects: Vec<Value>,
    pub signature: Signature
}

pub type Dictionary = HashMap<BasicValue,Value>;

#[derive(PartialEq,Debug,Clone)]
pub enum Value {
    BasicValue(BasicValue),
    Double(f64),
    Array(Vec<Value>),
    Variant(Box<Value>),
    Struct(Struct),
    Dictionary(Dictionary)
}

impl<'a> From<&'a Value> for u8 {
    fn from(v: &'a Value) -> u8 {
        match v {
            &Value::BasicValue(BasicValue::Byte(x)) => x,
            _ => panic!("Not a byte")
        }
    }
}

impl<'a> From<&'a Value> for i16 {
    fn from(v: &'a Value) -> i16 {
        match v {
            &Value::BasicValue(BasicValue::Int16(x)) => x,
            _ => panic!("Not an Int16")
        }
    }
}

impl<'a> From<&'a Value> for i32 {
    fn from(v: &'a Value) -> i32 {
        match v {
            &Value::BasicValue(BasicValue::Int32(x)) => x,
            _ => panic!("Not an Int32")
        }
    }
}

impl<'a> From<&'a Value> for i64 {
    fn from(v: &'a Value) -> i64 {
        match v {
            &Value::BasicValue(BasicValue::Int64(x)) => x,
            _ => panic!("Not an Int64")
        }
    }
}

impl<'a> From<&'a Value> for u16 {
    fn from(v: &'a Value) -> u16 {
        match v {
            &Value::BasicValue(BasicValue::Uint16(x)) => x,
            _ => panic!("Not a Uint16")
        }
    }
}

impl<'a> From<&'a Value> for u32 {
    fn from(v: &'a Value) -> u32 {
        match v {
            &Value::BasicValue(BasicValue::Uint32(x)) => x,
            _ => panic!("Not a Uint32")
        }
    }
}

impl<'a> From<&'a Value> for u64 {
    fn from(v: &'a Value) -> u64 {
        match v {
            &Value::BasicValue(BasicValue::Uint64(x)) => x,
            _ => panic!("Not a Uint32")
        }
    }
}

impl<'a> From<&'a Value> for String {
    fn from(v: &'a Value) -> String {
        match v {
            &Value::BasicValue(BasicValue::String(ref x)) => x.to_string(),
            &Value::BasicValue(BasicValue::ObjectPath(Path(ref x))) => x.to_string(),
            &Value::BasicValue(BasicValue::Signature(Signature(ref x))) => x.to_string(),
            _ => panic!("Not a string type")
        }
    }
}

<commit_msg>Make Variant a stand-alone type for convenience<commit_after>use std::collections::HashMap;

#[derive(PartialEq,Eq,Debug,Hash,Clone)]
pub enum BasicValue {
    Byte(u8),
    Boolean(bool),
    Int16(i16),
    Uint16(u16),
    Int32(i32),
    Uint32(u32),
    Int64(i64),
    Uint64(u64),
    String(String),
    ObjectPath(Path),
    Signature(Signature),
}

#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub struct Path(pub String);

#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub struct Signature(pub String);

#[derive(PartialEq,Debug,Clone)]
pub struct Struct {
    pub objects: Vec<Value>,
    pub signature: Signature
}

#[derive(PartialEq,Debug,Clone)]
pub struct Variant {
    pub object: Box<Value>,
    pub signature: Signature
}

pub type Dictionary = HashMap<BasicValue,Value>;

#[derive(PartialEq,Debug,Clone)]
pub enum Value {
    BasicValue(BasicValue),
    Double(f64),
    Array(Vec<Value>),
    Variant(Variant),
    Struct(Struct),
    Dictionary(Dictionary)
}

impl<'a> From<&'a Value> for u8 {
    fn from(v: &'a Value) -> u8 {
        match v {
            &Value::BasicValue(BasicValue::Byte(x)) => x,
            _ => panic!("Not a byte")
        }
    }
}

impl<'a> From<&'a Value> for i16 {
    fn from(v: &'a Value) -> i16 {
        match v {
            &Value::BasicValue(BasicValue::Int16(x)) => x,
            _ => panic!("Not an Int16")
        }
    }
}

impl<'a> From<&'a Value> for i32 {
    fn from(v: &'a Value) -> i32 {
        match v {
            &Value::BasicValue(BasicValue::Int32(x)) => x,
            _ => panic!("Not an Int32")
        }
    }
}

impl<'a> From<&'a Value> for i64 {
    fn from(v: &'a Value) -> i64 {
        match v {
            &Value::BasicValue(BasicValue::Int64(x)) => x,
            _ => panic!("Not an Int64")
        }
    }
}

impl<'a> From<&'a Value> for u16 {
    fn from(v: &'a Value) -> u16 {
        match v {
            &Value::BasicValue(BasicValue::Uint16(x)) => x,
            _ => panic!("Not a Uint16")
        }
    }
}

impl<'a> From<&'a Value> for u32 {
    fn from(v: &'a Value) -> u32 {
        match v {
            &Value::BasicValue(BasicValue::Uint32(x)) => x,
            _ => panic!("Not a Uint32")
        }
    }
}

impl<'a> From<&'a Value> for u64 {
    fn from(v: &'a Value) -> u64 {
        match v {
            &Value::BasicValue(BasicValue::Uint64(x)) => x,
            _ => panic!("Not a Uint32")
        }
    }
}

impl<'a> From<&'a Value> for String {
    fn from(v: &'a Value) -> String {
        match v {
            &Value::BasicValue(BasicValue::String(ref x)) => x.to_string(),
            &Value::BasicValue(BasicValue::ObjectPath(Path(ref x))) => x.to_string(),
            &Value::BasicValue(BasicValue::Signature(Signature(ref x))) => x.to_string(),
            _ => panic!("Not a string type")
        }
    }
}

<|endoftext|>


<commit_before>use std::string::String as StdString;

use proto::{Term, Datum, Term_TermType as TermType, Term_AssocPair as TermPair,
            Datum_DatumType as DatumType, Datum_AssocPair as DatumPair};

use protobuf::repeated::RepeatedField;
use serde_json::value::{ToJson, Value};

macro_rules! implement {
    (Selection<$dt:ident>) => {
        impl DataType for Selection<$dt> {}

        impl Selection<$dt> {
            pub fn new() -> Selection<$dt> {
                Selection::<$dt>($dt(Term::new()))
            }
        }

        impl From<Selection<$dt>> for Term {
            fn from(t: Selection<$dt>) -> Term {
                From::from(t.0)
            }
        }

        impl From<Term> for Selection<$dt> {
            fn from(t: Term) -> Selection<$dt> {
                Selection::<$dt>($dt(t))
            }
        }
    };

    ($(#[$attr:meta])* pub struct Command) => {
        $(
            #[$attr]
        )*
        #[derive(Debug, Clone)]
        pub struct Command(Term);

        impl DataType for Command {}

        impl From<Command> for Term {
            fn from(t: Command) -> Term {
                t.0
            }
        }

        impl From<Term> for Command {
            fn from(t: Term) -> Command {
                Command(t)
            }
        }
    };

    ($(#[$attr:meta])* pub struct $dt:ident) => {
        $(
            #[$attr]
        )*
        #[derive(Debug, Clone)]
        pub struct $dt(Term);

        impl DataType for $dt {}

        impl $dt {
            pub fn new() -> $dt {
                $dt(Term::new())
            }
        }

        impl From<$dt> for Term {
            fn from(t: $dt) -> Term {
                t.0
            }
        }

        impl From<Term> for $dt {
            fn from(t: Term) -> $dt {
                $dt(t)
            }
        }
    };
}

pub trait DataType: From<Term> + Into<Term> + Clone {}

implement! {
    /// **Arrays** are lists of zero or more elements.
    ///
    /// ```json
    /// [1, 2, 3]
    /// []
    /// [{user: 'Bob', posts: 23}, {user: 'Jason', posts: 10}]
    /// ```
    /// Anything valid in a JSON array is valid in RethinkDB.
    /// The elements may be any of the basic values, objects,
    /// or other arrays. Arrays in RethinkDB are loaded fully
    /// into memory before they’re returned to the user, so
    /// they’re inefficient at large sizes. RethinkDB defaults
    /// to supporting arrays of up to 100,000 elements; this
    /// may be set to a different value at runtime for reading
    /// by using the `array_limit` option to run.
    pub struct Array
}

implement! {
    /// **Booleans** are `true` and `false`
    pub struct Bool
}

implement! {
    /// **Databases** are RethinkDB databases.
    ///
    /// This is the return type of `db`.
    pub struct Db
}

implement! {
    /// **Functions** can be passed as parameters to certain ReQL
    /// commands.
    pub struct Function
}

implement! {
    /// **Grouped data** is created by the `group` command.
    ///
    /// The command partitions a stream into multiple groups
    /// based on specified fields or functions. ReQL commands
    /// called on GroupedData operate on each group
    /// individually. For more details, read the group
    /// documentation. Depending on the input to group,
    /// grouped data may have the type of GroupedStream.
    pub struct GroupedData
}

implement! {
    pub struct GroupedStream
}

implement! {
    /// **Minval** and **maxval** are used with some commands such
    /// as `between` to specify absolute lower and upper bounds
    /// (e.g., `between(r.minval, 1000)` would return all
    /// documents in a table whose primary key is less than
    /// 1000).
    pub struct MaxVal
}

implement! {
    pub struct MinVal
}

implement! {
    /// **Null** is a value distinct from the number zero, an
    /// empty set, or a zero-length string.
    ///
    /// Natively this is
    /// `None`. It is often used to explicitly denote the
    /// absence of any other value. The root node of a tree
    /// structure might have a parent of `null`, or a required
    /// but as yet non-initialized key might be given a value
    /// of `null`.
    pub struct Null
}

implement! {
    /// **Numbers** are any real number: `5`, `3.14159`, `-42`.
    ///
    /// RethinkDB uses double precision (64-bit) floating point
    /// numbers internally. Neither infinity nor NaN are allowed.
    pub struct Number
}

implement! {
    /// **Objects** are JSON data objects, standard key-value pairs.
    ///
    /// ```json
    /// {
    ///     username: 'bob',
    ///     posts: 23,
    ///     favorites: {
    ///         color: 'blue',
    ///         food: 'tacos'
    ///     },
    ///     friends: ['agatha', 'jason']
    /// }
    /// ```
    ///
    /// Any valid JSON object is a valid RethinkDB object, so
    /// values can be any of the basic values, arrays, or
    /// other objects. Documents in a RethinkDB database are
    /// objects. Like JSON, key names must be strings, not
    /// integers.
    pub struct Object
}

implement! {
    /// **Binary** objects are similar to BLOBs in SQL databases:
    /// files, images and other binary data.
    ///
    /// See Storing binary objects for details.
    pub struct Binary
}

implement! {
    /// **Geometry** data types for geospatial support, including
    /// points, lines, and polygons.
    pub struct Geometry
}

implement! {
    /// **Times** are RethinkDB’s native date/time type, stored
    /// with millisecond precision.
    ///
    /// You can use native date/time types in supported
    /// languages, as the conversion will be done by the driver.
    /// See Dates and times in RethinkDB for details.
    pub struct Time
}

implement! {
    /// **Streams** are lists like arrays, but they’re loaded in
    /// a lazy fashion.
    ///
    /// Operations that return streams return a `cursor`.
    /// A cursor is a pointer into the result set. Instead of
    /// reading the results all at once like an array, you
    /// loop over the results, retrieving the next member of the
    /// set with each iteration. This makes it possible to
    /// efficiently work with large result sets.
    ///
    /// (See “Working with Streams,” below, for some tips.)
    /// Streams are read-only; you can’t pass one as an input
    /// to an ReQL command meant to modify its input like
    /// `update` or `delete`.
    pub struct Stream
}

implement! {
    /// **Strings** are any valid UTF-8 string: `"superhero"`,
    /// `"ünnëcëssärÿ ümläüts"`. Strings may include the null
    /// code point (U+0000).
    pub struct String
}

implement! {
    /// **Tables** are RethinkDB database tables.
    ///
    /// They behave like selections—they’re writable, as you can
    /// insert and delete documents in them. ReQL methods that
    /// use an index, like `get_all`, are only available on
    /// tables.
    pub struct Table
}

implement! {
    pub struct TableSlice
}

/// **Selections** represent subsets of tables, for example,
/// the return values of `filter` or `get`.
///
/// There are three kinds of selections: `Selection<Object>`,
/// `Selection<Array>` and `Selection<Stream>`. The
/// difference between selections and their non-selection
/// counterparts is that selections are writable—their
/// return values can be passed as inputs to ReQL commands
/// that modify the database. For instance, the get command
/// will return a Selection<Object> that could then be
/// passed to an update or delete command.
///
/// (Note: _singleSelection_ is an older term for
/// Selection<Object>; they mean the same thing.)
/// Some commands (`order_by` and `between`) return a data
/// type similar to a selection called a `table_slice`.
/// In most cases a table_slice behaves identically to a
/// selection, but `between` can only be called on a table
/// or a table_slice, not any other kind of selection.
#[derive(Debug, Clone)]
pub struct Selection<T>(T);
implement! { Selection<Object> }
implement! { Selection<Array> }
implement! { Selection<Stream> }

pub type ObjectSelection = Selection<Object>;
pub type ArraySelection = Selection<Array>;
pub type StreamSelection = Selection<Stream>;

implement! {
    pub struct Command
}

implement! {
    pub struct PrimaryKey
}

implement! {
    pub struct SecondaryKey
}

impl<T> From<T> for Object
    where T: ToJson
{
    fn from(t: T) -> Object {
        let term = Term::from_json(t);
        From::from(term)
    }
}

impl<T> From<T> for String
    where T: Into<StdString>
{
    fn from(t: T) -> String {
        let mut datum = Datum::new();
        datum.set_field_type(DatumType::R_STR);
        datum.set_r_str(t.into());
        let mut output = String::new();
        output.0.set_field_type(TermType::DATUM);
        output.0.set_datum(datum);
        output
    }
}

impl<T> From<T> for Number
    where T: Into<f64>
{
    fn from(t: T) -> Number {
        let mut datum = Datum::new();
        datum.set_field_type(DatumType::R_NUM);
        datum.set_r_num(t.into());
        let mut output = Number::new();
        output.0.set_field_type(TermType::DATUM);
        output.0.set_datum(datum);
        output
    }
}

macro_rules! key_from_dt {
    ($T:ty) => {
        impl From<$T> for PrimaryKey {
            fn from(t: $T) -> PrimaryKey {
                let term: Term = t.into();
                From::from(term)
            }
        }

        impl From<$T> for SecondaryKey {
            fn from(t: $T) -> SecondaryKey {
                let term: Term = t.into();
                From::from(term)
            }
        }
    }
}

key_from_dt!{ String }
key_from_dt!{ Number }
key_from_dt!{ Bool }

impl<'a> From<&'a str> for PrimaryKey {
    fn from(t: &'a str) -> PrimaryKey {
        let dt = String::from(t);
        From::from(dt)
    }
}

impl<'a> From<&'a str> for SecondaryKey {
    fn from(t: &'a str) -> SecondaryKey {
        let dt = String::from(t);
        From::from(dt)
    }
}

macro_rules! key_from_st {
    ( $T:ident ) => {
        impl From<$T> for PrimaryKey {
            fn from(t: $T) -> PrimaryKey {
                let term = Term::from_json(t);
                From::from(term)
            }
        }

        impl From<$T> for SecondaryKey {
            fn from(t: $T) -> SecondaryKey {
                let term = Term::from_json(t);
                From::from(term)
            }
        }
    };
}

key_from_st!{ StdString }
key_from_st!{ bool }
key_from_st!{ f32 }
key_from_st!{ i32 }
key_from_st!{ u32 }
key_from_st!{ f64 }
key_from_st!{ i64 }
key_from_st!{ u64 }

impl Command {
    pub fn new(cmd_type: TermType, prev_cmd: Option<Term>) -> Command {
        let mut term = Term::new();
        term.set_field_type(cmd_type);
        if let Some(cmd) = prev_cmd {
            let args = RepeatedField::from_vec(vec![cmd]);
            term.set_args(args);
        }
        Command(term)
    }

    pub fn with_args(&mut self, args: Term) -> &mut Self {
        self.0.mut_args().push(args);
        self
    }

    pub fn with_opts(&mut self, opts: Object) -> &mut Self {
        let mut opts: Term = opts.into();
        if opts.has_datum() {
            let mut datum = opts.take_datum();
            let pairs = datum.take_r_object().into_vec();
            for mut pair in pairs {
                if pair.has_key() {
                    let mut term_pair = TermPair::new();
                    term_pair.set_key(pair.take_key());
                    let mut val = Term::new();
                    val.set_field_type(TermType::DATUM);
                    val.set_datum(pair.take_val());
                    term_pair.set_val(val);
                    self.0.mut_optargs().push(term_pair);
                }
            }
        }
        self
    }

    pub fn into<O>(self) -> O
        where O: From<Term>
    {
        From::from(self.0)
    }
}

impl Term {
    pub fn from_json<T: ToJson>(t: T) -> Term {
        // Datum
        let mut datum = Datum::new();
        match t.to_json() {
            Value::String(val) => {
                datum.set_field_type(DatumType::R_STR);
                datum.set_r_str(val);
            }
            Value::Bool(val) => {
                datum.set_field_type(DatumType::R_BOOL);
                datum.set_r_bool(val);
            }
            Value::I64(val) => {
                datum.set_field_type(DatumType::R_NUM);
                datum.set_r_num(val as f64);
            }
            Value::U64(val) => {
                datum.set_field_type(DatumType::R_NUM);
                datum.set_r_num(val as f64);
            }
            Value::F64(val) => {
                datum.set_field_type(DatumType::R_NUM);
                datum.set_r_num(val);
            }
            Value::Array(val) => {
                datum.set_field_type(DatumType::R_ARRAY);
                let args: Vec<Datum> = val.iter()
                    .map(|a| Term::from_json(a).take_datum())
                    .collect();
                let arr = RepeatedField::from_vec(args);
                datum.set_r_array(arr);
            }
            Value::Object(val) => {
                datum.set_field_type(DatumType::R_OBJECT);
                let args: Vec<DatumPair> = val.into_iter()
                    .map(|(name, arg)| {
                        let mut obj = DatumPair::new();
                        obj.set_key(name.into());
                        obj.set_val(Term::from_json(arg).take_datum());
                        obj
                    })
                    .collect();
                let obj = RepeatedField::from_vec(args);
                datum.set_r_object(obj);
            }
            Value::Null => {
                datum.set_field_type(DatumType::R_NULL);
            }
        }
        // Term
        let mut term = Term::new();
        term.set_field_type(TermType::DATUM);
        term.set_datum(datum);
        term
    }
}
<commit_msg>Cleanup types<commit_after>use std::string;

use proto::{Term, Datum,
    Term_TermType as TermType,
    Datum_DatumType as DatumType,
    Datum_AssocPair as DatumPair};

use protobuf::repeated::RepeatedField;
use serde_json::value::{ToJson, Value};

macro_rules! implement {
    (Selection<$dt:ident>) => {
        impl DataType for Selection<$dt> {}

        impl Selection<$dt> {
            pub fn new() -> Selection<$dt> {
                Selection::<$dt>($dt(Term::new()))
            }
        }

        impl From<Selection<$dt>> for Term {
            fn from(t: Selection<$dt>) -> Term {
                From::from(t.0)
            }
        }

        impl From<Term> for Selection<$dt> {
            fn from(t: Term) -> Selection<$dt> {
                Selection::<$dt>($dt(t))
            }
        }
    };

    ($(#[$attr:meta])* pub struct $dt:ident) => {
        $(
            #[$attr]
        )*
        #[derive(Debug, Clone)]
        pub struct $dt(Term);

        impl DataType for $dt {}

        impl $dt {
            pub fn new() -> $dt {
                $dt(Term::new())
            }
        }

        impl From<$dt> for Term {
            fn from(t: $dt) -> Term {
                t.0
            }
        }

        impl From<Term> for $dt {
            fn from(t: Term) -> $dt {
                $dt(t)
            }
        }
    };
}

pub trait DataType: From<Term> + Into<Term> + Clone {}

implement! {
    /// **Arrays** are lists of zero or more elements.
    ///
    /// ```json
    /// [1, 2, 3]
    /// []
    /// [{user: 'Bob', posts: 23}, {user: 'Jason', posts: 10}]
    /// ```
    /// Anything valid in a JSON array is valid in RethinkDB.
    /// The elements may be any of the basic values, objects,
    /// or other arrays. Arrays in RethinkDB are loaded fully
    /// into memory before they’re returned to the user, so
    /// they’re inefficient at large sizes. RethinkDB defaults
    /// to supporting arrays of up to 100,000 elements; this
    /// may be set to a different value at runtime for reading
    /// by using the `array_limit` option to run.
    pub struct Array
}

implement! {
    /// **Booleans** are `true` and `false`
    pub struct Bool
}

implement! {
    /// **Databases** are RethinkDB databases.
    ///
    /// This is the return type of `db`.
    pub struct Db
}

implement! {
    /// **Functions** can be passed as parameters to certain ReQL
    /// commands.
    pub struct Function
}

implement! {
    /// **Grouped data** is created by the `group` command.
    ///
    /// The command partitions a stream into multiple groups
    /// based on specified fields or functions. ReQL commands
    /// called on GroupedData operate on each group
    /// individually. For more details, read the group
    /// documentation. Depending on the input to group,
    /// grouped data may have the type of GroupedStream.
    pub struct GroupedData
}

implement! {
    pub struct GroupedStream
}

implement! {
    /// **Minval** and **maxval** are used with some commands such
    /// as `between` to specify absolute lower and upper bounds
    /// (e.g., `between(r.minval, 1000)` would return all
    /// documents in a table whose primary key is less than
    /// 1000).
    pub struct MaxVal
}

implement! {
    pub struct MinVal
}

implement! {
    /// **Null** is a value distinct from the number zero, an
    /// empty set, or a zero-length string.
    ///
    /// Natively this is
    /// `None`. It is often used to explicitly denote the
    /// absence of any other value. The root node of a tree
    /// structure might have a parent of `null`, or a required
    /// but as yet non-initialized key might be given a value
    /// of `null`.
    pub struct Null
}

implement! {
    /// **Numbers** are any real number: `5`, `3.14159`, `-42`.
    ///
    /// RethinkDB uses double precision (64-bit) floating point
    /// numbers internally. Neither infinity nor NaN are allowed.
    pub struct Number
}

implement! {
    /// **Objects** are JSON data objects, standard key-value pairs.
    ///
    /// ```json
    /// {
    ///     username: 'bob',
    ///     posts: 23,
    ///     favorites: {
    ///         color: 'blue',
    ///         food: 'tacos'
    ///     },
    ///     friends: ['agatha', 'jason']
    /// }
    /// ```
    ///
    /// Any valid JSON object is a valid RethinkDB object, so
    /// values can be any of the basic values, arrays, or
    /// other objects. Documents in a RethinkDB database are
    /// objects. Like JSON, key names must be strings, not
    /// integers.
    pub struct Object
}

implement! {
    /// **Binary** objects are similar to BLOBs in SQL databases:
    /// files, images and other binary data.
    ///
    /// See Storing binary objects for details.
    pub struct Binary
}

implement! {
    /// **Geometry** data types for geospatial support, including
    /// points, lines, and polygons.
    pub struct Geometry
}

implement! {
    /// **Times** are RethinkDB’s native date/time type, stored
    /// with millisecond precision.
    ///
    /// You can use native date/time types in supported
    /// languages, as the conversion will be done by the driver.
    /// See Dates and times in RethinkDB for details.
    pub struct Time
}

implement! {
    /// **Streams** are lists like arrays, but they’re loaded in
    /// a lazy fashion.
    ///
    /// Operations that return streams return a `cursor`.
    /// A cursor is a pointer into the result set. Instead of
    /// reading the results all at once like an array, you
    /// loop over the results, retrieving the next member of the
    /// set with each iteration. This makes it possible to
    /// efficiently work with large result sets.
    ///
    /// (See “Working with Streams,” below, for some tips.)
    /// Streams are read-only; you can’t pass one as an input
    /// to an ReQL command meant to modify its input like
    /// `update` or `delete`.
    pub struct Stream
}

implement! {
    /// **Strings** are any valid UTF-8 string: `"superhero"`,
    /// `"ünnëcëssärÿ ümläüts"`. Strings may include the null
    /// code point (U+0000).
    pub struct String
}

implement! {
    /// **Tables** are RethinkDB database tables.
    ///
    /// They behave like selections—they’re writable, as you can
    /// insert and delete documents in them. ReQL methods that
    /// use an index, like `get_all`, are only available on
    /// tables.
    pub struct Table
}

implement! {
    pub struct TableSlice
}

/// **Selections** represent subsets of tables, for example,
/// the return values of `filter` or `get`.
///
/// There are three kinds of selections: `Selection<Object>`,
/// `Selection<Array>` and `Selection<Stream>`. The
/// difference between selections and their non-selection
/// counterparts is that selections are writable—their
/// return values can be passed as inputs to ReQL commands
/// that modify the database. For instance, the get command
/// will return a Selection<Object> that could then be
/// passed to an update or delete command.
///
/// (Note: _singleSelection_ is an older term for
/// Selection<Object>; they mean the same thing.)
/// Some commands (`order_by` and `between`) return a data
/// type similar to a selection called a `table_slice`.
/// In most cases a table_slice behaves identically to a
/// selection, but `between` can only be called on a table
/// or a table_slice, not any other kind of selection.
#[derive(Debug, Clone)]
pub struct Selection<T>(T);
implement! { Selection<Object> }
implement! { Selection<Array> }
implement! { Selection<Stream> }

pub type ObjectSelection = Selection<Object>;
pub type ArraySelection = Selection<Array>;
pub type StreamSelection = Selection<Stream>;

impl<T> From<T> for Object
    where T: ToJson
{
    fn from(t: T) -> Object {
        let term = Term::from_json(t);
        From::from(term)
    }
}

impl<T> From<T> for String
    where T: Into<string::String>
{
    fn from(t: T) -> String {
        let mut datum = Datum::new();
        datum.set_field_type(DatumType::R_STR);
        datum.set_r_str(t.into());
        let mut output = String::new();
        output.0.set_field_type(TermType::DATUM);
        output.0.set_datum(datum);
        output
    }
}

impl<T> From<T> for Number
    where T: Into<f64>
{
    fn from(t: T) -> Number {
        let mut datum = Datum::new();
        datum.set_field_type(DatumType::R_NUM);
        datum.set_r_num(t.into());
        let mut output = Number::new();
        output.0.set_field_type(TermType::DATUM);
        output.0.set_datum(datum);
        output
    }
}

impl Term {
    pub fn from_json<T: ToJson>(t: T) -> Term {
        // Datum
        let mut datum = Datum::new();
        match t.to_json() {
            Value::String(val) => {
                datum.set_field_type(DatumType::R_STR);
                datum.set_r_str(val);
            }
            Value::Bool(val) => {
                datum.set_field_type(DatumType::R_BOOL);
                datum.set_r_bool(val);
            }
            Value::I64(val) => {
                datum.set_field_type(DatumType::R_NUM);
                datum.set_r_num(val as f64);
            }
            Value::U64(val) => {
                datum.set_field_type(DatumType::R_NUM);
                datum.set_r_num(val as f64);
            }
            Value::F64(val) => {
                datum.set_field_type(DatumType::R_NUM);
                datum.set_r_num(val);
            }
            Value::Array(val) => {
                datum.set_field_type(DatumType::R_ARRAY);
                let args: Vec<Datum> = val.iter()
                    .map(|a| Term::from_json(a).take_datum())
                    .collect();
                let arr = RepeatedField::from_vec(args);
                datum.set_r_array(arr);
            }
            Value::Object(val) => {
                datum.set_field_type(DatumType::R_OBJECT);
                let args: Vec<DatumPair> = val.into_iter()
                    .map(|(name, arg)| {
                        let mut obj = DatumPair::new();
                        obj.set_key(name.into());
                        obj.set_val(Term::from_json(arg).take_datum());
                        obj
                    })
                    .collect();
                let obj = RepeatedField::from_vec(args);
                datum.set_r_object(obj);
            }
            Value::Null => {
                datum.set_field_type(DatumType::R_NULL);
            }
        }
        // Term
        let mut term = Term::new();
        term.set_field_type(TermType::DATUM);
        term.set_datum(datum);
        term
    }
}
<|endoftext|>


<commit_before>use std::os::raw::c_int;
use std::convert::{From, Into};
use std::result;
use std::fmt;

use ffi;

pub type PortMidiDeviceId = c_int;

/// PortMidi result type.
pub type Result<T> = result::Result<T, Error>;
impl From<ffi::PmError> for Result<()> {
    fn from(err: ffi::PmError) -> Self {
        match err {
            ffi::PmError::PmNoError | ffi::PmError::PmGotData => Ok(()),
            _ => Err(Error::PortMidi(err)),
        }
    }
}

/// PortMidi error type.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Error {
    PortMidi(ffi::PmError),
    Unknown,
    Unimplemented,
    NoDefaultDevice,
    NotAnInputDevice,
    NotAnOutputDevice,
    Invalid,
}
impl From<ffi::PmError> for Error {
    fn from(err: ffi::PmError) -> Self {
        match err {
            err @ _ => Error::PortMidi(err),
        }
    }
}
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::PortMidi(pm_err) => write!(f, "{}", pm_err),
            err @ _ => write!(f, "{:?}", err),
        }
    }
}

/// Represents a Midi message.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: u8,
    pub data1: u8,
    pub data2: u8,
}
impl From<[u8; 3]> for MidiMessage {
    fn from(raw: [u8; 3]) -> Self {
        MidiMessage {
            status: raw[0],
            data1: raw[1],
            data2: raw[2],
        }
    }
}
impl fmt::Display for MidiMessage {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "status: {}, data: {}, {}",
               self.status,
               self.data1,
               self.data2)
    }
}
/// Converts a `PmMessage` to a `MidiMessage.
/// This can be used for `c_int` as well as `i32` because these are only type aliases.
impl From<ffi::PmMessage> for MidiMessage {
    fn from(raw: i32) -> Self {
        MidiMessage {
            status: (raw & 0x00_00_00_FF) as u8,
            data1: ((raw & 0x00_00_FF_00) >> 8) as u8,
            data2: ((raw & 0x00_FF_00_00) >> 16) as u8,
        }
    }
}
impl Into<ffi::PmMessage> for MidiMessage {
    fn into(self) -> i32 {
        (((self.data2 as i32) << 16)) | (((self.data1 as i32) << 8)) | self.status as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiEvent {
    pub message: MidiMessage,
    pub timestamp: ffi::PmTimestamp,
}
impl From<ffi::PmEvent> for MidiEvent {
    fn from(raw: ffi::PmEvent) -> Self {
        MidiEvent {
            message: MidiMessage::from(raw.message),
            timestamp: raw.timestamp,
        }
    }
}
impl From<MidiMessage> for MidiEvent {
    fn from(msg: MidiMessage) -> Self {
        MidiEvent {
            message: msg,
            timestamp: 0,
        }
    }
}
impl Into<ffi::PmEvent> for MidiEvent {
    fn into(self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: MidiMessage::into(self.message),
            timestamp: self.timestamp,
        }
    }
}
<commit_msg>Implement std::error::Error<commit_after>use std::error;
use std::os::raw::c_int;
use std::convert::{From, Into};
use std::result;
use std::fmt;

use ffi;

pub type PortMidiDeviceId = c_int;

/// PortMidi result type.
pub type Result<T> = result::Result<T, Error>;
impl From<ffi::PmError> for Result<()> {
    fn from(err: ffi::PmError) -> Self {
        match err {
            ffi::PmError::PmNoError | ffi::PmError::PmGotData => Ok(()),
            _ => Err(Error::PortMidi(err)),
        }
    }
}

/// PortMidi error type.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Error {
    PortMidi(ffi::PmError),
    Unknown,
    Unimplemented,
    NoDefaultDevice,
    NotAnInputDevice,
    NotAnOutputDevice,
    Invalid,
}
impl From<ffi::PmError> for Error {
    fn from(err: ffi::PmError) -> Self {
        match err {
            err @ _ => Error::PortMidi(err),
        }
    }
}
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::PortMidi(pm_err) => write!(f, "{}", pm_err),
            err @ _ => write!(f, "{:?}", err),
        }
    }
}
impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::PortMidi(pm_error)   => match pm_error {
                ffi::PmError::PmNoError             => "No error",
                ffi::PmError::PmGotData             => "Got data",
                ffi::PmError::PmHostError           => "Host error",
                ffi::PmError::PmInvalidDeviceId     => "Invalid device ID",
                ffi::PmError::PmInsufficientMemory  => "Insufficient memory",
                ffi::PmError::PmBufferTooSmall      => "Buffer too small",
                ffi::PmError::PmBufferOverflow      => "Buffer overflow",
                ffi::PmError::PmBadPtr              => "Bad pointer",
                ffi::PmError::PmBadData             => "Bad data",
                ffi::PmError::PmInternalError       => "Internal error",
                ffi::PmError::PmBufferMaxSize       => "Buffer max size"
            },
            Error::Unknown              => "Unknown",
            Error::Unimplemented        => "Unimplemented",
            Error::NoDefaultDevice      => "No default device",
            Error::NotAnInputDevice     => "Not an input device",
            Error::NotAnOutputDevice    => "Not an output device",
            Error::Invalid              => "Invalid"
        }
    }
}

/// Represents a Midi message.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: u8,
    pub data1: u8,
    pub data2: u8,
}
impl From<[u8; 3]> for MidiMessage {
    fn from(raw: [u8; 3]) -> Self {
        MidiMessage {
            status: raw[0],
            data1: raw[1],
            data2: raw[2],
        }
    }
}
impl fmt::Display for MidiMessage {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "status: {}, data: {}, {}",
               self.status,
               self.data1,
               self.data2)
    }
}
/// Converts a `PmMessage` to a `MidiMessage.
/// This can be used for `c_int` as well as `i32` because these are only type aliases.
impl From<ffi::PmMessage> for MidiMessage {
    fn from(raw: i32) -> Self {
        MidiMessage {
            status: (raw & 0x00_00_00_FF) as u8,
            data1: ((raw & 0x00_00_FF_00) >> 8) as u8,
            data2: ((raw & 0x00_FF_00_00) >> 16) as u8,
        }
    }
}
impl Into<ffi::PmMessage> for MidiMessage {
    fn into(self) -> i32 {
        (((self.data2 as i32) << 16)) | (((self.data1 as i32) << 8)) | self.status as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiEvent {
    pub message: MidiMessage,
    pub timestamp: ffi::PmTimestamp,
}
impl From<ffi::PmEvent> for MidiEvent {
    fn from(raw: ffi::PmEvent) -> Self {
        MidiEvent {
            message: MidiMessage::from(raw.message),
            timestamp: raw.timestamp,
        }
    }
}
impl From<MidiMessage> for MidiEvent {
    fn from(msg: MidiMessage) -> Self {
        MidiEvent {
            message: msg,
            timestamp: 0,
        }
    }
}
impl Into<ffi::PmEvent> for MidiEvent {
    fn into(self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: MidiMessage::into(self.message),
            timestamp: self.timestamp,
        }
    }
}
<|endoftext|>


<commit_before>//! General-use structs and methods.

use std::ascii::AsciiExt;
use std::f64;
use std::str;

use {Error, Result};

/// x, y, and z values in one struct.
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Triple<T: Copy> {
    /// The x value of the triple.
    pub x: T,
    /// The y value of the triple.
    pub y: T,
    /// The z value of the triple.
    pub z: T,
}

impl<T: Copy> Triple<T> {
    /// Creates a new triple.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::utils::Triple;
    /// let triple = Triple::new(1., 2., 3.);
    /// ```
    pub fn new(x: T, y: T, z: T) -> Triple<T> {
        Triple { x: x, y: y, z: z }
    }
}

/// Three-dimensional bounds.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Bounds<T: Copy> {
    /// The smallest corner of the bounds.
    pub min: Triple<T>,
    /// The largest corner of the bounds.
    pub max: Triple<T>,
}

impl<T: Copy> Bounds<T> {
    /// Creates a new bounds from min and max values.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::utils::Bounds;
    /// let bounds = Bounds::new(1., 2., 3., 4., 5., 6.);
    /// ```
    pub fn new(minx: T, miny: T, minz: T, maxx: T, maxy: T, maxz: T) -> Bounds<T> {
        Bounds {
            min: Triple {
                x: minx,
                y: miny,
                z: minz,
            },
            max: Triple {
                x: maxx,
                y: maxy,
                z: maxz,
            },
        }
    }
}

impl Bounds<f64> {
    /// Grows the bounds to include the point.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::utils::{Triple, Bounds};
    /// let mut bounds = Bounds::new(1., 2., 3., 4., 5., 6.);
    /// let point = Triple { x: 10., y: 11., z: 12. };
    /// bounds.grow(point);
    /// assert_eq!(point, bounds.max);
    /// ```
    pub fn grow(&mut self, triple: Triple<f64>) {
        self.min.x = self.min.x.min(triple.x);
        self.min.y = self.min.y.min(triple.y);
        self.min.z = self.min.z.min(triple.z);
        self.max.x = self.max.x.max(triple.x);
        self.max.y = self.max.y.max(triple.y);
        self.max.z = self.max.z.max(triple.z);
    }
}

impl Default for Bounds<f64> {
    fn default() -> Bounds<f64> {
        Bounds {
            min: Triple {
                x: f64::INFINITY,
                y: f64::INFINITY,
                z: f64::INFINITY,
            },
            max: Triple {
                x: f64::NEG_INFINITY,
                y: f64::NEG_INFINITY,
                z: f64::NEG_INFINITY,
            },
        }
    }
}

/// Converts bytes into a string, following LAS rules.
///
/// LAS specifies that all string fields should be ASCII and nul filled, but not all LAS data in
/// the wild follows these rules (here's looking at you, Riegl). This trait has two methods, one
/// permissive (`to_las_str`) and one strict (`to_las_str_strict`). The first just does it's best
/// to produce some sort of `&str`, while the second checks the rules.
pub trait ToLasStr {
    /// Interprets the bytes as a `&str`, permissively.
    ///
    /// # Examples
    ///
    /// `[u8]` implements `ToLasStr`.
    ///
    /// ```
    /// use las::utils::ToLasStr;
    /// assert_eq!("LiDAR", [76, 105, 68, 65, 82, 0, 33].to_las_str().unwrap());
    /// ```
    fn to_las_str(&self) -> Result<&str>;

    /// Interprets the bytes as a `&str`, enforcing the LAS rules.
    ///
    /// # Examples
    ///
    /// `[u8]` implements `ToLasStr`.
    ///
    /// ```
    /// use las::utils::ToLasStr;
    /// assert!([76, 105, 68, 65, 82, 0, 33].to_las_str_strict().is_err());
    /// ```
    fn to_las_str_strict(&self) -> Result<&str>;
}

impl ToLasStr for [u8] {
    fn to_las_str(&self) -> Result<&str> {
        if let Some(idx) = self.iter().position(|&n| n == 0) {
                str::from_utf8(&self[0..idx])
            } else {
                str::from_utf8(&self)
            }
            .map_err(Error::from)
    }

    fn to_las_str_strict(&self) -> Result<&str> {
        let s = try!(if let Some(idx) = self.iter().position(|&n| n == 0) {
            if self[idx..].iter().all(|&n| n == 0) {
                str::from_utf8(&self[0..idx]).map_err(Error::from)
            } else {
                Err(Error::NotNulFilled(self.to_vec()))
            }
        } else {
            str::from_utf8(&self).map_err(Error::from)
        });
        if s.is_ascii() {
            Ok(s)
        } else {
            Err(Error::NotAscii(s.to_string()))
        }
    }
}

/// A linear transformation.
///
/// If `y = ax + b`, `a` is the scale and `b` is the offset.
///
/// # Examples
///
/// Linear transforms can be created from `(f64, f64)`:
///
/// ```
/// # use las::utils::LinearTransform;
/// let transform = LinearTransform::from((1., 0.));
/// ```
///
/// The `scale * x + offset` version of the transformation can be computed with `direct`:
///
/// ```
/// # use las::utils::LinearTransform;
/// let transform = LinearTransform::from((2., 1.));
/// assert_eq!(7., transform.direct(3));
/// ```
///
/// The `inverse` computes `(x - offset) / scale`:
///
/// ```
/// # use las::utils::LinearTransform;
/// # let transform = LinearTransform::from((2., 1.));
/// assert_eq!(3, transform.inverse(7.));
/// ```
#[derive(Clone, Copy, Debug)]
pub struct LinearTransform {
    /// The mutiplicative constant.
    pub scale: f64,
    /// The additive constant.
    pub offset: f64,
}

impl LinearTransform {
    /// Computes the forward (direct) transformation, `scale * x + offset`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::utils::LinearTransform;
    /// let transform = LinearTransform::from((2., 1.));
    /// assert_eq!(7., transform.direct(3));
    /// ```
    pub fn direct(&self, n: i32) -> f64 {
        self.scale * n as f64 + self.offset
    }

    /// Computes the backwards (inverse) transformation, `(x - offset) / scale`.
    ///
    /// TODO formalize truncating/rounding.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::utils::LinearTransform;
    /// let transform = LinearTransform::from((2., 1.));
    /// assert_eq!(3, transform.inverse(7.));
    /// ```
    pub fn inverse(&self, n: f64) -> i32 {
        ((n - self.offset) / self.scale) as i32
    }
}

impl Default for LinearTransform {
    fn default() -> LinearTransform {
        LinearTransform {
            scale: 1.,
            offset: 0.,
        }
    }
}

impl From<(f64, f64)> for LinearTransform {
    fn from((scale, offset): (f64, f64)) -> LinearTransform {
        LinearTransform {
            scale: scale,
            offset: offset,
        }
    }
}

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

    #[test]
    fn bounds_new() {
        let bounds = Bounds::new(1., 2., 3., 4., 5., 6.);
        assert_eq!(1., bounds.min.x);
        assert_eq!(2., bounds.min.y);
        assert_eq!(3., bounds.min.z);
        assert_eq!(4., bounds.max.x);
        assert_eq!(5., bounds.max.y);
        assert_eq!(6., bounds.max.z);
    }

    #[test]
    fn bounds_grow() {
        let mut bounds: Bounds<f64> = Default::default();
        bounds.grow(Triple::new(1., 2., 3.));
        bounds.grow(Triple::new(-1., -2., -3.));
        assert_eq!(Bounds::new(-1., -2., -3., 1., 2., 3.), bounds);
    }

    #[test]
    fn to_las_str_empty() {
        let buf = [0; 0];
        assert_eq!("", buf.to_las_str().unwrap());
        assert_eq!("", buf.to_las_str_strict().unwrap());
    }

    #[test]
    fn to_las_str_one() {
        let buf = [76];
        assert_eq!("L", buf.to_las_str().unwrap());
        assert_eq!("L", buf.to_las_str_strict().unwrap());
    }

    #[test]
    fn to_las_str_not_filled() {
        let buf = [76, 0, 33];
        assert_eq!("L", buf.to_las_str().unwrap());
        assert!(buf.to_las_str_strict().is_err());
    }

    #[test]
    fn to_las_str_unicode() {
        let buf = [240, 159, 146, 150];
        assert_eq!("\u{1f496}", buf.to_las_str().unwrap());
        assert!(buf.to_las_str_strict().is_err());
    }

    #[test]
    fn linear_transformation_identity() {
        let transform = LinearTransform::from((1.0, 0.));
        assert_eq!(2., transform.direct(2));
        assert_eq!(2, transform.inverse(2.));
    }

    #[test]
    fn linear_transformation_changes() {
        let transform = LinearTransform::from((2.0, 1.));
        assert_eq!(7., transform.direct(3));
        assert_eq!(3, transform.inverse(7.));
    }
}
<commit_msg>Round inverse linear transforms<commit_after>//! General-use structs and methods.

use std::ascii::AsciiExt;
use std::f64;
use std::str;

use {Error, Result};

/// x, y, and z values in one struct.
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Triple<T: Copy> {
    /// The x value of the triple.
    pub x: T,
    /// The y value of the triple.
    pub y: T,
    /// The z value of the triple.
    pub z: T,
}

impl<T: Copy> Triple<T> {
    /// Creates a new triple.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::utils::Triple;
    /// let triple = Triple::new(1., 2., 3.);
    /// ```
    pub fn new(x: T, y: T, z: T) -> Triple<T> {
        Triple { x: x, y: y, z: z }
    }
}

/// Three-dimensional bounds.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Bounds<T: Copy> {
    /// The smallest corner of the bounds.
    pub min: Triple<T>,
    /// The largest corner of the bounds.
    pub max: Triple<T>,
}

impl<T: Copy> Bounds<T> {
    /// Creates a new bounds from min and max values.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::utils::Bounds;
    /// let bounds = Bounds::new(1., 2., 3., 4., 5., 6.);
    /// ```
    pub fn new(minx: T, miny: T, minz: T, maxx: T, maxy: T, maxz: T) -> Bounds<T> {
        Bounds {
            min: Triple {
                x: minx,
                y: miny,
                z: minz,
            },
            max: Triple {
                x: maxx,
                y: maxy,
                z: maxz,
            },
        }
    }
}

impl Bounds<f64> {
    /// Grows the bounds to include the point.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::utils::{Triple, Bounds};
    /// let mut bounds = Bounds::new(1., 2., 3., 4., 5., 6.);
    /// let point = Triple { x: 10., y: 11., z: 12. };
    /// bounds.grow(point);
    /// assert_eq!(point, bounds.max);
    /// ```
    pub fn grow(&mut self, triple: Triple<f64>) {
        self.min.x = self.min.x.min(triple.x);
        self.min.y = self.min.y.min(triple.y);
        self.min.z = self.min.z.min(triple.z);
        self.max.x = self.max.x.max(triple.x);
        self.max.y = self.max.y.max(triple.y);
        self.max.z = self.max.z.max(triple.z);
    }
}

impl Default for Bounds<f64> {
    fn default() -> Bounds<f64> {
        Bounds {
            min: Triple {
                x: f64::INFINITY,
                y: f64::INFINITY,
                z: f64::INFINITY,
            },
            max: Triple {
                x: f64::NEG_INFINITY,
                y: f64::NEG_INFINITY,
                z: f64::NEG_INFINITY,
            },
        }
    }
}

/// Converts bytes into a string, following LAS rules.
///
/// LAS specifies that all string fields should be ASCII and nul filled, but not all LAS data in
/// the wild follows these rules (here's looking at you, Riegl). This trait has two methods, one
/// permissive (`to_las_str`) and one strict (`to_las_str_strict`). The first just does it's best
/// to produce some sort of `&str`, while the second checks the rules.
pub trait ToLasStr {
    /// Interprets the bytes as a `&str`, permissively.
    ///
    /// # Examples
    ///
    /// `[u8]` implements `ToLasStr`.
    ///
    /// ```
    /// use las::utils::ToLasStr;
    /// assert_eq!("LiDAR", [76, 105, 68, 65, 82, 0, 33].to_las_str().unwrap());
    /// ```
    fn to_las_str(&self) -> Result<&str>;

    /// Interprets the bytes as a `&str`, enforcing the LAS rules.
    ///
    /// # Examples
    ///
    /// `[u8]` implements `ToLasStr`.
    ///
    /// ```
    /// use las::utils::ToLasStr;
    /// assert!([76, 105, 68, 65, 82, 0, 33].to_las_str_strict().is_err());
    /// ```
    fn to_las_str_strict(&self) -> Result<&str>;
}

impl ToLasStr for [u8] {
    fn to_las_str(&self) -> Result<&str> {
        if let Some(idx) = self.iter().position(|&n| n == 0) {
                str::from_utf8(&self[0..idx])
            } else {
                str::from_utf8(&self)
            }
            .map_err(Error::from)
    }

    fn to_las_str_strict(&self) -> Result<&str> {
        let s = try!(if let Some(idx) = self.iter().position(|&n| n == 0) {
            if self[idx..].iter().all(|&n| n == 0) {
                str::from_utf8(&self[0..idx]).map_err(Error::from)
            } else {
                Err(Error::NotNulFilled(self.to_vec()))
            }
        } else {
            str::from_utf8(&self).map_err(Error::from)
        });
        if s.is_ascii() {
            Ok(s)
        } else {
            Err(Error::NotAscii(s.to_string()))
        }
    }
}

/// A linear transformation.
///
/// If `y = ax + b`, `a` is the scale and `b` is the offset.
///
/// # Examples
///
/// Linear transforms can be created from `(f64, f64)`:
///
/// ```
/// # use las::utils::LinearTransform;
/// let transform = LinearTransform::from((1., 0.));
/// ```
///
/// The `scale * x + offset` version of the transformation can be computed with `direct`:
///
/// ```
/// # use las::utils::LinearTransform;
/// let transform = LinearTransform::from((2., 1.));
/// assert_eq!(7., transform.direct(3));
/// ```
///
/// The `inverse` computes `(x - offset) / scale`:
///
/// ```
/// # use las::utils::LinearTransform;
/// # let transform = LinearTransform::from((2., 1.));
/// assert_eq!(3, transform.inverse(7.));
/// ```
#[derive(Clone, Copy, Debug)]
pub struct LinearTransform {
    /// The mutiplicative constant.
    pub scale: f64,
    /// The additive constant.
    pub offset: f64,
}

impl LinearTransform {
    /// Computes the forward (direct) transformation, `scale * x + offset`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::utils::LinearTransform;
    /// let transform = LinearTransform::from((2., 1.));
    /// assert_eq!(7., transform.direct(3));
    /// ```
    pub fn direct(&self, n: i32) -> f64 {
        self.scale * n as f64 + self.offset
    }

    /// Computes the backwards (inverse) transformation, `(x - offset) / scale`.
    ///
    /// The resulting float is rounded to the nearest integer.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::utils::LinearTransform;
    /// let transform = LinearTransform::from((2., 1.));
    /// assert_eq!(3, transform.inverse(7.));
    /// ```
    pub fn inverse(&self, n: f64) -> i32 {
        ((n - self.offset) / self.scale).round() as i32
    }
}

impl Default for LinearTransform {
    fn default() -> LinearTransform {
        LinearTransform {
            scale: 1.,
            offset: 0.,
        }
    }
}

impl From<(f64, f64)> for LinearTransform {
    fn from((scale, offset): (f64, f64)) -> LinearTransform {
        LinearTransform {
            scale: scale,
            offset: offset,
        }
    }
}

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

    #[test]
    fn bounds_new() {
        let bounds = Bounds::new(1., 2., 3., 4., 5., 6.);
        assert_eq!(1., bounds.min.x);
        assert_eq!(2., bounds.min.y);
        assert_eq!(3., bounds.min.z);
        assert_eq!(4., bounds.max.x);
        assert_eq!(5., bounds.max.y);
        assert_eq!(6., bounds.max.z);
    }

    #[test]
    fn bounds_grow() {
        let mut bounds: Bounds<f64> = Default::default();
        bounds.grow(Triple::new(1., 2., 3.));
        bounds.grow(Triple::new(-1., -2., -3.));
        assert_eq!(Bounds::new(-1., -2., -3., 1., 2., 3.), bounds);
    }

    #[test]
    fn to_las_str_empty() {
        let buf = [0; 0];
        assert_eq!("", buf.to_las_str().unwrap());
        assert_eq!("", buf.to_las_str_strict().unwrap());
    }

    #[test]
    fn to_las_str_one() {
        let buf = [76];
        assert_eq!("L", buf.to_las_str().unwrap());
        assert_eq!("L", buf.to_las_str_strict().unwrap());
    }

    #[test]
    fn to_las_str_not_filled() {
        let buf = [76, 0, 33];
        assert_eq!("L", buf.to_las_str().unwrap());
        assert!(buf.to_las_str_strict().is_err());
    }

    #[test]
    fn to_las_str_unicode() {
        let buf = [240, 159, 146, 150];
        assert_eq!("\u{1f496}", buf.to_las_str().unwrap());
        assert!(buf.to_las_str_strict().is_err());
    }

    #[test]
    fn linear_transformation_identity() {
        let transform = LinearTransform::from((1.0, 0.));
        assert_eq!(2., transform.direct(2));
        assert_eq!(2, transform.inverse(2.));
    }

    #[test]
    fn linear_transformation_changes() {
        let transform = LinearTransform::from((2.0, 1.));
        assert_eq!(7., transform.direct(3));
        assert_eq!(3, transform.inverse(7.));
    }

    #[test]
    fn linear_transformation_rounding() {
        let transform = LinearTransform::from((4., 0.));
        assert_eq!(1, transform.inverse(3.));
    }
}
<|endoftext|>