<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()
    }
}

pub struct Square<'a> {
    pub universe: &'a Universe,
    pub shape: &'a Shape,
    pub position: UPoint,
}

impl<'a> Square<'a> {
    fn location_on(&self, parent_id: ShapeId) -> Option<Location> {
        let pos_on = self.shape.parent_ids.get(&parent_id)?;
        let new_shape = &self.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 {
                universe: self.universe,
                shape: new_shape,
                position: new_pos.to_point(),
            },
            subposition: new_subp,
        })
    }

    fn location(&self) -> Location {
        // TODO: This sort of sanity checking is slower, probably doesn't matter
        let mut locations: Vec<Location> = self.shape
            .parent_ids
            .keys()
            .filter_map(|s| self.location_on(*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<'a> {
    pub square: Square<'a>,
    pub subposition: ChildVec,
}

impl<'a> Location<'a> {
    pub fn inhabitant(&self) -> Option<Square> {
        let c = self.to_coordinate();

        let mut inhabitants: Vec<Square> = self.square
            .universe
            .parents_with_position_of(self.square.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 {
                    universe: self.square.universe,
                    shape: s,
                    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>Make Square and Location not store references<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) -> () {}
}

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!()
        }
    }
}
<|endoftext|>


<commit_before>

extern crate lapack;

use self::lapack::fortran::*;
use num_traits::Zero;

use error::LapackError;

pub trait ImplSolve: Sized {
    fn inv(size: usize, mut a: Vec<Self>) -> Result<Vec<Self>, LapackError>;
}

impl ImplSolve for f64 {
    fn inv(size: usize, mut a: Vec<Self>) -> Result<Vec<Self>, LapackError> {
        let n = size as i32;
        let lda = n;
        let mut ipiv = vec![0; size];
        let mut info = 0;
        dgetrf(n, n, &mut a, lda, &mut ipiv, &mut info);
        if info != 0 {
            return Err(From::from(info));
        }
        let lwork = n;
        let mut work = vec![Self::zero(); size];
        dgetri(n, &mut a, lda, &mut ipiv, &mut work, lwork, &mut info);
        if info == 0 {
            Ok(a)
        } else {
            Err(From::from(info))
        }
    }
}
<commit_msg>Fix format<commit_after>
extern crate lapack;

use self::lapack::fortran::*;
use num_traits::Zero;

use error::LapackError;

pub trait ImplSolve: Sized {
    fn inv(size: usize, mut a: Vec<Self>) -> Result<Vec<Self>, LapackError>;
}

impl ImplSolve for f64 {
    fn inv(size: usize, mut a: Vec<Self>) -> Result<Vec<Self>, LapackError> {
        let n = size as i32;
        let lda = n;
        let mut ipiv = vec![0; size];
        let mut info = 0;
        dgetrf(n, n, &mut a, lda, &mut ipiv, &mut info);
        if info != 0 {
            return Err(From::from(info));
        }
        let lwork = n;
        let mut work = vec![Self::zero(); size];
        dgetri(n, &mut a, lda, &mut ipiv, &mut work, lwork, &mut info);
        if info == 0 {
            Ok(a)
        } else {
            Err(From::from(info))
        }
    }
}
<|endoftext|>


<commit_before>use utils::bigint::M256;
use std::cmp::{min};
use super::{Result, Error};
use super::opcode::Opcode;

pub trait PC {
    fn peek_opcode(&self) -> Result<Opcode>;
    fn read_opcode(&mut self) -> Result<Opcode>;
    fn stop(&mut self);
    fn stopped(&self) -> bool;
    fn read(&mut self, byte_count: usize) -> Result<M256>;
    fn position(&self) -> usize;
    fn jump(&mut self, position: usize) -> Result<()>;
    fn code(&self) -> &[u8];
}

pub struct VectorPC {
    position: usize,
    code: Vec<u8>,
    stopped: bool
}

impl VectorPC {
    pub fn new(code: &[u8]) -> Self {
        VectorPC {
            position: 0,
            code: code.into(),
            stopped: false,
        }
    }
}

impl PC for VectorPC {
    fn code(&self) -> &[u8] {
        self.code.as_ref()
    }

    fn jump(&mut self, position: usize) -> Result<()> {
        if position >= self.code.len() {
            return Err(Error::PCOverflow);
        }

        let opcode: Opcode = self.code[position].into();
        if opcode != Opcode::JUMPDEST {
            return Err(Error::PCBadJumpDest);
        }

        self.position = position;
        Ok(())
    }

    fn position(&self) -> usize {
        self.position
    }

    fn peek_opcode(&self) -> Result<Opcode> {
        let position = self.position;
        if position >= self.code.len() {
            return Err(Error::PCOverflow);
        }
        let opcode: Opcode = self.code[position].into();
        Ok(opcode)
    }

    fn read_opcode(&mut self) -> Result<Opcode> {
        let position = self.position;
        if position.checked_add(1).is_none() {
            return Err(Error::PCTooLarge);
        }
        if position >= self.code.len() {
            return Err(Error::PCOverflow);
        }
        let opcode: Opcode = self.code[position].into();
        self.position += 1;
        Ok(opcode)
    }

    fn stop(&mut self) {
        self.stopped = true;
    }

    fn stopped(&self) -> bool {
        self.stopped || self.position >= self.code.len()
    }

    fn read(&mut self, byte_count: usize) -> Result<M256> {
        let position = self.position;
        if position.checked_add(byte_count).is_none() {
            return Err(Error::PCTooLarge);
        }
        self.position += byte_count;
        let max = min(position + byte_count, self.code.len());
        Ok(M256::from(&self.code[position..max]))
    }
}
<commit_msg>Problem: PUSH data in code is not handled Solution: check validity of code when initializing VectorPC<commit_after>use utils::bigint::M256;
use std::cmp::{min};
use super::{Result, Error};
use super::opcode::Opcode;

pub trait PC {
    fn peek_opcode(&self) -> Result<Opcode>;
    fn read_opcode(&mut self) -> Result<Opcode>;
    fn stop(&mut self);
    fn stopped(&self) -> bool;
    fn read(&mut self, byte_count: usize) -> Result<M256>;
    fn position(&self) -> usize;
    fn jump(&mut self, position: usize) -> Result<()>;
    fn code(&self) -> &[u8];
}

pub struct VectorPC {
    position: usize,
    code: Vec<u8>,
    valids: Vec<bool>,
    stopped: bool
}

impl VectorPC {
    pub fn new(code: &[u8]) -> Self {
        let code: Vec<u8> = code.into();
        let mut valids: Vec<bool> = Vec::with_capacity(code.len());
        valids.resize(code.len(), false);

        let mut i = 0;
        while i < code.len() {
            let opcode: Opcode = code[i].into();
            match opcode {
                Opcode::JUMPDEST => {
                    valids[i] = true;
                    i = i + 1;
                },
                Opcode::PUSH(v) => {
                    i = i + v + 1;
                },
                _ => {
                    i = i + 1;
                }
            }
        }

        VectorPC {
            position: 0,
            code: code,
            valids: valids,
            stopped: false,
        }
    }
}

impl PC for VectorPC {
    fn code(&self) -> &[u8] {
        self.code.as_ref()
    }

    fn jump(&mut self, position: usize) -> Result<()> {
        if position >= self.code.len() {
            return Err(Error::PCOverflow);
        }

        if !self.valids[position] {
            return Err(Error::PCBadJumpDest);
        }

        self.position = position;
        Ok(())
    }

    fn position(&self) -> usize {
        self.position
    }

    fn peek_opcode(&self) -> Result<Opcode> {
        let position = self.position;
        if position >= self.code.len() {
            return Err(Error::PCOverflow);
        }
        let opcode: Opcode = self.code[position].into();
        Ok(opcode)
    }

    fn read_opcode(&mut self) -> Result<Opcode> {
        let position = self.position;
        if position.checked_add(1).is_none() {
            return Err(Error::PCTooLarge);
        }
        if position >= self.code.len() {
            return Err(Error::PCOverflow);
        }
        let opcode: Opcode = self.code[position].into();
        self.position += 1;
        Ok(opcode)
    }

    fn stop(&mut self) {
        self.stopped = true;
    }

    fn stopped(&self) -> bool {
        self.stopped || self.position >= self.code.len()
    }

    fn read(&mut self, byte_count: usize) -> Result<M256> {
        let position = self.position;
        if position.checked_add(byte_count).is_none() {
            return Err(Error::PCTooLarge);
        }
        self.position += byte_count;
        let max = min(position + byte_count, self.code.len());
        Ok(M256::from(&self.code[position..max]))
    }
}
<|endoftext|>


<commit_before>use std::fmt::{Debug, Error, Formatter};
use std::rc::Rc;

use super::super::ast::{Function as AstFunction, Node, Root};
use super::super::parser;
use super::builtins::build as build_builtins;
use super::frame::{Closure, Frame};
use super::value::Value;

struct InnerBuiltinFunction {
    name: String,
    call_target: fn(Vec<Value>) -> Value,
}

#[derive(Clone)]
pub struct BuiltinFunction(Rc<InnerBuiltinFunction>);

impl BuiltinFunction {
    pub fn new(name: String, call_target: fn(Vec<Value>) -> Value) -> Self {
        Self(Rc::new(InnerBuiltinFunction { name, call_target }))
    }

    pub fn call(&self, arguments: Vec<Value>) -> Value {
        let call_target = &self.0.call_target;
        call_target(arguments)
    }

    pub fn name(&self) -> String {
        self.0.name.clone()
    }
}

impl Debug for BuiltinFunction {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.write_str(&self.name())
    }
}

