<commit_before>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! Provide basic definitions of terms.

use std::collections::BitVec;
//use std::tuple::Tuple1;

/// Represents root terms.
struct Root ( () );
struct Any ( () );
struct ENone ( () );
#[derive(Debug)]
struct EString( String ) ;
struct Symbol( String );
#[derive(Debug)]
struct Integer( isize );
struct Float( f64 );
struct BitString( BitVec );
struct Boolean( bool );

trait Termable<T>{
    fn new(value: T) -> Self;
    fn native(&self) -> &T;
}

impl Termable<String> for EString{
    fn new(value: String) -> EString{
        EString(value)
    }
    fn native(&self) -> &String {
        &self.0
    }
}

#[derive(Debug)]
struct Term<T> {
    value: T,
}

impl<T> Term<T>
{
    pub fn new<U>(t: U) -> Term<U> where U: Termable<T> {
        Term { value: t }
    }
    pub fn unwrap(&self) -> &T {
        &self.value
    }
}

#[test]
fn term_type_check_test() -> (){
    let termable = EString::new("Test".to_string());
    let stringterm = Term::new(termable);
   // let nestedterm = Term::new(Term::new(Integer(3)));
    let stringval = &stringterm.unwrap().native();
    panic!("Intentionial panic. {:?}", stringval);
}

<commit_msg>Expanded term test case<commit_after>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! Provide basic definitions of terms.

use std::collections::BitVec;
//use std::tuple::Tuple1;

/// Represents root terms.
struct Root ( () );
struct Any ( () );
struct ENone ( () );
#[derive(Debug)]
struct EString( String ) ;
struct Symbol( String );
#[derive(Debug)]
struct Integer( isize );
struct Float( f64 );
struct BitString( BitVec );
struct Boolean( bool );

trait Termable<T>{
    fn new(value: T) -> Self;
    fn native(&self) -> &T;
}

impl Termable<String> for EString{
    fn new(value: String) -> EString{
        EString(value)
    }
    fn native(&self) -> &String {
        &self.0
    }
}

impl Termable<isize> for Integer{
    fn new(value: isize) -> Integer{
        Integer(value)
    }
    fn native(&self) -> &isize {
        &self.0
    }
}

#[derive(Debug)]
struct Term<T> {
    value: T,
}

impl<T> Term<T>
{
    pub fn new<U>(t: U) -> Term<U> where U: Termable<T> {
        Term { value: t }
    }
    pub fn unwrap(&self) -> &T {
        &self.value
    }
}

#[test]
fn term_type_check_test() -> (){
    let termable = EString::new("Test".to_string());
    let mut stringterm = Term::new(termable);
    let integerterm = Term::new(Integer(3));
    // Uncomment the following line to see the type checker assist in action
    // stringterm = integerterm;

    //Nested terms don't work right now
    // let nestedterm = Term::new(Term::new(Integer(3)));
    let stringval = &stringterm.unwrap().native();
    panic!("Intentionial panic. {:?}", stringval);
}

<|endoftext|>


<commit_before><commit_msg>Fix lint about many short variable names<commit_after><|endoftext|>


<commit_before>use fool::BoolExt;
use std::borrow::Borrow;
use std::collections::{HashSet, VecDeque};

use crate::graph::edge::{Arc, ArcKey, ArcView};
use crate::graph::geometry::{Geometric, Geometry, GraphGeometry};
use crate::graph::mutation::Consistent;
use crate::graph::vertex::{Vertex, VertexKey, VertexView};
use crate::graph::{GraphError, OptionExt as _, Selector};
use crate::network::borrow::{Reborrow, ReborrowMut};
use crate::network::storage::{AsStorage, AsStorageMut};
use crate::network::view::{ClosedView, View};
use crate::IteratorExt as _;

/// View of a path in a graph.
///
/// Provides a representation of non-intersecting paths in a graph. A path is
/// conceptually an ordered set of vertices that are joined by arcs. Paths are
/// notated as either sequences or sets. An open path over vertices $A$, $B$,
/// and $C$ is notated $\overrightarrow{(A,B,C)}$ and a closed path over the
/// same vertices is notated $\overrightarrow{\\{A,B,C\\}}$.
///
/// `Path` represents paths of the form $\overrightarrow{(A,\cdots,B)}$, where
/// $A$ is the back of the path and $B$ is the front of the path. Note that
/// closed paths are always of the form $\overrightarrow{(A,\cdots,A)}$, where
/// the back and front vertices are both $A$ (the same).
#[derive(Clone)]
pub struct Path<B>
where
    B: Reborrow,
    B::Target:
        AsStorage<Arc<Geometry<B>>> + AsStorage<Vertex<Geometry<B>>> + Consistent + Geometric,
{
    keys: VecDeque<ArcKey>,
    storage: B,
}

impl<B, M, G> Path<B>
where
    B: Reborrow<Target = M>,
    M: AsStorage<Arc<G>> + AsStorage<Vertex<G>> + Consistent + Geometric<Geometry = G>,
    G: GraphGeometry,
{
    // Paths bind multiple keys to storage and so do not support `View`,
    // `Orphan`, nor `ClosedView`. This bespoke `bind` function ensures that the
    // path is not empty and that the topology forms a non-intersecting path.
    pub(in crate::graph) fn bind<I>(storage: B, keys: I) -> Result<Self, GraphError>
    where
        I: IntoIterator,
        I::Item: Borrow<VertexKey>,
    {
        let mut keys = keys.into_iter().map(|key| *key.borrow());
        let a = keys.next().ok_or_else(|| GraphError::TopologyMalformed)?;
        let b = keys.next().ok_or_else(|| GraphError::TopologyMalformed)?;
        let ab = (a, b).into();
        View::<_, Arc<G>>::bind(storage.reborrow(), ab)
            .ok_or_else(|| GraphError::TopologyNotFound)?;
        let mut path = Path {
            keys: (&[ab]).iter().cloned().collect(),
            storage,
        };
        for key in keys {
            path.push_front(Selector::ByKey(key))?;
        }
        Ok(path)
    }

    pub fn to_ref(&self) -> Path<&M> {
        let storage = self.storage.reborrow();
        let keys = self.keys.iter();
        Path::bind_unchecked(storage, keys)
    }

    /// Pushes a vertex onto the back of the path.
    ///
    /// The back of a path $\overrightarrow{(A,\cdots)}$ is the vertex $A$.
    /// This is the source vertex of the first arc that forms the path.
    ///
    /// The given vertex must be a source vertex of an arc formed with the the
    /// back of the path. That is, if the given vertex is $X$, then
    /// $\overrightarrow{XA}$ must exist.
    ///
    /// Returns the key of the arc $\overrightarrow{XA}$ inserted into the path
    /// using the given source vertex $X$.
    ///
    /// # Errors
    ///
    /// Returns an error if the path is closed, the given vertex is not found,
    /// or the given vertex does not form an arc with the back of the path.
    pub fn push_back(&mut self, destination: Selector<VertexKey>) -> Result<ArcKey, GraphError> {
        self.is_open()
            .ok_or_else(|| GraphError::TopologyMalformed)?;
        let back = self.back();
        let xa = match destination {
            Selector::ByKey(key) => back
                .incoming_arcs()
                .find(|arc| arc.into_source_vertex().key() == key)
                .ok_or_else(|| GraphError::TopologyMalformed)?
                .key(),
            Selector::ByIndex(index) => {
                let x = back
                    .neighboring_vertices()
                    .keys()
                    .nth(index)
                    .ok_or_else(|| GraphError::TopologyNotFound)?;
                (x, back.key()).into()
            }
        };
        let (x, _) = xa.into();
        // Do not allow intersections unless they form a loop with the first
        // vertex in the path (this iteration skips the vertex at the front of
        // the path).
        let is_intersecting = self
            .arcs()
            .map(|arc| arc.into_source_vertex())
            .keys()
            .any(|key| key == x);
        if is_intersecting {
            Err(GraphError::TopologyMalformed)
        }
        else {
            self.keys.push_back(xa);
            Ok(xa)
        }
    }

    /// Pops a vertex from the back of the path.
    pub fn pop_back(&mut self) -> Option<ArcKey> {
        // Empty paths are forbidden.
        if self.keys.len() > 1 {
            self.keys.pop_back()
        }
        else {
            None
        }
    }

    /// Pushes a vertex onto the front of the path.
    ///
    /// The front of a path $\overrightarrow{(\cdots,B)}$ is the vertex $B$.
    /// This is the destination vertex of the last arc that forms the path.
    ///
    /// The given vertex must be a destination vertex of an arc formed with the
    /// the front of the path. That is, if the given vertex is $X$, then
    /// $\overrightarrow{BX}$ must exist.
    ///
    /// Returns the key of the arc $\overrightarrow{BX}$ inserted into the path
    /// using the given source vertex $X$.
    ///
    /// # Errors
    ///
    /// Returns an error if the path is closed, the given vertex is not found,
    /// or the given vertex does not form an arc with the front of the path.
    pub fn push_front(&mut self, destination: Selector<VertexKey>) -> Result<ArcKey, GraphError> {
        self.is_open()
            .ok_or_else(|| GraphError::TopologyMalformed)?;
        let front = self.front();
        let bx = match destination {
            Selector::ByKey(key) => front
                .outgoing_arcs()
                .find(|arc| arc.into_destination_vertex().key() == key)
                .ok_or_else(|| GraphError::TopologyMalformed)?
                .key(),
            Selector::ByIndex(index) => {
                let x = front
                    .neighboring_vertices()
                    .keys()
                    .nth(index)
                    .ok_or_else(|| GraphError::TopologyNotFound)?;
                (front.key(), x).into()
            }
        };
        let (_, x) = bx.into();
        // Do not allow intersections unless they form a loop with the first
        // vertex in the path (this iteration skips the vertex at the back of
        // the path).
        let is_intersecting = self
            .arcs()
            .map(|arc| arc.into_destination_vertex())
            .keys()
            .any(|key| key == x);
        if is_intersecting {
            Err(GraphError::TopologyMalformed)
        }
        else {
            self.keys.push_front(bx);
            Ok(bx)
        }
    }

    /// Pops a vertex from the front of the path.
    pub fn pop_front(&mut self) -> Option<ArcKey> {
        // Empty paths are forbidden.
        if self.keys.len() > 1 {
            self.keys.pop_front()
        }
        else {
            None
        }
    }

    /// Gets the vertex at the back of the path.
    pub fn back(&self) -> VertexView<&M> {
        let (key, _) = self.endpoints();
        View::bind_into(self.storage.reborrow(), key).expect_consistent()
    }

    /// Gets the vertex at the front of the path.
    pub fn front(&self) -> VertexView<&M> {
        let (_, key) = self.endpoints();
        View::bind_into(self.storage.reborrow(), key).expect_consistent()
    }

    /// Gets an iterator over the vertices in the path.
    pub fn vertices<'a>(&'a self) -> impl Iterator<Item = VertexView<&'a M>>
    where
        M: 'a,
    {
        let back = self.back();
        Some(back)
            .into_iter()
            .chain(self.arcs().map(|arc| arc.into_destination_vertex()))
    }

    /// Gets an iterator over the arcs in the path.
    pub fn arcs<'a>(&'a self) -> impl ExactSizeIterator<Item = ArcView<&'a M>>
    where
        M: 'a,
    {
        let storage = self.storage.reborrow();
        self.keys
            .iter()
            .rev()
            .cloned()
            .map(move |key| View::bind_into(storage, key).expect_consistent())
    }

    /// Returns `true` if the path is open.
    ///
    /// An _open path_ is a path that terminates and does **not** form a loop.
    pub fn is_open(&self) -> bool {
        !self.is_closed()
    }

    /// Returns `true` if the path is closed.
    ///
    /// A _closed path_ is a path that forms a loop by starting and ending at
    /// the same vertex.
    pub fn is_closed(&self) -> bool {
        let (a, b) = self.endpoints();
        a == b
    }

    fn bind_unchecked<I>(storage: B, keys: I) -> Self
    where
        I: IntoIterator,
        I::Item: Borrow<ArcKey>,
    {
        let keys = keys.into_iter().map(|key| *key.borrow()).collect();
        Path { storage, keys }
    }

    fn endpoints(&self) -> (VertexKey, VertexKey) {
        let (a, _) = self.keys.back().cloned().expect("empty path").into();
        let (_, b) = self.keys.front().cloned().expect("empty pathy").into();
        (a, b)
    }
}