#[derive(Clone)]
pub struct Function {
    /// The closure in which this function was defined.
    closure: Option<Closure>,
    /// The AST node defining this function.
    node: AstFunction,
}

impl Function {
    fn new(closure: Option<Closure>, root: AstFunction) -> Self {
        Self {
            closure,
            node: root,
        }
    }

    pub fn build_closure(&self) -> Option<Closure> {
        // If the function has its own bindings (used by child function(s)) or
        // if it uses bindings from its parent then we need to set up a closure
        // for it.
        let needs_closure = self.node.has_bindings() || self.node.has_parent_bindings();
        if needs_closure {
            let bindings = self.node.get_bindings();
            let parent = self.closure.clone();
            Some(Closure::new(bindings, parent))
        } else {
            None
        }
    }
}

impl Debug for Function {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.write_str("function")
    }
}

struct Module {
    source: String,
    root: Root,
    closure: Closure,
}

impl Module {
    fn new_from_source(source: String, builtins: Option<Closure>) -> Self {
        let root = parser::parse(&source);

        // NOTE: Parent bindings should only be imports or builtins. Anything
        //   else is probably use of undefined variables.
        if let Some(parent_bindings) = &root.parent_bindings {
            for binding in parent_bindings.iter() {
                if !builtins
                    .as_ref()
                    .map(|closure| closure.has(binding.clone()))
                    .unwrap_or(false)
                {
                    panic!("Dangling root parent binding: {}", binding);
                }
            }
        }
        let closure = Closure::new(root.bindings.clone(), builtins);

        Self {
            source,
            root,
            closure,
        }
    }
}

#[derive(Debug)]
enum Action {
    // Regular implicit return of evaluating a statement or expression.
    Value(Value),
    // "Interrupt" to return a value from a function.
    Return(Option<Value>),
}

trait Eval {
    fn eval(&self, frame: &mut Frame) -> Action;
}

impl Eval for Module {
    fn eval(&self, frame: &mut Frame) -> Action {
        for node in self.root.nodes.iter() {
            node.eval(frame);
        }
        Action::Value(Value::Null)
    }
}