impl<B, M, G> Path<B>
where
    B: ReborrowMut<Target = M>,
    M: AsStorageMut<Arc<G>> + AsStorageMut<Vertex<G>> + Consistent + Geometric<Geometry = G>,
    G: GraphGeometry,
{
    pub fn to_mut(&mut self) -> Path<&mut M> {
        let storage = self.storage.reborrow_mut();
        let keys = self.keys.iter();
        Path::bind_unchecked(storage, keys)
    }
}

impl<'a, M, G> Path<&'a mut M>
where
    M: AsStorageMut<Arc<G>> + AsStorageMut<Vertex<G>> + Consistent + Geometric<Geometry = G>,
    G: GraphGeometry,
{
    /// Converts a mutable view into an immutable view.
    ///
    /// This is useful when mutations are not (or no longer) needed and mutual
    /// access is desired.
    pub fn into_ref(self) -> Path<&'a M> {
        let Path { keys, storage, .. } = self;
        Path {
            keys,
            storage: &*storage,
        }
    }
}

impl<B, M, G> PartialEq for Path<B>
where
    B: Reborrow<Target = M>,
    M: AsStorage<Arc<G>> + AsStorage<Vertex<G>> + Consistent + Geometric<Geometry = G>,
    G: GraphGeometry,
{
    fn eq(&self, other: &Self) -> bool {
        let keys = |path: &Self| path.arcs().keys().collect::<HashSet<_>>();
        keys(self) == keys(other)
    }
}

#[cfg(test)]
mod tests {
    use nalgebra::Point2;

    use crate::buffer::FromRawBuffers;
    use crate::graph::{ClosedView, MeshGraph, Selector};
    use crate::primitive::Trigon;
    use crate::IteratorExt;

    use Selector::ByKey;

    type E2 = Point2<f64>;

    #[test]
    fn open_close() {
        let graph = MeshGraph::<E2>::from_raw_buffers(
            vec![Trigon::from([0usize, 1, 2])],
            vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0)],
        )
        .unwrap();
        let keys = graph
            .faces()
            .nth(0)
            .unwrap()
            .interior_arcs()
            .map(|arc| arc.into_source_vertex())
            .keys()
            .collect::<Vec<_>>();

        let mut path = graph.path(keys.iter()).unwrap();
        assert!(path.is_open());
        // TODO: Move this assertion to a distinct test.
        assert_eq!(path.vertices().keys().collect::<Vec<_>>(), keys.to_vec());

        path.push_front(ByKey(keys[0])).unwrap();
        assert!(path.is_closed());
        assert_eq!(path.front().key(), path.back().key());
    }
}
<commit_msg>Implement `Path` using binding traits.<commit_after>use fool::BoolExt;
use std::borrow::Borrow;
use std::collections::{HashSet, VecDeque};

use crate::graph::edge::{Arc, ArcKey, ArcView};
use crate::graph::geometry::{Geometric, Geometry, GraphGeometry};
use crate::graph::mutation::Consistent;
use crate::graph::vertex::{Vertex, VertexKey, VertexView};
use crate::graph::{GraphError, OptionExt as _, Selector};
use crate::network::borrow::{Reborrow, ReborrowMut};
use crate::network::storage::{AsStorage, AsStorageMut};
use crate::network::view::{Bind, ClosedView};
use crate::IteratorExt as _;

/// View of a path in a graph.
///
/// Provides a representation of non-intersecting paths in a graph. A path is
/// conceptually an ordered set of vertices that are joined by arcs. Paths are
/// notated as either sequences or sets. An open path over vertices $A$, $B$,
/// and $C$ is notated $\overrightarrow{(A,B,C)}$ and a closed path over the
/// same vertices is notated $\overrightarrow{\\{A,B,C\\}}$.
///
/// `Path` represents paths of the form $\overrightarrow{(A,\cdots,B)}$, where
/// $A$ is the back of the path and $B$ is the front of the path. Note that
/// closed paths are always of the form $\overrightarrow{(A,\cdots,A)}$, where
/// the back and front vertices are both $A$ (the same).
#[derive(Clone)]
pub struct Path<B>
where
    B: Reborrow,
    B::Target:
        AsStorage<Arc<Geometry<B>>> + AsStorage<Vertex<Geometry<B>>> + Consistent + Geometric,
{
    keys: VecDeque<ArcKey>,
    storage: B,
}

impl<B, M, G> Path<B>
where
    B: Reborrow<Target = M>,
    M: AsStorage<Arc<G>> + AsStorage<Vertex<G>> + Consistent + Geometric<Geometry = G>,
    G: GraphGeometry,
{
    // Paths bind multiple keys to storage and so do not support view APIs.
    // This bespoke `bind` function ensures that the path is not empty and that
    // the topology forms a non-intersecting path.
    pub(in crate::graph) fn bind<I>(storage: B, keys: I) -> Result<Self, GraphError>
    where
        I: IntoIterator,
        I::Item: Borrow<VertexKey>,
    {
        let mut keys = keys.into_iter().map(|key| *key.borrow());
        let a = keys.next().ok_or_else(|| GraphError::TopologyMalformed)?;
        let b = keys.next().ok_or_else(|| GraphError::TopologyMalformed)?;
        let ab = (a, b).into();
        ArcView::bind(storage.reborrow(), ab).ok_or_else(|| GraphError::TopologyNotFound)?;
        let mut path = Path {
            keys: (&[ab]).iter().cloned().collect(),
            storage,
        };
        for key in keys {
            path.push_front(Selector::ByKey(key))?;
        }
        Ok(path)
    }

    pub fn to_ref(&self) -> Path<&M> {
        let storage = self.storage.reborrow();
        let keys = self.keys.iter();
        Path::bind_unchecked(storage, keys)
    }

    /// Pushes a vertex onto the back of the path.
    ///
    /// The back of a path $\overrightarrow{(A,\cdots)}$ is the vertex $A$.
    /// This is the source vertex of the first arc that forms the path.
    ///
    /// The given vertex must be a source vertex of an arc formed with the the
    /// back of the path. That is, if the given vertex is $X$, then
    /// $\overrightarrow{XA}$ must exist.
    ///
    /// Returns the key of the arc $\overrightarrow{XA}$ inserted into the path
    /// using the given source vertex $X$.
    ///
    /// # Errors
    ///
    /// Returns an error if the path is closed, the given vertex is not found,
    /// or the given vertex does not form an arc with the back of the path.
    pub fn push_back(&mut self, destination: Selector<VertexKey>) -> Result<ArcKey, GraphError> {
        self.is_open()
            .ok_or_else(|| GraphError::TopologyMalformed)?;
        let back = self.back();
        let xa = match destination {
            Selector::ByKey(key) => back
                .incoming_arcs()
                .find(|arc| arc.into_source_vertex().key() == key)
                .ok_or_else(|| GraphError::TopologyMalformed)?
                .key(),
            Selector::ByIndex(index) => {
                let x = back
                    .neighboring_vertices()
                    .keys()
                    .nth(index)
                    .ok_or_else(|| GraphError::TopologyNotFound)?;
                (x, back.key()).into()
            }
        };
        let (x, _) = xa.into();
        // Do not allow intersections unless they form a loop with the first
        // vertex in the path (this iteration skips the vertex at the front of
        // the path).
        let is_intersecting = self
            .arcs()
            .map(|arc| arc.into_source_vertex())
            .keys()
            .any(|key| key == x);
        if is_intersecting {
            Err(GraphError::TopologyMalformed)
        }
        else {
            self.keys.push_back(xa);
            Ok(xa)
        }
    }

    /// Pops a vertex from the back of the path.
    pub fn pop_back(&mut self) -> Option<ArcKey> {
        // Empty paths are forbidden.
        if self.keys.len() > 1 {
            self.keys.pop_back()
        }
        else {
            None
        }
    }

    /// Pushes a vertex onto the front of the path.
    ///
    /// The front of a path $\overrightarrow{(\cdots,B)}$ is the vertex $B$.
    /// This is the destination vertex of the last arc that forms the path.
    ///
    /// The given vertex must be a destination vertex of an arc formed with the
    /// the front of the path. That is, if the given vertex is $X$, then
    /// $\overrightarrow{BX}$ must exist.
    ///
    /// Returns the key of the arc $\overrightarrow{BX}$ inserted into the path
    /// using the given source vertex $X$.
    ///
    /// # Errors
    ///
    /// Returns an error if the path is closed, the given vertex is not found,
    /// or the given vertex does not form an arc with the front of the path.
    pub fn push_front(&mut self, destination: Selector<VertexKey>) -> Result<ArcKey, GraphError> {
        self.is_open()
            .ok_or_else(|| GraphError::TopologyMalformed)?;
        let front = self.front();
        let bx = match destination {
            Selector::ByKey(key) => front
                .outgoing_arcs()
                .find(|arc| arc.into_destination_vertex().key() == key)
                .ok_or_else(|| GraphError::TopologyMalformed)?
                .key(),
            Selector::ByIndex(index) => {
                let x = front
                    .neighboring_vertices()
                    .keys()
                    .nth(index)
                    .ok_or_else(|| GraphError::TopologyNotFound)?;
                (front.key(), x).into()
            }
        };
        let (_, x) = bx.into();
        // Do not allow intersections unless they form a loop with the first
        // vertex in the path (this iteration skips the vertex at the back of
        // the path).
        let is_intersecting = self
            .arcs()
            .map(|arc| arc.into_destination_vertex())
            .keys()
            .any(|key| key == x);
        if is_intersecting {
            Err(GraphError::TopologyMalformed)
        }
        else {
            self.keys.push_front(bx);
            Ok(bx)
        }
    }

    /// Pops a vertex from the front of the path.
    pub fn pop_front(&mut self) -> Option<ArcKey> {
        // Empty paths are forbidden.
        if self.keys.len() > 1 {
            self.keys.pop_front()
        }
        else {
            None
        }
    }

    /// Gets the vertex at the back of the path.
    pub fn back(&self) -> VertexView<&M> {
        let (key, _) = self.endpoints();
        Bind::bind(self.storage.reborrow(), key).expect_consistent()
    }

    /// Gets the vertex at the front of the path.
    pub fn front(&self) -> VertexView<&M> {
        let (_, key) = self.endpoints();
        Bind::bind(self.storage.reborrow(), key).expect_consistent()
    }

    /// Gets an iterator over the vertices in the path.
    pub fn vertices<'a>(&'a self) -> impl Iterator<Item = VertexView<&'a M>>
    where
        M: 'a,
    {
        let back = self.back();
        Some(back)
            .into_iter()
            .chain(self.arcs().map(|arc| arc.into_destination_vertex()))
    }

    /// Gets an iterator over the arcs in the path.
    pub fn arcs<'a>(&'a self) -> impl ExactSizeIterator<Item = ArcView<&'a M>>
    where
        M: 'a,
    {
        let storage = self.storage.reborrow();
        self.keys
            .iter()
            .rev()
            .cloned()
            .map(move |key| Bind::bind(storage, key).expect_consistent())
    }

    /// Returns `true` if the path is open.
    ///
    /// An _open path_ is a path that terminates and does **not** form a loop.
    pub fn is_open(&self) -> bool {
        !self.is_closed()
    }

    /// Returns `true` if the path is closed.
    ///
    /// A _closed path_ is a path that forms a loop by starting and ending at
    /// the same vertex.
    pub fn is_closed(&self) -> bool {
        let (a, b) = self.endpoints();
        a == b
    }

    fn bind_unchecked<I>(storage: B, keys: I) -> Self
    where
        I: IntoIterator,
        I::Item: Borrow<ArcKey>,
    {
        let keys = keys.into_iter().map(|key| *key.borrow()).collect();
        Path { storage, keys }
    }

    fn endpoints(&self) -> (VertexKey, VertexKey) {
        let (a, _) = self.keys.back().cloned().expect("empty path").into();
        let (_, b) = self.keys.front().cloned().expect("empty pathy").into();
        (a, b)
    }
}

impl<B, M, G> Path<B>
where
    B: ReborrowMut<Target = M>,
    M: AsStorageMut<Arc<G>> + AsStorageMut<Vertex<G>> + Consistent + Geometric<Geometry = G>,
    G: GraphGeometry,
{
    pub fn to_mut(&mut self) -> Path<&mut M> {
        let storage = self.storage.reborrow_mut();
        let keys = self.keys.iter();
        Path::bind_unchecked(storage, keys)
    }
}

impl<'a, M, G> Path<&'a mut M>
where
    M: AsStorageMut<Arc<G>> + AsStorageMut<Vertex<G>> + Consistent + Geometric<Geometry = G>,
    G: GraphGeometry,
{
    /// Converts a mutable view into an immutable view.
    ///
    /// This is useful when mutations are not (or no longer) needed and mutual
    /// access is desired.
    pub fn into_ref(self) -> Path<&'a M> {
        let Path { keys, storage, .. } = self;
        Path {
            keys,
            storage: &*storage,
        }
    }
}

impl<B, M, G> PartialEq for Path<B>
where
    B: Reborrow<Target = M>,
    M: AsStorage<Arc<G>> + AsStorage<Vertex<G>> + Consistent + Geometric<Geometry = G>,
    G: GraphGeometry,
{
    fn eq(&self, other: &Self) -> bool {
        let keys = |path: &Self| path.arcs().keys().collect::<HashSet<_>>();
        keys(self) == keys(other)
    }
}

#[cfg(test)]
mod tests {
    use nalgebra::Point2;

    use crate::buffer::FromRawBuffers;
    use crate::graph::{ClosedView, MeshGraph, Selector};
    use crate::primitive::Trigon;
    use crate::IteratorExt;

    use Selector::ByKey;

    type E2 = Point2<f64>;

    #[test]
    fn open_close() {
        let graph = MeshGraph::<E2>::from_raw_buffers(
            vec![Trigon::from([0usize, 1, 2])],
            vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0)],
        )
        .unwrap();
        let keys = graph
            .faces()
            .nth(0)
            .unwrap()
            .interior_arcs()
            .map(|arc| arc.into_source_vertex())
            .keys()
            .collect::<Vec<_>>();

        let mut path = graph.path(keys.iter()).unwrap();
        assert!(path.is_open());
        // TODO: Move this assertion to a distinct test.
        assert_eq!(path.vertices().keys().collect::<Vec<_>>(), keys.to_vec());

        path.push_front(ByKey(keys[0])).unwrap();
        assert!(path.is_closed());
        assert_eq!(path.front().key(), path.back().key());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2019, Ben Boeckel
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of this project nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::collections::HashMap;
use std::fs;
use std::str::FromStr;

use regex::{Captures, Regex};

lazy_static! {
    pub static ref PAGE_SIZE: usize = page_size();
    pub static ref KEY_INFO: KeyQuota = key_user_info();
}

fn page_size() -> usize {
    errno::set_errno(errno::Errno(0));
    let ret = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
    if ret < 0 {
        let err = errno::errno();
        if err.0 == 0 {
            panic!("page size is indeterminite?");
        } else {
            panic!("failed to query the page size: {}", errno::errno());
        }
    }
    ret as usize
}

const KEY_USERS_FILE: &str = "/proc/key-users";

lazy_static! {
    static ref KEY_USERS: Regex = Regex::new(
        " *(?P<uid>\\d+): +\
         (?P<usage>\\d+) \
         (?P<nkeys>\\d+)/(?P<nikeys>\\d+) \
         (?P<qnkeys>\\d+)/(?P<maxkeys>\\d+) \
         (?P<qnbytes>\\d+)/(?P<maxbytes>\\d+)"
    )
    .unwrap();
}

fn by_name<T: FromStr>(capture: &Captures, name: &str) -> T {
    let cap = capture
        .name(name)
        .expect("name should be captured")
        .as_str();
    match cap.parse() {
        Ok(v) => v,
        Err(_) => panic!("failed to parse {} as an integer", name),
    }
}

#[derive(Debug, Clone, Copy)]
pub struct KeyQuota {
    pub usage: usize,
    pub nkeys: usize,
    pub nikeys: usize,
    pub qnkeys: usize,
    pub maxkeys: usize,
    pub qnbytes: usize,
    pub maxbytes: usize,
}

fn all_key_user_info() -> HashMap<libc::uid_t, KeyQuota> {
    let data = String::from_utf8(fs::read(KEY_USERS_FILE).unwrap()).unwrap();
    (*KEY_USERS)
        .captures_iter(&data)
        .map(|capture| {
            let uid = by_name(&capture, "uid");
            let usage = by_name(&capture, "usage");
            let nkeys = by_name(&capture, "nkeys");
            let nikeys = by_name(&capture, "nikeys");
            let qnkeys = by_name(&capture, "qnkeys");
            let maxkeys = by_name(&capture, "maxkeys");
            let qnbytes = by_name(&capture, "qnbytes");
            let maxbytes = by_name(&capture, "maxbytes");

            (
                uid,
                KeyQuota {
                    usage,
                    nkeys,
                    nikeys,
                    qnkeys,
                    maxkeys,
                    qnbytes,
                    maxbytes,
                },
            )
        })
        .collect()
}