impl Eval for Node {
    fn eval(&self, frame: &mut Frame) -> Action {
        // Utility macro to get the value or early-return if it's a
        // `Return` action.
        macro_rules! value {
            ($x:expr) => {{
                match $x {
                    Action::Value(val) => val,
                    ret @ Action::Return(_) => return ret,
                }
            }};
        }

        let value: Value = match self {
            Node::Block(block) => {
                if let Some((last_node, nodes)) = block.nodes.split_last() {
                    for node in nodes {
                        value!(node.eval(frame));
                    }
                    value!(last_node.eval(frame))
                } else {
                    Value::Null
                }
            }
            Node::Function(ast_function) => {
                let function = Function::new(frame.get_closure(), ast_function.clone());
                let value = Value::Function(function);
                if let Some(name) = &ast_function.name {
                    frame.set(name.clone(), value.clone())
                }
                value
            }
            Node::Identifier(identifier) => {
                let name = identifier.value.clone();
                frame
                    .get(name.clone())
                    .expect(&format!("Not found: {}", name))
            }
            Node::Integer(integer) => Value::Integer(integer.value),
            Node::Let(let_) => {
                let rhs = match &let_.rhs {
                    Some(rhs) => value!(rhs.eval(frame)),
                    None => Value::Null,
                };
                let lhs: String = let_.lhs.value.clone();
                frame.set(lhs, rhs);
                Value::Null
            }
            Node::PostfixCall(call) => {
                let target = value!(call.target.eval(frame));
                let mut arguments = Vec::<Value>::with_capacity(call.arguments.len());
                for argument in call.arguments.iter() {
                    let value = value!(argument.eval(frame));
                    arguments.push(value)
                }
                assert_eq!(arguments.len(), call.arguments.len(),);
                eval_function(target, arguments)
            }
            Node::Return(ret) => {
                if let Some(rhs) = &ret.rhs {
                    let value = value!(rhs.eval(frame));
                    return Action::Return(Some(value));
                } else {
                    return Action::Return(None);
                }
            }
            Node::Var(var) => {
                let rhs = match &var.rhs {
                    Some(rhs) => value!(rhs.eval(frame)),
                    None => Value::Null,
                };
                let lhs: String = var.lhs.value.clone();
                frame.set(lhs, rhs);
                Value::Null
            }
            other @ _ => unreachable!("Cannot eval: {}", other),
        };
        Action::Value(value)
    }
}

fn eval_function(target: Value, arguments: Vec<Value>) -> Value {
    match target {
        Value::BuiltinFunction(builtin_function) => builtin_function.call(arguments),
        Value::Function(function) => {
            let mut frame = Frame::new_for_function(&function);
            match function.node.body.eval(&mut frame) {
                // Implicit return.
                Action::Value(value) => value,
                // Explicit return.
                Action::Return(value) => value.unwrap_or(Value::Null),
            }
        }
        other @ _ => unreachable!("Cannot call: {:?}", other),
    }
}

pub struct Vm {
    builtins: Option<Closure>,
}

impl Vm {
    pub fn new() -> Self {
        Self {
            builtins: Some(build_builtins()),
        }
    }

    pub fn eval_source(&self, source: String) {
        let module = Module::new_from_source(source, self.builtins.clone());
        let mut frame = Frame::new_with_closure(module.closure.clone());
        module.eval(&mut frame);
    }
}
<commit_msg>Implement rudimentary assignment<commit_after>use std::fmt::{Debug, Error, Formatter};
use std::rc::Rc;

use super::super::ast::{Function as AstFunction, Node, Root};
use super::super::parser;
use super::builtins::build as build_builtins;
use super::frame::{Closure, Frame};
use super::value::Value;

struct InnerBuiltinFunction {
    name: String,
    call_target: fn(Vec<Value>) -> Value,
}

#[derive(Clone)]
pub struct BuiltinFunction(Rc<InnerBuiltinFunction>);

impl BuiltinFunction {
    pub fn new(name: String, call_target: fn(Vec<Value>) -> Value) -> Self {
        Self(Rc::new(InnerBuiltinFunction { name, call_target }))
    }

    pub fn call(&self, arguments: Vec<Value>) -> Value {
        let call_target = &self.0.call_target;
        call_target(arguments)
    }

    pub fn name(&self) -> String {
        self.0.name.clone()
    }
}

impl Debug for BuiltinFunction {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.write_str(&self.name())
    }
}

#[derive(Clone)]
pub struct Function {
    /// The closure in which this function was defined.
    closure: Option<Closure>,
    /// The AST node defining this function.
    node: AstFunction,
}

impl Function {
    fn new(closure: Option<Closure>, root: AstFunction) -> Self {
        Self {
            closure,
            node: root,
        }
    }

    pub fn build_closure(&self) -> Option<Closure> {
        // If the function has its own bindings (used by child function(s)) or
        // if it uses bindings from its parent then we need to set up a closure
        // for it.
        let needs_closure = self.node.has_bindings() || self.node.has_parent_bindings();
        if needs_closure {
            let bindings = self.node.get_bindings();
            let parent = self.closure.clone();
            Some(Closure::new(bindings, parent))
        } else {
            None
        }
    }
}

impl Debug for Function {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.write_str("function")
    }
}

struct Module {
    source: String,
    root: Root,
    closure: Closure,
}

impl Module {
    fn new_from_source(source: String, builtins: Option<Closure>) -> Self {
        let root = parser::parse(&source);

        // NOTE: Parent bindings should only be imports or builtins. Anything
        //   else is probably use of undefined variables.
        if let Some(parent_bindings) = &root.parent_bindings {
            for binding in parent_bindings.iter() {
                if !builtins
                    .as_ref()
                    .map(|closure| closure.has(binding.clone()))
                    .unwrap_or(false)
                {
                    panic!("Dangling root parent binding: {}", binding);
                }
            }
        }
        let closure = Closure::new(root.bindings.clone(), builtins);

        Self {
            source,
            root,
            closure,
        }
    }
}

#[derive(Debug)]
enum Action {
    // Regular implicit return of evaluating a statement or expression.
    Value(Value),
    // "Interrupt" to return a value from a function.
    Return(Option<Value>),
}

trait Eval {
    fn eval(&self, frame: &mut Frame) -> Action;
}

impl Eval for Module {
    fn eval(&self, frame: &mut Frame) -> Action {
        for node in self.root.nodes.iter() {
            node.eval(frame);
        }
        Action::Value(Value::Null)
    }
}

impl Eval for Node {
    fn eval(&self, frame: &mut Frame) -> Action {
        // Utility macro to get the value or early-return if it's a
        // `Return` action.
        macro_rules! value {
            ($x:expr) => {{
                match $x {
                    Action::Value(val) => val,
                    ret @ Action::Return(_) => return ret,
                }
            }};
        }

        let value: Value = match self {
            Node::Assignment(assignment) => {
                let rhs = value!(assignment.rhs.eval(frame));
                match assignment.lhs.as_ref() {
                    Node::Identifier(identifier) => {
                        frame.set(identifier.value.clone(), rhs.clone());
                    }
                    other @ _ => {
                        unreachable!("Cannot assign to: {}", other)
                    }
                }
                rhs
            }
            Node::Block(block) => {
                if let Some((last_node, nodes)) = block.nodes.split_last() {
                    for node in nodes {
                        value!(node.eval(frame));
                    }
                    value!(last_node.eval(frame))
                } else {
                    Value::Null
                }
            }
            Node::Function(ast_function) => {
                let function = Function::new(frame.get_closure(), ast_function.clone());
                let value = Value::Function(function);
                if let Some(name) = &ast_function.name {
                    frame.set(name.clone(), value.clone())
                }
                value
            }
            Node::Identifier(identifier) => {
                let name = identifier.value.clone();
                frame
                    .get(name.clone())
                    .expect(&format!("Not found: {}", name))
            }
            Node::Integer(integer) => Value::Integer(integer.value),
            Node::Let(let_) => {
                let rhs = match &let_.rhs {
                    Some(rhs) => value!(rhs.eval(frame)),
                    None => Value::Null,
                };
                let lhs: String = let_.lhs.value.clone();
                frame.set(lhs, rhs);
                Value::Null
            }
            Node::PostfixCall(call) => {
                let target = value!(call.target.eval(frame));
                let mut arguments = Vec::<Value>::with_capacity(call.arguments.len());
                for argument in call.arguments.iter() {
                    let value = value!(argument.eval(frame));
                    arguments.push(value)
                }
                assert_eq!(arguments.len(), call.arguments.len(),);
                eval_function(target, arguments)
            }
            Node::Return(ret) => {
                if let Some(rhs) = &ret.rhs {
                    let value = value!(rhs.eval(frame));
                    return Action::Return(Some(value));
                } else {
                    return Action::Return(None);
                }
            }
            Node::Var(var) => {
                let rhs = match &var.rhs {
                    Some(rhs) => value!(rhs.eval(frame)),
                    None => Value::Null,
                };
                let lhs: String = var.lhs.value.clone();
                frame.set(lhs, rhs);
                Value::Null
            }
            other @ _ => unreachable!("Cannot eval: {}", other),
        };
        Action::Value(value)
    }
}

fn eval_function(target: Value, arguments: Vec<Value>) -> Value {
    match target {
        Value::BuiltinFunction(builtin_function) => builtin_function.call(arguments),
        Value::Function(function) => {
            let mut frame = Frame::new_for_function(&function);
            match function.node.body.eval(&mut frame) {
                // Implicit return.
                Action::Value(value) => value,
                // Explicit return.
                Action::Return(value) => value.unwrap_or(Value::Null),
            }
        }
        other @ _ => unreachable!("Cannot call: {:?}", other),
    }
}

pub struct Vm {
    builtins: Option<Closure>,
}

impl Vm {
    pub fn new() -> Self {
        Self {
            builtins: Some(build_builtins()),
        }
    }

    pub fn eval_source(&self, source: String) {
        let module = Module::new_from_source(source, self.builtins.clone());
        let mut frame = Frame::new_with_closure(module.closure.clone());
        module.eval(&mut frame);
    }
}
<|endoftext|>


<commit_before>extern crate stemmer;
extern crate unicode_normalization;
extern crate unicode_segmentation;

use std::iter::Peekable;

use self::stemmer::Stemmer;
use self::unicode_normalization::UnicodeNormalization;
use self::unicode_segmentation::UnicodeSegmentation;

pub struct Stems<'a> {
    words: Peekable<unicode_segmentation::UWordBoundIndices<'a>>,
    stemmer: Stemmer,
    word_position: usize,
}

#[derive(Debug, PartialEq)]
pub struct StemmedWord {
    // Where the stemmed word starts
    pub word_pos: u32,
    // The stemmed word
    pub stemmed: String,
}

impl<'a> Stems<'a> {
    pub fn new(text: &str) -> Stems {
        Stems{
            words: text.split_word_bound_indices().peekable(),
            stemmer: Stemmer::new("english").unwrap(),
            word_position: 0,
        }
    }
}

impl<'a> Iterator for Stems<'a> {
    type Item = StemmedWord;

    fn next(&mut self) -> Option<StemmedWord> {
        let mut word_to_stem = String::new();
        let mut normalized = String::new();
        loop {
            match self.words.peek() {
                Some(&(_pos, word)) => {
                    normalized = word.nfkc().collect::<String>();
                    if word.chars().next().unwrap().is_alphabetic() {
                        break;
                    } else {
                        word_to_stem.push_str(&normalized);
                        self.words.next();
                    }
                },
                None => {
                    if word_to_stem.is_empty() {
                        if self.word_position == 0 {
                            self.word_position = 1;
                            // in this case we were passed an empty string
                            // so we don't just return None, but we return
                            // an empty string Stemmed word.
                            // otherwise searching fields with empty strings
                            // wouldn't be possible.
                            return Some(StemmedWord {
                                word_pos: 0,
                                stemmed: String::new(),
                            });
                        } else {
                            return None;
                        }
                    } else {
                        break;
                    }
                },
            }
        }

        if !word_to_stem.is_empty() {
            // we found the begining of the string is not a stemmable word.
            // Return the accumulated string as the stemmed word
            debug_assert!(self.word_position == 0);
            self.word_position += 1;
            return Some(StemmedWord {
                            word_pos: 0,
                            stemmed: word_to_stem,
                });
        }
        // normalized contains our stemmable word. advance the iter since we only peeked.
        self.words.next();
        word_to_stem = normalized;
        loop {
            // loop through all non-alphabetic chars and add to suffix
            match self.words.peek() {
                Some(&(_pos, word)) => {
                    normalized = word.nfkc().collect::<String>();
                    if normalized.chars().next().unwrap().is_alphabetic() {
                        break;
                    } else {
                        self.words.next();
                    }
                },
                None => break,
            }
        }
        let stemmed = self.stemmer.stem(&word_to_stem.to_lowercase());
        let ret = StemmedWord {
                    word_pos: self.word_position as u32,
                    stemmed: stemmed,
                 };
        self.word_position += 1;
        Some(ret)
    }
}

#[cfg(test)]
mod tests {
    use super::{StemmedWord, Stems};

    #[test]
    fn test_stems_mixedcase() {
        let input = "THEse Words deeplY test smOOthly that stemmING";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![
            StemmedWord { word_pos: 0, stemmed: String::from("these")},
            StemmedWord { word_pos: 1, stemmed: String::from("word")},
            // "deeply" stems to "deepli"
            StemmedWord { word_pos: 2, stemmed: String::from("deepli")},
            StemmedWord { word_pos: 3, stemmed: String::from("test")},
            StemmedWord { word_pos: 4, stemmed: String::from("smooth")},
            StemmedWord { word_pos: 5, stemmed: String::from("that")},
            StemmedWord { word_pos: 6, stemmed: String::from("stem")},
            ];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }

    #[test]
    fn test_stems_nonchars() {
        let input = "  @#$!== \t+-";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        assert_eq!(result, vec![StemmedWord { word_pos: 0, stemmed: String::from("  @#$!== \t+-")}]);
    }