fn key_user_info() -> KeyQuota {
    let uid = unsafe { libc::getuid() };
    *all_key_user_info()
        .get(&uid)
        .expect("the current user has no keys?")
}
<commit_msg>tests/utils/kernel: add statics for the uid and gid<commit_after>// Copyright (c) 2019, Ben Boeckel
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of this project nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::collections::HashMap;
use std::fs;
use std::str::FromStr;

use regex::{Captures, Regex};

lazy_static! {
    pub static ref PAGE_SIZE: usize = page_size();
    pub static ref UID: libc::uid_t = getuid();
    pub static ref GID: libc::gid_t = getgid();
    pub static ref KEY_INFO: KeyQuota = key_user_info();
}

fn page_size() -> usize {
    errno::set_errno(errno::Errno(0));
    let ret = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
    if ret < 0 {
        let err = errno::errno();
        if err.0 == 0 {
            panic!("page size is indeterminite?");
        } else {
            panic!("failed to query the page size: {}", errno::errno());
        }
    }
    ret as usize
}

const KEY_USERS_FILE: &str = "/proc/key-users";

lazy_static! {
    static ref KEY_USERS: Regex = Regex::new(
        " *(?P<uid>\\d+): +\
         (?P<usage>\\d+) \
         (?P<nkeys>\\d+)/(?P<nikeys>\\d+) \
         (?P<qnkeys>\\d+)/(?P<maxkeys>\\d+) \
         (?P<qnbytes>\\d+)/(?P<maxbytes>\\d+)"
    )
    .unwrap();
}

fn by_name<T: FromStr>(capture: &Captures, name: &str) -> T {
    let cap = capture
        .name(name)
        .expect("name should be captured")
        .as_str();
    match cap.parse() {
        Ok(v) => v,
        Err(_) => panic!("failed to parse {} as an integer", name),
    }
}

#[derive(Debug, Clone, Copy)]
pub struct KeyQuota {
    pub usage: usize,
    pub nkeys: usize,
    pub nikeys: usize,
    pub qnkeys: usize,
    pub maxkeys: usize,
    pub qnbytes: usize,
    pub maxbytes: usize,
}

fn all_key_user_info() -> HashMap<libc::uid_t, KeyQuota> {
    let data = String::from_utf8(fs::read(KEY_USERS_FILE).unwrap()).unwrap();
    (*KEY_USERS)
        .captures_iter(&data)
        .map(|capture| {
            let uid = by_name(&capture, "uid");
            let usage = by_name(&capture, "usage");
            let nkeys = by_name(&capture, "nkeys");
            let nikeys = by_name(&capture, "nikeys");
            let qnkeys = by_name(&capture, "qnkeys");
            let maxkeys = by_name(&capture, "maxkeys");
            let qnbytes = by_name(&capture, "qnbytes");
            let maxbytes = by_name(&capture, "maxbytes");

            (
                uid,
                KeyQuota {
                    usage,
                    nkeys,
                    nikeys,
                    qnkeys,
                    maxkeys,
                    qnbytes,
                    maxbytes,
                },
            )
        })
        .collect()
}

fn key_user_info() -> KeyQuota {
    let uid = unsafe { libc::getuid() };
    *all_key_user_info()
        .get(&uid)
        .expect("the current user has no keys?")
}

fn getuid() -> libc::uid_t {
    unsafe { libc::getuid() }
}

fn getgid() -> libc::gid_t {
    unsafe { libc::getgid() }
}
<|endoftext|>


<commit_before>//! Types and traits for working with binary buffers.

use std::{
    cell::RefCell,
    error::Error,
    fmt::{self, Debug, Display},
    marker::PhantomData,
    ops::{Deref, DerefMut},
};

use crate::{
    context::Context,
    handle::Handle,
    result::{JsResult, NeonResult, ResultExt},
    types::{
        buffer::lock::{Ledger, Lock},
        JsArrayBuffer, JsTypedArray,
    },
};

pub(crate) mod lock;
pub(super) mod types;

pub use types::Binary;

/// A trait allowing Rust to borrow binary data from the memory buffer of JavaScript
/// [typed arrays][typed-arrays].
///
/// This trait provides both statically and dynamically checked borrowing. As usual
/// in Rust, mutable borrows are guaranteed not to overlap with other borrows.
///
/// # Example
///
/// ```
/// # use neon::prelude::*;
/// use neon::types::buffer::TypedArray;
///
/// fn double(mut cx: FunctionContext) -> JsResult<JsUndefined> {
///     let mut array: Handle<JsUint32Array> = cx.argument(0)?;
///
///     for elem in array.as_mut_slice(&mut cx).iter_mut() {
///         *elem *= 2;
///     }
///
///     Ok(cx.undefined())
/// }
/// ```
///
/// [typed-arrays]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
pub trait TypedArray: private::Sealed {
    type Item;

    /// Statically checked immutable borrow of binary data.
    ///
    /// This may not be used if a mutable borrow is in scope. For the dynamically
    /// checked variant see [`TypedArray::try_borrow`].
    fn as_slice<'cx, 'a, C>(&self, cx: &'a C) -> &'a [Self::Item]
    where
        C: Context<'cx>;

    /// Statically checked mutable borrow of binary data.
    ///
    /// This may not be used if any other borrow is in scope. For the dynamically
    /// checked variant see [`TypedArray::try_borrow_mut`].
    fn as_mut_slice<'cx, 'a, C>(&mut self, cx: &'a mut C) -> &'a mut [Self::Item]
    where
        C: Context<'cx>;

    /// Dynamically checked immutable borrow of binary data, returning an error if the
    /// the borrow would overlap with a mutable borrow.
    ///
    /// The borrow lasts until [`Ref`] exits scope.
    ///
    /// This is the dynamically checked version of [`TypedArray::as_slice`].
    fn try_borrow<'cx, 'a, C>(&self, lock: &'a Lock<C>) -> Result<Ref<'a, Self::Item>, BorrowError>
    where
        C: Context<'cx>;

    /// Dynamically checked mutable borrow of binary data, returning an error if the
    /// the borrow would overlap with an active borrow.
    ///
    /// The borrow lasts until [`RefMut`] exits scope.
    ///
    /// This is the dynamically checked version of [`TypedArray::as_mut_slice`].
    fn try_borrow_mut<'cx, 'a, C>(
        &mut self,
        lock: &'a Lock<C>,
    ) -> Result<RefMut<'a, Self::Item>, BorrowError>
    where
        C: Context<'cx>;

    /// Returns the size, in bytes, of the allocated binary data.
    fn byte_length<'cx, C>(&self, cx: &mut C) -> usize
    where
        C: Context<'cx>;
}

#[derive(Debug)]
/// Wraps binary data immutably borrowed from a JavaScript value.
pub struct Ref<'a, T> {
    data: &'a [T],
    ledger: &'a RefCell<Ledger>,
}

#[derive(Debug)]
/// Wraps binary data mutably borrowed from a JavaScript value.
pub struct RefMut<'a, T> {
    data: &'a mut [T],
    ledger: &'a RefCell<Ledger>,
}

impl<'a, T> Deref for Ref<'a, T> {
    type Target = [T];

    fn deref(&self) -> &Self::Target {
        self.data
    }
}

impl<'a, T> Deref for RefMut<'a, T> {
    type Target = [T];

    fn deref(&self) -> &Self::Target {
        self.data
    }
}

impl<'a, T> DerefMut for RefMut<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.data
    }
}

impl<'a, T> Drop for Ref<'a, T> {
    fn drop(&mut self) {
        let mut ledger = self.ledger.borrow_mut();
        let range = Ledger::slice_to_range(self.data);
        let i = ledger.shared.iter().rposition(|r| r == &range).unwrap();

        ledger.shared.remove(i);
    }
}

impl<'a, T> Drop for RefMut<'a, T> {
    fn drop(&mut self) {
        let mut ledger = self.ledger.borrow_mut();
        let range = Ledger::slice_to_range(self.data);
        let i = ledger.owned.iter().rposition(|r| r == &range).unwrap();

        ledger.owned.remove(i);
    }
}

#[derive(Eq, PartialEq)]
/// An error returned by [`TypedArray::try_borrow`] or [`TypedArray::try_borrow_mut`] indicating
/// that a mutable borrow would overlap with another borrow.
///
/// [`BorrowError`] may be converted to an exception with [`ResultExt::or_throw`].
pub struct BorrowError {
    _private: (),
}

impl BorrowError {
    fn new() -> Self {
        BorrowError { _private: () }
    }
}

impl Error for BorrowError {}

impl Display for BorrowError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Display::fmt("Borrow overlaps with an active mutable borrow", f)
    }
}

impl Debug for BorrowError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BorrowError").finish()
    }
}

impl<T> ResultExt<T> for Result<T, BorrowError> {
    fn or_throw<'a, C: Context<'a>>(self, cx: &mut C) -> NeonResult<T> {
        self.or_else(|_| cx.throw_error("BorrowError"))
    }
}

/// Represents a typed region of an [`ArrayBuffer`](crate::types::JsArrayBuffer).
///
/// A `Region` can be created via the
/// [`Handle<JsArrayBuffer>::region()`](crate::handle::Handle::region) or
/// [`JsTypedArray::to_region()`](crate::types::JsTypedArray::to_region) methods.
///
/// A region is **not** checked for validity until it is converted
/// a typed array via [`to_typed_array()`](Region::to_typed_array) or
/// [`JsTypedArray::from_region()`](crate::types::JsTypedArray::from_region).
///
/// # Example
///
/// ```
/// # use crate::prelude::*;
/// # fn f(mut cx: FunctionContext) -> JsResult<JsUint32Array> {
/// // Allocate a 16-byte ArrayBuffer and a uint32 array of length 2 (i.e., 8 bytes)
/// // starting at byte offset 4 of the buffer:
/// //
/// //       0       4       8       12      16
/// //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// // buf: | | | | | | | | | | | | | | | | |
/// //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// //               ^       ^
/// //               |       |
/// //              +-------+-------+
/// //         arr: |       |       |
/// //              +-------+-------+
/// //               0       1       2
/// let buf = cx.array_buffer(16);
/// let arr = JsUint32Array::from_region(&mut cx, buf.region(4, 2))?;
/// # Ok(arr)
/// # }
/// ```
#[derive(Clone, Copy)]
pub struct Region<'cx, T: Binary> {
    pub(super) buffer: Handle<'cx, JsArrayBuffer>,
    pub(super) byte_offset: usize,
    pub(super) len: usize,
    pub(super) phantom: PhantomData<T>,
}

impl<'cx, T: Binary> Region<'cx, T> {
    /// Returns the handle to the region's buffer.
    pub fn buffer(self) -> Handle<'cx, JsArrayBuffer> {
        self.buffer
    }

    /// Returns the starting byte offset of the region.
    pub fn byte_offset(self) -> usize {
        self.byte_offset
    }

    /// Returns the number of elements of type `T` in the region.
    pub fn len(self) -> usize {
        self.len
    }

    /// Returns the byte length of the region, which is equal to
    /// `(self.len() * size_of::<T>())`.
    pub fn byte_length(self) -> usize {
        self.len * std::mem::size_of::<T>()
    }

    /// Constructs a typed array for this buffer region.
    ///
    /// The resulting typed array has `self.len()` elements and byte length
    /// `self.byte_length()`.
    ///
    /// Throws an exception if the region is invalid, for example if the starting
    /// offset is not properly aligned, or the length goes beyond the end of the
    /// buffer.
    pub fn to_typed_array<'c, C>(self, cx: &mut C) -> JsResult<'c, JsTypedArray<T>>
    where
        C: Context<'c>,
    {
        JsTypedArray::from_region(cx, self)
    }
}

mod private {
    use super::Binary;
    use crate::sys::raw;
    use std::marker::PhantomData;

    pub trait Sealed {}

    #[derive(Debug, Clone)]
    pub struct JsTypedArrayInner<T: Binary> {
        pub(super) local: raw::Local,
        pub(super) buffer: raw::Local,
        pub(super) _type: PhantomData<T>,
    }
}
<commit_msg>fix doc test<commit_after>//! Types and traits for working with binary buffers.

use std::{
    cell::RefCell,
    error::Error,
    fmt::{self, Debug, Display},
    marker::PhantomData,
    ops::{Deref, DerefMut},
};

use crate::{
    context::Context,
    handle::Handle,
    result::{JsResult, NeonResult, ResultExt},
    types::{
        buffer::lock::{Ledger, Lock},
        JsArrayBuffer, JsTypedArray,
    },
};

pub(crate) mod lock;
pub(super) mod types;

pub use types::Binary;

/// A trait allowing Rust to borrow binary data from the memory buffer of JavaScript
/// [typed arrays][typed-arrays].
///
/// This trait provides both statically and dynamically checked borrowing. As usual
/// in Rust, mutable borrows are guaranteed not to overlap with other borrows.
///
/// # Example
///
/// ```
/// # use neon::prelude::*;
/// use neon::types::buffer::TypedArray;
///
/// fn double(mut cx: FunctionContext) -> JsResult<JsUndefined> {
///     let mut array: Handle<JsUint32Array> = cx.argument(0)?;
///
///     for elem in array.as_mut_slice(&mut cx).iter_mut() {
///         *elem *= 2;
///     }
///
///     Ok(cx.undefined())
/// }
/// ```
///
/// [typed-arrays]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
pub trait TypedArray: private::Sealed {
    type Item;

    /// Statically checked immutable borrow of binary data.
    ///
    /// This may not be used if a mutable borrow is in scope. For the dynamically
    /// checked variant see [`TypedArray::try_borrow`].
    fn as_slice<'cx, 'a, C>(&self, cx: &'a C) -> &'a [Self::Item]
    where
        C: Context<'cx>;

    /// Statically checked mutable borrow of binary data.
    ///
    /// This may not be used if any other borrow is in scope. For the dynamically
    /// checked variant see [`TypedArray::try_borrow_mut`].
    fn as_mut_slice<'cx, 'a, C>(&mut self, cx: &'a mut C) -> &'a mut [Self::Item]
    where
        C: Context<'cx>;

    /// Dynamically checked immutable borrow of binary data, returning an error if the
    /// the borrow would overlap with a mutable borrow.
    ///
    /// The borrow lasts until [`Ref`] exits scope.
    ///
    /// This is the dynamically checked version of [`TypedArray::as_slice`].
    fn try_borrow<'cx, 'a, C>(&self, lock: &'a Lock<C>) -> Result<Ref<'a, Self::Item>, BorrowError>
    where
        C: Context<'cx>;

    /// Dynamically checked mutable borrow of binary data, returning an error if the
    /// the borrow would overlap with an active borrow.
    ///
    /// The borrow lasts until [`RefMut`] exits scope.
    ///
    /// This is the dynamically checked version of [`TypedArray::as_mut_slice`].
    fn try_borrow_mut<'cx, 'a, C>(
        &mut self,
        lock: &'a Lock<C>,
    ) -> Result<RefMut<'a, Self::Item>, BorrowError>
    where
        C: Context<'cx>;

    /// Returns the size, in bytes, of the allocated binary data.
    fn byte_length<'cx, C>(&self, cx: &mut C) -> usize
    where
        C: Context<'cx>;
}

#[derive(Debug)]
/// Wraps binary data immutably borrowed from a JavaScript value.
pub struct Ref<'a, T> {
    data: &'a [T],
    ledger: &'a RefCell<Ledger>,
}

#[derive(Debug)]
/// Wraps binary data mutably borrowed from a JavaScript value.
pub struct RefMut<'a, T> {
    data: &'a mut [T],
    ledger: &'a RefCell<Ledger>,
}

impl<'a, T> Deref for Ref<'a, T> {
    type Target = [T];

    fn deref(&self) -> &Self::Target {
        self.data
    }
}

impl<'a, T> Deref for RefMut<'a, T> {
    type Target = [T];

    fn deref(&self) -> &Self::Target {
        self.data
    }
}

impl<'a, T> DerefMut for RefMut<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.data
    }
}

impl<'a, T> Drop for Ref<'a, T> {
    fn drop(&mut self) {
        let mut ledger = self.ledger.borrow_mut();
        let range = Ledger::slice_to_range(self.data);
        let i = ledger.shared.iter().rposition(|r| r == &range).unwrap();

        ledger.shared.remove(i);
    }
}

impl<'a, T> Drop for RefMut<'a, T> {
    fn drop(&mut self) {
        let mut ledger = self.ledger.borrow_mut();
        let range = Ledger::slice_to_range(self.data);
        let i = ledger.owned.iter().rposition(|r| r == &range).unwrap();

        ledger.owned.remove(i);
    }
}

#[derive(Eq, PartialEq)]
/// An error returned by [`TypedArray::try_borrow`] or [`TypedArray::try_borrow_mut`] indicating
/// that a mutable borrow would overlap with another borrow.
///
/// [`BorrowError`] may be converted to an exception with [`ResultExt::or_throw`].
pub struct BorrowError {
    _private: (),
}

impl BorrowError {
    fn new() -> Self {
        BorrowError { _private: () }
    }
}

impl Error for BorrowError {}

impl Display for BorrowError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Display::fmt("Borrow overlaps with an active mutable borrow", f)
    }
}

impl Debug for BorrowError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BorrowError").finish()
    }
}

impl<T> ResultExt<T> for Result<T, BorrowError> {
    fn or_throw<'a, C: Context<'a>>(self, cx: &mut C) -> NeonResult<T> {
        self.or_else(|_| cx.throw_error("BorrowError"))
    }
}

/// Represents a typed region of an [`ArrayBuffer`](crate::types::JsArrayBuffer).
///
/// A `Region` can be created via the
/// [`Handle<JsArrayBuffer>::region()`](crate::handle::Handle::region) or
/// [`JsTypedArray::to_region()`](crate::types::JsTypedArray::to_region) methods.
///
/// A region is **not** checked for validity until it is converted
/// a typed array via [`to_typed_array()`](Region::to_typed_array) or
/// [`JsTypedArray::from_region()`](crate::types::JsTypedArray::from_region).
///
/// # Example
///
/// ```
/// # use neon::prelude::*;
/// # fn f(mut cx: FunctionContext) -> JsResult<JsUint32Array> {
/// // Allocate a 16-byte ArrayBuffer and a uint32 array of length 2 (i.e., 8 bytes)
/// // starting at byte offset 4 of the buffer:
/// //
/// //       0       4       8       12      16
/// //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// // buf: | | | | | | | | | | | | | | | | |
/// //      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// //               ^       ^
/// //               |       |
/// //              +-------+-------+
/// //         arr: |       |       |
/// //              +-------+-------+
/// //               0       1       2
/// let buf = cx.array_buffer(16)?;
/// let arr = JsUint32Array::from_region(&mut cx, buf.region(4, 2))?;
/// # Ok(arr)
/// # }
/// ```
#[derive(Clone, Copy)]
pub struct Region<'cx, T: Binary> {
    pub(super) buffer: Handle<'cx, JsArrayBuffer>,
    pub(super) byte_offset: usize,
    pub(super) len: usize,
    pub(super) phantom: PhantomData<T>,
}