    #[test]
    fn test_stems_some_nonchars() {
        let input = "@!?   Let's seeing...";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![
            StemmedWord { word_pos: 0, stemmed: String::from("@!?   ")},
            StemmedWord { word_pos: 1, stemmed: String::from("let")},
            StemmedWord { word_pos: 2, stemmed: String::from("see")},
            ];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }

    #[test]
    fn test_stems_unicode() {
        let input = "Ünicöde stemming";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![
            StemmedWord { word_pos: 0, stemmed: String::from("ünicöd")},
            StemmedWord { word_pos: 1, stemmed: String::from("stem")},
            ];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }

    #[test]
    fn test_stems_unicode_lowercase_has_more_bytes() {
        let input = "İ";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![StemmedWord { word_pos: 0, stemmed: String::from("i̇")}];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }

    // Some characters don't have a corresponding uppercase chararacter with the same byte size,
    // but when those uppercase letters are transformed to lowercase, they are transformed to the
    // same number of bytes combining several characters (although there is a single character for
    // it).
    // Here's an example in Python:
    //
    //     >>> u"Ρ̓".lower() == u"ῤ"
    //     False
    //     >>> u"Ρ̓".lower() == u"ῤ".lower()
    //     False
    //     >>> u"Ρ̓".lower() == u"ῤ".upper().lower()
    //     True
    // Or Rust:
    //
    //    let upper = "Ρ̓";
    //    let lower = "ῤ";
    //    println!("lower({}) == {}: {}", upper, lower, upper.to_lowercase() == lower);
    //    println!("lower({}) == lower(upper({})): {}", upper, lower, upper.to_lowercase() == lower.to_uppercase().to_lowercase());
    //    lower(Ρ̓) == ῤ: false
    //    lower(Ρ̓) == lower(upper(ῤ)): true
    #[test]
    fn test_stems_unicode_lowercase_has_less_bytes() {
        // The input is: Ρ̓ῤῤ (11 bytes), lowercases is ῤῤῤ (9 bytes)
        let input = "\u{03A1}\u{0313}\u{03C1}\u{0313}\u{1FE4}";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![
            StemmedWord { word_pos: 0, stemmed: String::from("\u{03C1}\u{0313}\u{1FE4}\u{1FE4}")},
           ];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }
}
<commit_msg>Fixed bug where trailing unnormalized text causes panic<commit_after>extern crate stemmer;
extern crate unicode_normalization;
extern crate unicode_segmentation;

use std::iter::Peekable;

use self::stemmer::Stemmer;
use self::unicode_normalization::UnicodeNormalization;
use self::unicode_segmentation::UnicodeSegmentation;

pub struct Stems<'a> {
    words: Peekable<unicode_segmentation::UWordBoundIndices<'a>>,
    stemmer: Stemmer,
    word_position: usize,
}

#[derive(Debug, PartialEq)]
pub struct StemmedWord {
    // Where the stemmed word starts
    pub word_pos: u32,
    // The stemmed word
    pub stemmed: String,
}

impl<'a> Stems<'a> {
    pub fn new(text: &str) -> Stems {
        Stems{
            words: text.split_word_bound_indices().peekable(),
            stemmer: Stemmer::new("english").unwrap(),
            word_position: 0,
        }
    }
}

impl<'a> Iterator for Stems<'a> {
    type Item = StemmedWord;

    fn next(&mut self) -> Option<StemmedWord> {
        // first we loop though until we find alphabetic chars. That becomes our stem word.
        let mut word_to_stem = String::new(); // will contain any leading non-alphabetic chars
                                              // iff no other alphabetic chars

        let mut normalized = String::new(); // will contain the first alphabetic chars
        loop {
            match self.words.peek() {
                Some(&(_pos, word)) => {
                    normalized = word.nfkc().collect::<String>();
                    if normalized.chars().next().unwrap().is_alphabetic() {
                        break;
                    } else {
                        word_to_stem.push_str(&normalized);
                        self.words.next();
                    }
                },
                None => {
                    if word_to_stem.is_empty() {
                        if self.word_position == 0 {
                            self.word_position = 1;
                            // in this case we were passed an empty string
                            // so we don't just return None, but we return
                            // an empty string Stemmed word.
                            // otherwise searching fields for empty strings
                            // wouldn't be possible.
                            return Some(StemmedWord {
                                word_pos: 0,
                                stemmed: String::new(),
                            });
                        } else {
                            return None;
                        }
                    } else {
                        break;
                    }
                },
            }
        }

        if !word_to_stem.is_empty() {
            // we found the string is not a stemmable word.
            // Return the accumulated string as the stemmed word
            debug_assert!(self.word_position == 0);

            self.word_position += 1;
            return Some(StemmedWord {
                            word_pos: 0,
                            stemmed: word_to_stem,
                });
        }
        // normalized contains our stemmable word. advance the iter since we only peeked.
        self.words.next();
        word_to_stem = normalized;
        loop {
            // loop through all non-alphabetic chars discarding them.
            match self.words.peek() { // peek to avoid advancing iter
                Some(&(_pos, word)) => {
                    normalized = word.nfkc().collect::<String>();
                    if normalized.chars().next().unwrap().is_alphabetic() {
                        break; // now we'll get these on the next() call
                    } else {
                        self.words.next(); //advance the iter
                    }
                },
                None => break,
            }
        }
        let stemmed = self.stemmer.stem(&word_to_stem.to_lowercase());
        let ret = StemmedWord {
                    word_pos: self.word_position as u32,
                    stemmed: stemmed,
                 };
        self.word_position += 1;
        Some(ret)
    }
}

#[cfg(test)]
mod tests {
    use super::{StemmedWord, Stems};

    #[test]
    fn test_stems_mixedcase() {
        let input = "THEse Words deeplY test smOOthly that stemmING";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![
            StemmedWord { word_pos: 0, stemmed: String::from("these")},
            StemmedWord { word_pos: 1, stemmed: String::from("word")},
            // "deeply" stems to "deepli"
            StemmedWord { word_pos: 2, stemmed: String::from("deepli")},
            StemmedWord { word_pos: 3, stemmed: String::from("test")},
            StemmedWord { word_pos: 4, stemmed: String::from("smooth")},
            StemmedWord { word_pos: 5, stemmed: String::from("that")},
            StemmedWord { word_pos: 6, stemmed: String::from("stem")},
            ];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }

    #[test]
    fn test_stems_nonchars() {
        let input = "  @#$!== \t+-";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        assert_eq!(result, vec![StemmedWord { word_pos: 0, stemmed: String::from("  @#$!== \t+-")}]);
    }

    #[test]
    fn test_stems_some_nonchars() {
        let input = "@!?   Let's seeing...";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![
            StemmedWord { word_pos: 0, stemmed: String::from("@!?   ")},
            StemmedWord { word_pos: 1, stemmed: String::from("let")},
            StemmedWord { word_pos: 2, stemmed: String::from("see")},
            ];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }

    #[test]
    fn test_stems_unicode() {
        let input = "Ünicöde stemming";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![
            StemmedWord { word_pos: 0, stemmed: String::from("ünicöd")},
            StemmedWord { word_pos: 1, stemmed: String::from("stem")},
            ];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }

    #[test]
    fn test_stems_trailing_needs_normalized() {
        let input = r#"Didgeridoos™"#;
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![
            StemmedWord { word_pos: 0, stemmed: String::from("didgeridoo")},
            StemmedWord { word_pos: 1, stemmed: String::from("tm")},
            ];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }

    #[test]
    fn test_stems_unicode_lowercase_has_more_bytes() {
        let input = "İ";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![StemmedWord { word_pos: 0, stemmed: String::from("i̇")}];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }

    // Some characters don't have a corresponding uppercase chararacter with the same byte size,
    // but when those uppercase letters are transformed to lowercase, they are transformed to the
    // same number of bytes combining several characters (although there is a single character for
    // it).
    // Here's an example in Python:
    //
    //     >>> u"Ρ̓".lower() == u"ῤ"
    //     False
    //     >>> u"Ρ̓".lower() == u"ῤ".lower()
    //     False
    //     >>> u"Ρ̓".lower() == u"ῤ".upper().lower()
    //     True
    // Or Rust:
    //
    //    let upper = "Ρ̓";
    //    let lower = "ῤ";
    //    println!("lower({}) == {}: {}", upper, lower, upper.to_lowercase() == lower);
    //    println!("lower({}) == lower(upper({})): {}", upper, lower, upper.to_lowercase() == lower.to_uppercase().to_lowercase());
    //    lower(Ρ̓) == ῤ: false
    //    lower(Ρ̓) == lower(upper(ῤ)): true
    #[test]
    fn test_stems_unicode_lowercase_has_less_bytes() {
        // The input is: Ρ̓ῤῤ (11 bytes), lowercases is ῤῤῤ (9 bytes)
        let input = "\u{03A1}\u{0313}\u{03C1}\u{0313}\u{1FE4}";
        let result = Stems::new(input).collect::<Vec<StemmedWord>>();
        let expected = vec![
            StemmedWord { word_pos: 0, stemmed: String::from("\u{03C1}\u{0313}\u{1FE4}\u{1FE4}")},
           ];
        assert_eq!(result.len(), expected.len());
        for (stem, expected_stem) in result.iter().zip(expected.iter()) {
            assert_eq!(stem, expected_stem);
        }
    }
}
<|endoftext|>


<commit_before>use rusqlite::{params, Connection};
use std::collections::HashMap;
use std::path::Path;
use std::result::Result as Result_;
use thiserror::Error;

pub type Result<T, E = StoreError> = Result_<T, E>;

#[derive(Error, Debug)]
pub enum StoreError {
    #[error("database error")]
    Sqlite(#[from] rusqlite::Error),

    #[error("could not de/serialize object")]
    Serialization(#[from] serde_json::Error),
}

trait AsStoreResult<T> {
    fn as_store_result(self) -> Result<T>;
}

impl<T, E> AsStoreResult<T> for Result_<T, E>
where
    E: Into<StoreError>,
{
    fn as_store_result(self) -> Result<T> {
        self.map_err(|e| e.into())
    }
}

pub type Object = HashMap<String, serde_json::Value>;

pub struct Store {
    conn: Connection,
}

impl Store {
    pub fn open(path: impl AsRef<Path>) -> Result<Store> {
        let mut store = Store {
            conn: Connection::open(path)?,
        };

        // Make SQLite use a write-ahead instead of a delete-based journal; see
        // [the SQLite documentation](https://www.sqlite.org/wal.html) for more info.
        store.conn.pragma_update(None, "journal_mode", &"WAL")?;

        // Check that the JSON1 extension is working.
        store
            .conn
            .prepare("SELECT json(\"{}\")")?
            .query(params![])
            // Explicitly ignore the value.
            .map(|_| {})?;

        store.upgrade_if_needed()?;

        Ok(store)
    }

    fn upgrade_if_needed(&mut self) -> Result<()> {
        // We check the version of the database and upgrade it if necessary.
        // Conveniently, this starts at 0 in an empty database.
        let version = self
            .conn
            .prepare("SELECT user_version from pragma_user_version")?
            .query_row(params![], |row| row.get::<usize, i64>(0))? as usize;

        // We use `AUTOINCREMENT` on the objects table so that IDs are not reused.
        let updates = [
            "
                        CREATE TABLE objects (
                                object_id INTEGER PRIMARY KEY AUTOINCREMENT,
                                properties TEXT
                        );
                ",
            "
                        CREATE TABLE object_changes (
                                serial INTEGER PRIMARY KEY,
                                timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                                object_id INTEGER,
                                action TEXT,
                                previous TEXT
                        );
                        CREATE TABLE checkpoints (
                                checkpoint_id INTEGER PRIMARY KEY,
                                timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                                serial INTEGER
                        );
                ",
        ];

        // We set the `user_version` after each update to ensure updates are not applied twice if one
        // in a sequence of updates fails.
        for (version, update) in updates.iter().enumerate().skip(version) {
            self.conn.execute_batch(update)?;
            self.conn
                .pragma_update(None, "user_version", &(version as i64))?;
        }

        Ok(())
    }

    pub fn all(&self) -> Collection {
        Collection { conn: &self.conn }
    }

    pub fn add(&mut self, object: Object) -> Result<()> {
        let object_serialized = serde_json::to_string(&object)?;

        self.conn
            .prepare("INSERT INTO objects(properties) VALUES(?)")?
            .execute(params![object_serialized])?;

        Ok(())
    }
}

pub struct Collection<'a> {
    conn: &'a Connection,
}

impl<'a> Collection<'a> {
    pub fn len(&self) -> Result<usize> {
        Ok(self
            .conn
            .prepare("SELECT COUNT(*) FROM objects")?
            // This workaround can be removed when https://github.com/rusqlite/rusqlite/issues/700
            // is closed
            .query_row(params![], |row| row.get::<usize, i64>(0))? as usize)
    }