impl<'cx, T: Binary> Region<'cx, T> {
    /// Returns the handle to the region's buffer.
    pub fn buffer(self) -> Handle<'cx, JsArrayBuffer> {
        self.buffer
    }

    /// Returns the starting byte offset of the region.
    pub fn byte_offset(self) -> usize {
        self.byte_offset
    }

    /// Returns the number of elements of type `T` in the region.
    pub fn len(self) -> usize {
        self.len
    }

    /// Returns the byte length of the region, which is equal to
    /// `(self.len() * size_of::<T>())`.
    pub fn byte_length(self) -> usize {
        self.len * std::mem::size_of::<T>()
    }

    /// Constructs a typed array for this buffer region.
    ///
    /// The resulting typed array has `self.len()` elements and byte length
    /// `self.byte_length()`.
    ///
    /// Throws an exception if the region is invalid, for example if the starting
    /// offset is not properly aligned, or the length goes beyond the end of the
    /// buffer.
    pub fn to_typed_array<'c, C>(self, cx: &mut C) -> JsResult<'c, JsTypedArray<T>>
    where
        C: Context<'c>,
    {
        JsTypedArray::from_region(cx, self)
    }
}

mod private {
    use super::Binary;
    use crate::sys::raw;
    use std::marker::PhantomData;

    pub trait Sealed {}

    #[derive(Debug, Clone)]
    pub struct JsTypedArrayInner<T: Binary> {
        pub(super) local: raw::Local,
        pub(super) buffer: raw::Local,
        pub(super) _type: PhantomData<T>,
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt;
use std::io;

use crate::credential::CredentialsError;

use super::proto::xml::util::XmlParseError;
use super::request::{BufferedHttpResponse, HttpDispatchError};
use crate::client::SignAndDispatchError;

/// Generic error type returned by all rusoto requests.
#[derive(Debug, PartialEq)]
pub enum RusotoError<E> {
    /// A service-specific error occurred.
    Service(E),
    /// An error occurred dispatching the HTTP request
    HttpDispatch(HttpDispatchError),
    /// An error was encountered with AWS credentials.
    Credentials(CredentialsError),
    /// A validation error occurred.  Details from AWS are provided.
    Validation(String),
    /// An error occurred parsing the response payload.
    ParseError(String),
    /// An unknown error occurred.  The raw HTTP response is provided.
    Unknown(BufferedHttpResponse),
    /// An error occurred when attempting to run a future as blocking
    Blocking,
}

/// Result carrying a generic `RusotoError`.
pub type RusotoResult<T, E> = Result<T, RusotoError<E>>;

impl<E> From<XmlParseError> for RusotoError<E> {
    fn from(err: XmlParseError) -> Self {
        let XmlParseError(message) = err;
        RusotoError::ParseError(message)
    }
}

impl<E> From<serde_json::error::Error> for RusotoError<E> {
    fn from(err: serde_json::error::Error) -> Self {
        RusotoError::ParseError(err.to_string())
    }
}

impl<E> From<CredentialsError> for RusotoError<E> {
    fn from(err: CredentialsError) -> Self {
        RusotoError::Credentials(err)
    }
}

impl<E> From<HttpDispatchError> for RusotoError<E> {
    fn from(err: HttpDispatchError) -> Self {
        RusotoError::HttpDispatch(err)
    }
}

impl<E> From<SignAndDispatchError> for RusotoError<E> {
    fn from(err: SignAndDispatchError) -> Self {
        match err {
            SignAndDispatchError::Credentials(e) => Self::from(e),
            SignAndDispatchError::Dispatch(e) => Self::from(e),
        }
    }
}

impl<E> From<io::Error> for RusotoError<E> {
    fn from(err: io::Error) -> Self {
        RusotoError::HttpDispatch(HttpDispatchError::from(err))
    }
}

impl<E: Error + 'static> fmt::Display for RusotoError<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            RusotoError::Service(ref err) => write!(f, "{}", err),
            RusotoError::Validation(ref cause) => write!(f, "{}", cause),
            RusotoError::Credentials(ref err) => write!(f, "{}", err),
            RusotoError::HttpDispatch(ref dispatch_error) => write!(f, "{}", dispatch_error),
            RusotoError::ParseError(ref cause) => write!(f, "{}", cause),
            RusotoError::Unknown(ref cause) => write!(f, "{}", cause.body_as_str()),
            RusotoError::Blocking => write!(f, "Failed to run blocking future"),
        }
    }
}

impl<E: Error + 'static> Error for RusotoError<E> {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match *self {
            RusotoError::Service(ref err) => Some(err),
            RusotoError::Credentials(ref err) => Some(err),
            RusotoError::HttpDispatch(ref err) => Some(err),
            _ => None,
        }
    }
}
<commit_msg>Rollup merge of #1704<commit_after>use std::error::Error;
use std::fmt;
use std::io;

use crate::credential::CredentialsError;

use super::proto::xml::util::XmlParseError;
use super::request::{BufferedHttpResponse, HttpDispatchError};
use crate::client::SignAndDispatchError;

/// Generic error type returned by all rusoto requests.
#[derive(Debug, PartialEq)]
pub enum RusotoError<E> {
    /// A service-specific error occurred.
    Service(E),
    /// An error occurred dispatching the HTTP request
    HttpDispatch(HttpDispatchError),
    /// An error was encountered with AWS credentials.
    Credentials(CredentialsError),
    /// A validation error occurred.  Details from AWS are provided.
    Validation(String),
    /// An error occurred parsing the response payload.
    ParseError(String),
    /// An unknown error occurred.  The raw HTTP response is provided.
    Unknown(BufferedHttpResponse),
    /// An error occurred when attempting to run a future as blocking
    Blocking,
}

/// Result carrying a generic `RusotoError`.
pub type RusotoResult<T, E> = Result<T, RusotoError<E>>;

/// Header used by AWS on responses to identify the request
pub const AWS_REQUEST_ID_HEADER: &str = "x-amzn-requestid";

impl<E> From<XmlParseError> for RusotoError<E> {
    fn from(err: XmlParseError) -> Self {
        let XmlParseError(message) = err;
        RusotoError::ParseError(message)
    }
}

impl<E> From<serde_json::error::Error> for RusotoError<E> {
    fn from(err: serde_json::error::Error) -> Self {
        RusotoError::ParseError(err.to_string())
    }
}

impl<E> From<CredentialsError> for RusotoError<E> {
    fn from(err: CredentialsError) -> Self {
        RusotoError::Credentials(err)
    }
}

impl<E> From<HttpDispatchError> for RusotoError<E> {
    fn from(err: HttpDispatchError) -> Self {
        RusotoError::HttpDispatch(err)
    }
}

impl<E> From<SignAndDispatchError> for RusotoError<E> {
    fn from(err: SignAndDispatchError) -> Self {
        match err {
            SignAndDispatchError::Credentials(e) => Self::from(e),
            SignAndDispatchError::Dispatch(e) => Self::from(e),
        }
    }
}

impl<E> From<io::Error> for RusotoError<E> {
    fn from(err: io::Error) -> Self {
        RusotoError::HttpDispatch(HttpDispatchError::from(err))
    }
}

impl<E: Error + 'static> fmt::Display for RusotoError<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            RusotoError::Service(ref err) => write!(f, "{}", err),
            RusotoError::Validation(ref cause) => write!(f, "{}", cause),
            RusotoError::Credentials(ref err) => write!(f, "{}", err),
            RusotoError::HttpDispatch(ref dispatch_error) => write!(f, "{}", dispatch_error),
            RusotoError::ParseError(ref cause) => write!(f, "{}", cause),
            RusotoError::Unknown(ref cause) => write!(
                f,
                "Request ID: {:?} Body: {}",
                cause.headers.get(AWS_REQUEST_ID_HEADER),
                cause.body_as_str()
            ),
            RusotoError::Blocking => write!(f, "Failed to run blocking future"),
        }
    }
}

impl<E: Error + 'static> Error for RusotoError<E> {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match *self {
            RusotoError::Service(ref err) => Some(err),
            RusotoError::Credentials(ref err) => Some(err),
            RusotoError::HttpDispatch(ref err) => Some(err),
            _ => None,
        }
    }
}
<|endoftext|>


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

/// Performs prime factorization in O(√x) time.
pub fn factorize(mut x: i64) -> BTreeMap<i64, i64> {
    let mut ms = BTreeMap::new();
    let r = (x as f64).sqrt() as i64 + 1;

    for p in 2..r as i64 {
        let mut m = 0;

        while x >= p && x % p == 0 {
            x /= p;
            m += 1;
        }

        if m > 0 {
            ms.insert(p, m);
        }
    }

    // `x` can have a prime factor larger than √x at most one.
    if x > 1 {
        ms.insert(x, 1);
    }

    ms
}

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

    #[test]
    fn test_factorize() {
        let x = 2 * 2 * 2 * 5 * 5 * 7 * 97;
        let m = factorize(x);
        let v = m.into_iter().collect::<Vec<_>>();
        assert_eq!(v, vec![(2, 3), (5, 2), (7, 1), (97, 1)])
    }

    #[test]
    fn test_factorize_edges() {
        assert_eq!(factorize(0).len(), 0);
    }
}
<commit_msg>Add prime::is_prime<commit_after>use std::collections::BTreeMap;

/// Determines if the specified number is a prime or not.
/// O(√x) time.
pub fn is_prime(x: i64) -> bool {
    let r = |x: i64| (x as f64).sqrt() as i64 + 1;
    x >= 2 && (2..r(x)).all(|k| x % k != 0)
}