    pub fn iter(&self) -> Result<impl Iterator<Item = Object> + 'a> {
        Ok(self
            .conn
            .prepare("SELECT properties FROM objects")?
            .query_and_then(params![], |row| row.get::<usize, String>(0))?
            .map(|r| {
                r.as_store_result().and_then(|serialized_object| {
                    serde_json::from_str(&serialized_object).as_store_result()
                })
            })
            .collect::<Result<Vec<Object>>>()?
            .into_iter())
    }
}

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

    fn open_store(tempdir: &TempDir, name: &str) -> Store {
        Store::open(tempdir.path().join(name)).unwrap()
    }

    fn test_dir() -> TempDir {
        TempDir::new("qualia-store").unwrap()
    }

    fn mkobject<'a>(proplist: &'a [(&'a str, &'a str)]) -> Object {
        proplist
            .iter()
            .cloned()
            .map(|(k, v)| (k.to_string(), serde_json::Value::String(v.to_string())))
            .collect()
    }

    fn sort_objects(objects: &mut Vec<Object>) {
        objects.sort_by_key(|o| {
            o.get("name")
                .and_then(|v| Some(v.as_str().unwrap_or("")))
                .unwrap_or("")
                .to_string()
        })
    }

    #[test]
    fn new_store_is_empty() {
        assert_eq!(
            open_store(&test_dir(), "store.qualia").all().len().unwrap(),
            0
        );
    }

    #[test]
    fn added_objects_can_be_found() {
        let test_dir = test_dir();
        let mut store = open_store(&test_dir, "store.qualia");

        store.add(mkobject(&[("name", "b"), ("c", "d")])).unwrap();
        store.add(mkobject(&[("name", "d"), ("c", "f")])).unwrap();
        store.add(mkobject(&[("name", "c"), ("c", "e")])).unwrap();

        let all = store.all();

        assert_eq!(all.len().unwrap(), 3);
        let mut all_objects = all.iter().unwrap().collect::<Vec<Object>>();
        sort_objects(&mut all_objects);
        assert_eq!(
            all_objects,
            vec![
                mkobject(&[("name", "b"), ("c", "d")]),
                mkobject(&[("name", "c"), ("c", "e")]),
                mkobject(&[("name", "d"), ("c", "f")])
            ],
        );
    }
}
<commit_msg>Fix indentation of database updates<commit_after>use rusqlite::{params, Connection};
use std::collections::HashMap;
use std::path::Path;
use std::result::Result as Result_;
use thiserror::Error;

pub type Result<T, E = StoreError> = Result_<T, E>;

#[derive(Error, Debug)]
pub enum StoreError {
    #[error("database error")]
    Sqlite(#[from] rusqlite::Error),

    #[error("could not de/serialize object")]
    Serialization(#[from] serde_json::Error),
}

trait AsStoreResult<T> {
    fn as_store_result(self) -> Result<T>;
}

impl<T, E> AsStoreResult<T> for Result_<T, E>
where
    E: Into<StoreError>,
{
    fn as_store_result(self) -> Result<T> {
        self.map_err(|e| e.into())
    }
}

pub type Object = HashMap<String, serde_json::Value>;

pub struct Store {
    conn: Connection,
}

impl Store {
    pub fn open(path: impl AsRef<Path>) -> Result<Store> {
        let mut store = Store {
            conn: Connection::open(path)?,
        };

        // Make SQLite use a write-ahead instead of a delete-based journal; see
        // [the SQLite documentation](https://www.sqlite.org/wal.html) for more info.
        store.conn.pragma_update(None, "journal_mode", &"WAL")?;

        // Check that the JSON1 extension is working.
        store
            .conn
            .prepare("SELECT json(\"{}\")")?
            .query(params![])
            // Explicitly ignore the value.
            .map(|_| {})?;

        store.upgrade_if_needed()?;

        Ok(store)
    }

    fn upgrade_if_needed(&mut self) -> Result<()> {
        // We check the version of the database and upgrade it if necessary.
        // Conveniently, this starts at 0 in an empty database.
        let version = self
            .conn
            .prepare("SELECT user_version from pragma_user_version")?
            .query_row(params![], |row| row.get::<usize, i64>(0))? as usize;

        // We use `AUTOINCREMENT` on the objects table so that IDs are not reused.
        let updates = [
            "
                CREATE TABLE objects (
                    object_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    properties TEXT
                );
            ",
            "
                CREATE TABLE object_changes (
                    serial INTEGER PRIMARY KEY,
                    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    object_id INTEGER,
                    action TEXT,
                    previous TEXT
                );
                CREATE TABLE checkpoints (
                    checkpoint_id INTEGER PRIMARY KEY,
                    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    serial INTEGER
                );
            ",
        ];

        // We set the `user_version` after each update to ensure updates are not applied twice if one
        // in a sequence of updates fails.
        for (version, update) in updates.iter().enumerate().skip(version) {
            self.conn.execute_batch(update)?;
            self.conn
                .pragma_update(None, "user_version", &(version as i64))?;
        }

        Ok(())
    }

    pub fn all(&self) -> Collection {
        Collection { conn: &self.conn }
    }

    pub fn add(&mut self, object: Object) -> Result<()> {
        let object_serialized = serde_json::to_string(&object)?;

        self.conn
            .prepare("INSERT INTO objects(properties) VALUES(?)")?
            .execute(params![object_serialized])?;

        Ok(())
    }
}

pub struct Collection<'a> {
    conn: &'a Connection,
}

impl<'a> Collection<'a> {
    pub fn len(&self) -> Result<usize> {
        Ok(self
            .conn
            .prepare("SELECT COUNT(*) FROM objects")?
            // This workaround can be removed when https://github.com/rusqlite/rusqlite/issues/700
            // is closed
            .query_row(params![], |row| row.get::<usize, i64>(0))? as usize)
    }