/// Performs prime factorization in O(√x) time.
pub fn factorize(mut x: i64) -> BTreeMap<i64, i64> {
    let mut ms = BTreeMap::new();
    let r = (x as f64).sqrt() as i64 + 1;

    for p in 2..r as i64 {
        let mut m = 0;

        while x >= p && x % p == 0 {
            x /= p;
            m += 1;
        }

        if m > 0 {
            ms.insert(p, m);
        }
    }

    // `x` can have a prime factor larger than √x at most one.
    if x > 1 {
        ms.insert(x, 1);
    }

    ms
}

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

    #[test]
    fn test_is_prime_edges() {
        assert_eq!(is_prime(1), false);
        assert_eq!(is_prime(2), true);
        assert_eq!(is_prime(1_000_000_007), true);
    }

    #[test]
    fn test_is_prime_small() {
        for x in 1..100 {
            let actual = is_prime(x);
            let expected = x >= 2 && (2..x).all(|d| x % d != 0);
            assert_eq!(actual, expected, "{}", x);
        }
    }

    #[test]
    fn test_factorize() {
        let x = 2 * 2 * 2 * 5 * 5 * 7 * 97;
        let m = factorize(x);
        let v = m.into_iter().collect::<Vec<_>>();
        assert_eq!(v, vec![(2, 3), (5, 2), (7, 1), (97, 1)])
    }

    #[test]
    fn test_factorize_edges() {
        assert_eq!(factorize(0).len(), 0);
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ops;
use std::ptr;
use std::slice;
use std::iter;

use nodrop::NoDrop;

use num_traits::{Unsigned, Zero, One};

pub struct OverflowError<T1, T2>(pub T1, pub T2);

#[derive(Debug)]
pub enum InsertError<T1, T2> {
    Overflow(T1, T2),
    OutOfBounds(T1, T2)
}

pub unsafe trait Array {
    type Item;
    type Index: Index;
    fn as_ptr(&self) -> *const Self::Item;
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
    fn capacity(&self) -> usize;
}

pub trait Index : Unsigned + ops::AddAssign + ops::SubAssign + Copy {
    fn as_usize(self) -> usize;
    fn from_usize(value: usize) -> Self;
}

macro_rules! impl_index {
    ($index_type:ty) => (
        impl Index for $index_type {
            fn as_usize(self) -> usize {
                self as usize
            }

            fn from_usize(value: usize) -> Self {
                value as $index_type
            }
        }
    )
}

impl_index!(u8);
impl_index!(u16);
impl_index!(u32);
impl_index!(usize);

macro_rules! impl_array {
    ($index_type:ty, $len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            type Index = $index_type;
            #[inline(always)]
            fn as_ptr(&self) -> *const T {
                self as *const _ as *const _
            }

            #[inline(always)]
            fn as_mut_ptr(&mut self) -> *mut T {
                self as *mut _ as *mut _
            }

            #[inline(always)]
            fn capacity(&self) -> usize {
                $len
            }
        }
    )
}

macro_rules! impl_array_many {
    ($index_type:ty, $($len:expr),+) => (
        $(
            impl_array!($index_type, $len);
        )*
    );
}

impl_array_many!(u8, 1, 2, 7, 31, 256);

pub struct LockstepArray<A1: Array, A2: Array> {
    len: A1::Index,
    array1: NoDrop<A1>,
    array2: NoDrop<A2>
}

impl<A1, A2> LockstepArray<A1, A2> where A1: Array, A2: Array {
    pub fn new() -> LockstepArray<A1, A2> {
        LockstepArray {
            len: Zero::zero(),
            array1: NoDrop::new(unsafe {mem::uninitialized()}),
            array2: NoDrop::new(unsafe {mem::uninitialized()})
        }
    }

    pub fn from_arrays<B1, B2>(array1: B1, array2: B2) -> LockstepArray<A1, A2>
        where B1: Array<Item=A1::Item>, B2: Array<Item=A2::Item> {
        let mut lockstep = LockstepArray::<A1, A2>::new();
        // Eventually these will be encoded into the type system
        assert!(array1.capacity() <= lockstep.array1.capacity());
        assert!(array2.capacity() <= lockstep.array2.capacity());
        assert_eq!(array1.capacity(), array2.capacity());
        let len = A1::Index::from_usize(array1.capacity());
        unsafe {
            ptr::copy_nonoverlapping(array1.as_ptr(),
                                     lockstep.array1.as_mut_ptr(),
                                     array1.capacity());
            mem::forget(array1);
            ptr::copy_nonoverlapping(array2.as_ptr(),
                                     lockstep.array2.as_mut_ptr(),
                                     array2.capacity());
            mem::forget(array2);
        }
        lockstep.len = len;
        lockstep
    }

    pub fn push(&mut self, item1: A1::Item, item2: A2::Item)
                -> Result<(), OverflowError<A1::Item, A2::Item>> {
        if self.len.as_usize() == self.array1.capacity() {
            return Err(OverflowError(item1, item2));
        }
        unsafe {
            let p1 = self.array1.as_mut_ptr();
            ptr::write(p1.offset(self.len.as_usize() as isize), item1);
            let p2 = self.array2.as_mut_ptr();
            ptr::write(p2.offset(self.len.as_usize() as isize), item2);
        }
        self.len += One::one();
        Ok(())
    }

    pub fn pop(&mut self) -> Option<(A1::Item, A2::Item)> {
        if self.len == Zero::zero() {
            None
        } else {
            unsafe {
                // Calculate item 1's pointer
                let src1 = self.array1.as_mut_ptr()
                    .offset(self.len.as_usize() as isize);
                // Move item 1 out of the pointer
                let item1 = ptr::read(src1);
                // Calculate item 1's pointer
                let src2 = self.array2.as_mut_ptr()
                    .offset(self.len.as_usize() as isize);
                // Move item 1 out of the pointer
                let item2 = ptr::read(src2);
                // Update length
                self.len -= One::one();
                Some((item1, item2))
            }
        }
    }

    pub fn insert(&mut self, index: usize, item1: A1::Item, item2: A2::Item)
                  -> Result<(), InsertError<A1::Item, A2::Item>> {
        if index > self.len.as_usize() {
            Err(InsertError::OutOfBounds(item1, item2))
        } else if self.len.as_usize() == self.array1.capacity() {
            Err(InsertError::Overflow(item1, item2))
        } else {
            unsafe {
                // TODO: Tricky math, check indices and such
                let dest1 = self.array1.as_mut_ptr().offset(index as isize);
                ptr::copy(dest1, dest1.offset(1), self.len.as_usize() - index);
                ptr::write(dest1, item1);
                let dest2 = self.array2.as_mut_ptr().offset(index as isize);
                ptr::copy(dest2, dest2.offset(1), self.len.as_usize() - index);
                ptr::write(dest2, item2);
            }
            self.len += One::one();
            Ok(())
        }
    }

    pub fn remove(&mut self, index: usize) -> Option<(A1::Item, A2::Item)> {
        if index >= self.len.as_usize() {
            None
        } else {
            let item1;
            let item2;
            unsafe {
                // Calculate item 1's pointer
                let src1 = self.array1.as_mut_ptr().offset(index as isize);
                // Move item 1 out of the pointer
                item1 = ptr::read(src1);
                // Shift down array 1 down by 1
                // Is self.len - index correct?
                ptr::copy(src1.offset(1), src1, self.len.as_usize() - index);
                // Calculate item 1's pointer
                let src2 = self.array2.as_mut_ptr().offset(index as isize);
                // Move item 1 out of the pointer
                item2 = ptr::read(src2);
                // Shift down array 1 down by 1
                // Is self.len - index correct?
                ptr::copy(src2, src2.offset(1), self.len.as_usize() - index);
                // Update length
                self.len -= One::one();
            }
            Some((item1, item2))
        }
    }

    pub fn is_empty(&self) -> bool {
        self.len != Zero::zero()
    }

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

    pub fn array1(&self) -> &[A1::Item] {
        unsafe {
            let ptr = self.array1.as_ptr();
            let len = self.len.as_usize();
            slice::from_raw_parts(ptr, len)
        }
    }

    pub fn array2(&self) -> &[A2::Item] {
        unsafe {
            let ptr = self.array2.as_ptr();
            let len = self.len.as_usize();
            slice::from_raw_parts(ptr, len)
        }
    }

    pub fn array1_mut(&mut self) -> &mut [A1::Item] {
        unsafe {
            let ptr = self.array1.as_mut_ptr();
            let len = self.len.as_usize();
            slice::from_raw_parts_mut(ptr, len)
        }
    }

    pub fn array2_mut(&mut self) -> &mut [A2::Item] {
        unsafe {
            let ptr = self.array2.as_mut_ptr();
            let len = self.len.as_usize();
            slice::from_raw_parts_mut(ptr, len)
        }
    }

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

impl<A1, A2> Default for LockstepArray<A1, A2> where A1: Array, A2: Array {
    fn default() -> Self {
        Self::new()
    }
}

impl<A1, A2> IntoIterator for LockstepArray<A1, A2> where A1: Array, A2: Array {
    type Item = (A1::Item, A2::Item);
    type IntoIter = IntoIter<A1, A2>;
    fn into_iter(self) -> Self::IntoIter {
        let LockstepArray { len, array1, array2 } = self;
        IntoIter {
            len: len.as_usize(),
            array1: array1,
            array2: array2,
            pos: 0
        }
    }
}

pub struct IntoIter<A1: Array, A2: Array> {
    len: usize,
    array1: NoDrop<A1>,
    array2: NoDrop<A2>,
    pos: usize
}

impl<A1: Array, A2: Array> Iterator for IntoIter<A1, A2> {
    type Item = (A1::Item, A2::Item);
    fn next(&mut self) -> Option<Self::Item> {
        if self.pos == self.len {
            None
        } else {
            unsafe {
                let ptr1 = self.array1.as_mut_ptr().offset(self.pos as isize);
                let item1 = ptr::read(ptr1);
                let ptr2 = self.array2.as_mut_ptr().offset(self.pos as isize);
                let item2 = ptr::read(ptr2);
                self.pos += 1;
                Some((item1, item2))
            }
        }
    }
}

#[test]
fn test_into_iter() {
    let mut locksteparray = LockstepArray::<[u8; 7], [u8; 7]>::new();
    locksteparray.insert(0, 4, 5).unwrap();
    locksteparray.insert(1, 3, 4).unwrap();
    let mut iter = locksteparray.into_iter();
    assert_eq!(iter.next(), Some((4, 5)));
    assert_eq!(iter.next(), Some((3, 4)));
    assert_eq!(iter.next(), None);
}
<commit_msg>Add a LockstepArray::get()<commit_after>use std::mem;
use std::ops;
use std::ptr;
use std::slice;
use std::iter;

use nodrop::NoDrop;

use num_traits::{Unsigned, Zero, One};

pub struct OverflowError<T1, T2>(pub T1, pub T2);

#[derive(Debug)]
pub enum InsertError<T1, T2> {
    Overflow(T1, T2),
    OutOfBounds(T1, T2)
}

pub unsafe trait Array {
    type Item;
    type Index: Index;
    fn as_ptr(&self) -> *const Self::Item;
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
    fn capacity(&self) -> usize;
}

pub trait Index : Unsigned + ops::AddAssign + ops::SubAssign + Copy {
    fn as_usize(self) -> usize;
    fn from_usize(value: usize) -> Self;
}

macro_rules! impl_index {
    ($index_type:ty) => (
        impl Index for $index_type {
            fn as_usize(self) -> usize {
                self as usize
            }

            fn from_usize(value: usize) -> Self {
                value as $index_type
            }
        }
    )
}

impl_index!(u8);
impl_index!(u16);
impl_index!(u32);
impl_index!(usize);

macro_rules! impl_array {
    ($index_type:ty, $len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            type Index = $index_type;
            #[inline(always)]
            fn as_ptr(&self) -> *const T {
                self as *const _ as *const _
            }

            #[inline(always)]
            fn as_mut_ptr(&mut self) -> *mut T {
                self as *mut _ as *mut _
            }

            #[inline(always)]
            fn capacity(&self) -> usize {
                $len
            }
        }
    )
}