    pub fn iter(&self) -> Result<impl Iterator<Item = Object> + 'a> {
        Ok(self
            .conn
            .prepare("SELECT properties FROM objects")?
            .query_and_then(params![], |row| row.get::<usize, String>(0))?
            .map(|r| {
                r.as_store_result().and_then(|serialized_object| {
                    serde_json::from_str(&serialized_object).as_store_result()
                })
            })
            .collect::<Result<Vec<Object>>>()?
            .into_iter())
    }
}

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

    fn open_store(tempdir: &TempDir, name: &str) -> Store {
        Store::open(tempdir.path().join(name)).unwrap()
    }

    fn test_dir() -> TempDir {
        TempDir::new("qualia-store").unwrap()
    }

    fn mkobject<'a>(proplist: &'a [(&'a str, &'a str)]) -> Object {
        proplist
            .iter()
            .cloned()
            .map(|(k, v)| (k.to_string(), serde_json::Value::String(v.to_string())))
            .collect()
    }

    fn sort_objects(objects: &mut Vec<Object>) {
        objects.sort_by_key(|o| {
            o.get("name")
                .and_then(|v| Some(v.as_str().unwrap_or("")))
                .unwrap_or("")
                .to_string()
        })
    }

    #[test]
    fn new_store_is_empty() {
        assert_eq!(
            open_store(&test_dir(), "store.qualia").all().len().unwrap(),
            0
        );
    }

    #[test]
    fn added_objects_can_be_found() {
        let test_dir = test_dir();
        let mut store = open_store(&test_dir, "store.qualia");

        store.add(mkobject(&[("name", "b"), ("c", "d")])).unwrap();
        store.add(mkobject(&[("name", "d"), ("c", "f")])).unwrap();
        store.add(mkobject(&[("name", "c"), ("c", "e")])).unwrap();

        let all = store.all();

        assert_eq!(all.len().unwrap(), 3);
        let mut all_objects = all.iter().unwrap().collect::<Vec<Object>>();
        sort_objects(&mut all_objects);
        assert_eq!(
            all_objects,
            vec![
                mkobject(&[("name", "b"), ("c", "d")]),
                mkobject(&[("name", "c"), ("c", "e")]),
                mkobject(&[("name", "d"), ("c", "f")])
            ],
        );
    }
}
<|endoftext|>


<commit_before>use std::collections::Bound::Included;
use std::collections::BTreeMap;
use std::u64;

pub struct Store<'a> {
  max_offset: u64,
  data: Box<BTreeMap<&'a str, Box<BTreeMap<u64, &'a [u8]>>>>
}

impl<'a> Store<'a> {
  pub fn new<'b>() -> Store<'b> {
    Store {
      max_offset: 0,
      data: Box::new(BTreeMap::new()),
    }
  }

  pub fn add(&mut self, key: &'a str, value: &'a [u8]) {
    self.max_offset += 1;
    if self.data.get(&key).is_none() {
      if self.data.insert(key, Box::new(BTreeMap::new())).is_some() {
        panic!("Invariant violation; duplicate version tree detected");
      }
    }

    if self.data.get_mut(&key).unwrap().insert(self.max_offset, value).is_some() {
      panic!("Invariant violation; duplicate offset detected");
    }
  }

  pub fn get(&self, key: &'a str) -> Option<&'a [u8]> {
    self.data.get(&key).map( |version_tree| {
      let (_, v) = version_tree.range(Included(&0), Included(&u64::MAX)).last().unwrap();
      *v
    })
  }
}

#[test]
fn add_something() {
  let mut store = Store::new();
  store.add("yo", b"ok");
}

#[test]
fn get_something() {
  let mut store = Store::new();
  store.add("spaghetti", b"I'm");
  store.add("spaghetti", b"James");
  store.add("spaghetti", b"Quall");
  store.add("spaghetti", b"spaghetti");
  store.add("spaghetti", b"and");
  store.add("spaghetti", b"meatballs");
  assert!(store.get("spaghetti") == Some(b"meatballs"));
}
<commit_msg>WHATS IN THE BOX??!?!??<commit_after>use std::collections::Bound::Included;
use std::collections::BTreeMap;
use std::u64;

pub struct Store<'a> {
  max_offset: u64,
  data: BTreeMap<&'a str, BTreeMap<u64, &'a [u8]>>
}

impl<'a> Store<'a> {
  pub fn new<'b>() -> Store<'b> {
    Store {
      max_offset: 0,
      data: BTreeMap::new(),
    }
  }

  pub fn add(&mut self, key: &'a str, value: &'a [u8]) {
    self.max_offset += 1;
    if self.data.get(&key).is_none() {
      if self.data.insert(key, BTreeMap::new()).is_some() {
        panic!("Invariant violation; duplicate version tree detected");
      }
    }

    if self.data.get_mut(&key).unwrap().insert(self.max_offset, value).is_some() {
      panic!("Invariant violation; duplicate offset detected");
    }
  }

  pub fn get(&self, key: &'a str) -> Option<&'a [u8]> {
    self.data.get(&key).map( |version_tree| {
      let (_, v) = version_tree.range(Included(&0), Included(&u64::MAX)).last().unwrap();
      *v
    })
  }
}

#[test]
fn add_something() {
  let mut store = Store::new();
  store.add("yo", b"ok");
}

#[test]
fn get_something() {
  let mut store = Store::new();
  store.add("spaghetti", b"I'm");
  store.add("spaghetti", b"James");
  store.add("spaghetti", b"Quall");
  store.add("spaghetti", b"spaghetti");
  store.add("spaghetti", b"and");
  store.add("spaghetti", b"meatballs");
  assert!(store.get("spaghetti") == Some(b"meatballs"));
}
<|endoftext|>


<commit_before>use super::Checked;

// Test a unary operator
macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

// Test a binary operator
macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty, $v:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$v>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

// These tests use None to indicate over/underflow.
test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul1 u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
test_binop! (shl u8, u32: 10 << 3 == 80);
test_binop! (shr u8, u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));

#[test]
fn order() {
    assert!(Checked::from(1_000_u32) <= Checked::from(10_000_u32));
    assert!(!(Checked::from(1_000_u32) <= Checked::from(None)));
    assert!((Checked::from(None) <= Checked::from(1_000_u32)));
}
<commit_msg>add test for 'new' method<commit_after>use super::Checked;

// Test a unary operator
macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

// Test a binary operator
macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty, $v:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$v>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

// These tests use None to indicate over/underflow.
test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul1 u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
test_binop! (shl u8, u32: 10 << 3 == 80);
test_binop! (shr u8, u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));

#[test]
fn order() {
    assert!(Checked::from(1_000_u32) <= Checked::from(10_000_u32));
    assert!(!(Checked::from(1_000_u32) <= Checked::from(None)));
    assert!((Checked::from(None) <= Checked::from(1_000_u32)));
}

#[test]
fn new_checked() {
    assert_eq(Checked::new(100) == Checked(Some(100)))
}
<|endoftext|>