macro_rules! impl_array_many {
    ($index_type:ty, $($len:expr),+) => (
        $(
            impl_array!($index_type, $len);
        )*
    );
}

impl_array_many!(u8, 1, 2, 7, 31, 256);

pub struct LockstepArray<A1: Array, A2: Array> {
    len: A1::Index,
    array1: NoDrop<A1>,
    array2: NoDrop<A2>
}

impl<A1, A2> LockstepArray<A1, A2> where A1: Array, A2: Array {
    pub fn new() -> LockstepArray<A1, A2> {
        LockstepArray {
            len: Zero::zero(),
            array1: NoDrop::new(unsafe {mem::uninitialized()}),
            array2: NoDrop::new(unsafe {mem::uninitialized()})
        }
    }

    pub fn from_arrays<B1, B2>(array1: B1, array2: B2) -> LockstepArray<A1, A2>
        where B1: Array<Item=A1::Item>, B2: Array<Item=A2::Item> {
        let mut lockstep = LockstepArray::<A1, A2>::new();
        // Eventually these will be encoded into the type system
        assert!(array1.capacity() <= lockstep.array1.capacity());
        assert!(array2.capacity() <= lockstep.array2.capacity());
        assert_eq!(array1.capacity(), array2.capacity());
        let len = A1::Index::from_usize(array1.capacity());
        unsafe {
            ptr::copy_nonoverlapping(array1.as_ptr(),
                                     lockstep.array1.as_mut_ptr(),
                                     array1.capacity());
            mem::forget(array1);
            ptr::copy_nonoverlapping(array2.as_ptr(),
                                     lockstep.array2.as_mut_ptr(),
                                     array2.capacity());
            mem::forget(array2);
        }
        lockstep.len = len;
        lockstep
    }

    pub fn push(&mut self, item1: A1::Item, item2: A2::Item)
                -> Result<(), OverflowError<A1::Item, A2::Item>> {
        if self.len.as_usize() == self.array1.capacity() {
            return Err(OverflowError(item1, item2));
        }
        unsafe {
            let p1 = self.array1.as_mut_ptr();
            ptr::write(p1.offset(self.len.as_usize() as isize), item1);
            let p2 = self.array2.as_mut_ptr();
            ptr::write(p2.offset(self.len.as_usize() as isize), item2);
        }
        self.len += One::one();
        Ok(())
    }

    pub fn pop(&mut self) -> Option<(A1::Item, A2::Item)> {
        if self.len == Zero::zero() {
            None
        } else {
            unsafe {
                // Calculate item 1's pointer
                let src1 = self.array1.as_mut_ptr()
                    .offset(self.len.as_usize() as isize);
                // Move item 1 out of the pointer
                let item1 = ptr::read(src1);
                // Calculate item 1's pointer
                let src2 = self.array2.as_mut_ptr()
                    .offset(self.len.as_usize() as isize);
                // Move item 1 out of the pointer
                let item2 = ptr::read(src2);
                // Update length
                self.len -= One::one();
                Some((item1, item2))
            }
        }
    }

    pub fn insert(&mut self, index: usize, item1: A1::Item, item2: A2::Item)
                  -> Result<(), InsertError<A1::Item, A2::Item>> {
        if index > self.len.as_usize() {
            Err(InsertError::OutOfBounds(item1, item2))
        } else if self.len.as_usize() == self.array1.capacity() {
            Err(InsertError::Overflow(item1, item2))
        } else {
            unsafe {
                // TODO: Tricky math, check indices and such
                let dest1 = self.array1.as_mut_ptr().offset(index as isize);
                ptr::copy(dest1, dest1.offset(1), self.len.as_usize() - index);
                ptr::write(dest1, item1);
                let dest2 = self.array2.as_mut_ptr().offset(index as isize);
                ptr::copy(dest2, dest2.offset(1), self.len.as_usize() - index);
                ptr::write(dest2, item2);
            }
            self.len += One::one();
            Ok(())
        }
    }

    pub fn remove(&mut self, index: usize) -> Option<(A1::Item, A2::Item)> {
        if index >= self.len.as_usize() {
            None
        } else {
            let item1;
            let item2;
            unsafe {
                // Calculate item 1's pointer
                let src1 = self.array1.as_mut_ptr().offset(index as isize);
                // Move item 1 out of the pointer
                item1 = ptr::read(src1);
                // Shift down array 1 down by 1
                // Is self.len - index correct?
                ptr::copy(src1.offset(1), src1, self.len.as_usize() - index);
                // Calculate item 1's pointer
                let src2 = self.array2.as_mut_ptr().offset(index as isize);
                // Move item 1 out of the pointer
                item2 = ptr::read(src2);
                // Shift down array 1 down by 1
                // Is self.len - index correct?
                ptr::copy(src2, src2.offset(1), self.len.as_usize() - index);
                // Update length
                self.len -= One::one();
            }
            Some((item1, item2))
        }
    }

    pub fn is_empty(&self) -> bool {
        self.len != Zero::zero()
    }

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

    pub fn get(&self, index: usize) -> Option<(&A1::Item, &A2::Item)> {
        if index >= self.len.as_usize() {
            None
        } else {
            let item1 = unsafe {
                &*self.array1.as_ptr().offset(index as isize)
            };
            let item2 = unsafe {
                &*self.array2.as_ptr().offset(index as isize)
            };
            Some((item1, item2))
        }
    }

    pub fn array1(&self) -> &[A1::Item] {
        unsafe {
            let ptr = self.array1.as_ptr();
            let len = self.len.as_usize();
            slice::from_raw_parts(ptr, len)
        }
    }

    pub fn array2(&self) -> &[A2::Item] {
        unsafe {
            let ptr = self.array2.as_ptr();
            let len = self.len.as_usize();
            slice::from_raw_parts(ptr, len)
        }
    }

    pub fn array1_mut(&mut self) -> &mut [A1::Item] {
        unsafe {
            let ptr = self.array1.as_mut_ptr();
            let len = self.len.as_usize();
            slice::from_raw_parts_mut(ptr, len)
        }
    }

    pub fn array2_mut(&mut self) -> &mut [A2::Item] {
        unsafe {
            let ptr = self.array2.as_mut_ptr();
            let len = self.len.as_usize();
            slice::from_raw_parts_mut(ptr, len)
        }
    }

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

impl<A1, A2> Default for LockstepArray<A1, A2> where A1: Array, A2: Array {
    fn default() -> Self {
        Self::new()
    }
}

impl<A1, A2> IntoIterator for LockstepArray<A1, A2> where A1: Array, A2: Array {
    type Item = (A1::Item, A2::Item);
    type IntoIter = IntoIter<A1, A2>;
    fn into_iter(self) -> Self::IntoIter {
        let LockstepArray { len, array1, array2 } = self;
        IntoIter {
            len: len.as_usize(),
            array1: array1,
            array2: array2,
            pos: 0
        }
    }
}

pub struct IntoIter<A1: Array, A2: Array> {
    len: usize,
    array1: NoDrop<A1>,
    array2: NoDrop<A2>,
    pos: usize
}

impl<A1: Array, A2: Array> Iterator for IntoIter<A1, A2> {
    type Item = (A1::Item, A2::Item);
    fn next(&mut self) -> Option<Self::Item> {
        if self.pos == self.len {
            None
        } else {
            unsafe {
                let ptr1 = self.array1.as_mut_ptr().offset(self.pos as isize);
                let item1 = ptr::read(ptr1);
                let ptr2 = self.array2.as_mut_ptr().offset(self.pos as isize);
                let item2 = ptr::read(ptr2);
                self.pos += 1;
                Some((item1, item2))
            }
        }
    }
}

#[test]
fn test_into_iter() {
    let mut locksteparray = LockstepArray::<[u8; 7], [u8; 7]>::new();
    locksteparray.insert(0, 4, 5).unwrap();
    locksteparray.insert(1, 3, 4).unwrap();
    let mut iter = locksteparray.into_iter();
    assert_eq!(iter.next(), Some((4, 5)));
    assert_eq!(iter.next(), Some((3, 4)));
    assert_eq!(iter.next(), None);
}
<|endoftext|>