<commit_before>use std::ops::{Deref, DerefMut};

trait Graph {
	type R: PartialOrd<u32>;
	fn graph_fn(&self) -> &Self::R ;
}
trait GraphMut: Graph {
	fn graph_mut(&mut self) -> &mut Self::R;
}
trait GraphMut2: Graph {
	fn graph_mut2(&mut self) -> &mut Self::R;
}

trait BaseConstraint: Sized {
	type Graph: Graph;
	fn get_graph(&self) -> &Self::Graph;
	fn constrain<G>(self) -> Result<G, ()>
		where G: Constraint<Base=Self>
	{
		G::constrain(self)
	}
}
trait BaseConstraintMut: BaseConstraint {
	fn get_graph_mut(&mut self) -> &mut Self::Graph;
}
trait Constraint: Sized {
	type Base:  BaseConstraint;
	type Constrained: Constraint<Base=Self::Base>;

	fn base_single(&self) -> &Self::Constrained;
	fn unconstrain_single(self) -> Self::Constrained;
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()>;

	fn unconstrain(self) -> Self::Base{
		self.unconstrain_single().unconstrain()
	}
	fn constrain(g: Self::Base) -> Result<Self, ()>{
		Self::constrain_single(Self::Constrained::constrain(g)?)
	}
	fn base(&self) -> &<Self::Base as BaseConstraint>::Graph {
		self.base_single().base()
	}

}
trait ConstraintMut: Constraint<Base=<Self as ConstraintMut>::BaseMut, Constrained=<Self as ConstraintMut>::ConstrainedMut> {
	type BaseMut:  BaseConstraintMut;
	type ConstrainedMut: ConstraintMut<BaseMut=Self::BaseMut>;

	fn base_single_mut(&mut self) -> &mut Self::ConstrainedMut;
	fn base_mut(&mut self) -> &mut <Self::BaseMut as BaseConstraint>::Graph
	{
		self.base_single_mut().base_mut()
	}
}

impl<G: Graph, D: Deref<Target=G>> BaseConstraint for D {
	type Graph = G;
	fn get_graph(&self) -> &Self::Graph {&**self}
}
impl<G: GraphMut, D: DerefMut<Target=G>> BaseConstraintMut for D {
	fn get_graph_mut(&mut self) -> &mut Self::Graph {&mut **self}
}
impl<B: BaseConstraint> Constraint for B {
	type Base = Self;
	type Constrained = Self;

	fn base_single(&self) -> &Self::Constrained { &self }
	fn unconstrain_single(self) -> Self::Constrained { self }
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()> { Ok(g)}

	fn unconstrain(self) -> Self::Base { self }
	fn constrain(g: Self::Base) -> Result<Self, ()>{ Ok(g) }
	fn base(&self) -> &<Self::Base as BaseConstraint>::Graph { self.get_graph() }
}
impl<B: BaseConstraintMut> ConstraintMut for B {
	type BaseMut = Self;
	type ConstrainedMut = Self;
	fn base_single_mut(&mut self) -> &mut Self::ConstrainedMut { self }
	fn base_mut(&mut self) -> &mut <Self::BaseMut as BaseConstraint>::Graph {
		self.get_graph_mut()
	}
}

struct BaseGraph(u32);
impl BaseGraph {
	fn base_graph_fn(&self) -> u32
	{
		self.0
	}
}
impl Graph for BaseGraph{
	type R = u32;
	fn graph_fn(&self) -> &u32 {
		&self.0
	}
}
impl GraphMut for BaseGraph {
	fn graph_mut(&mut self) -> &mut u32 { &mut self.0 }
}
impl GraphMut2 for BaseGraph {
	fn graph_mut2(&mut self) -> &mut u32 { &mut self.0 }
}
impl BaseConstraint for BaseGraph {
	type Graph = Self;
	fn get_graph(&self) -> &Self::Graph {self}
}
impl BaseConstraintMut for BaseGraph{
	fn get_graph_mut(&mut self) -> &mut Self::Graph {self}
}

struct Connected<C: Constraint>(C);
impl<C: Constraint> Constraint for Connected<C> {
	type Base = C::Base;
	type Constrained = C;

	fn base_single(&self) -> &Self::Constrained { &self.0 }
	fn unconstrain_single(self) -> Self::Constrained { self.0 }
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()> {
		if g.base().graph_fn() < &32 {
			Ok(Self(g))
		} else {
			Err(())
		}

	}
}
impl<C: ConstraintMut> ConstraintMut for Connected<C> {
	type BaseMut = C::BaseMut;
	type ConstrainedMut = C;

	fn base_single_mut(&mut self) -> &mut Self::Constrained { &mut self.0 }
}

impl<C: Constraint> Connected<C> {
	fn connected_fn(&self) -> &<<C::Base as BaseConstraint>::Graph as Graph>::R
	{
		self.base().graph_fn()
	}
}
impl<C: Constraint> Graph for Connected<C>{
	type R = <<C::Base as BaseConstraint>::Graph as Graph>::R;
	fn graph_fn(&self) -> &Self::R {
		self.base().graph_fn()
	}
}
impl<C: ConstraintMut> GraphMut for Connected<C>
	where <C::Base as BaseConstraint>::Graph: GraphMut {
	fn graph_mut(&mut self) -> &mut <<C::Base as BaseConstraint>::Graph as Graph>::R
	{
		self.0.base_mut().graph_mut()
	}
}
impl<C: ConstraintMut> GraphMut2 for Connected<C>
	where <C::Base as BaseConstraint>::Graph: GraphMut2 {
	fn graph_mut2(&mut self) -> &mut <<C::Base as BaseConstraint>::Graph as Graph>::R { self.0.base_mut().graph_mut2() }
}

#[test]
fn constrainer_constraining_base(){
	type ConstrainedGraphRef<'a> =
	Connected<
		Connected<
			&'a BaseGraph
		>>;

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), &16);

	let c_ref = ConstrainedGraphRef::constrain(&g).unwrap();
	assert_eq!(c_ref.connected_fn(), &16);

	type ConstrainedGraphMut<'a> =
	Connected<
		Connected<
			&'a mut BaseGraph
		>>;

	let mut c_ref_mut = ConstrainedGraphMut::constrain(&mut g).unwrap();
	*c_ref_mut.graph_mut() = 30;
	*c_ref_mut.graph_mut2() = 30;
	assert_eq!(c_ref_mut.connected_fn(), &30);

	type ConstrainedGraph<'a> =
	Connected<
		Connected<
			BaseGraph
		>>;

	let c_owned = ConstrainedGraph::constrain(g).unwrap();
	assert_eq!(c_owned.connected_fn(), &30);

}

#[test]
fn inline_constrainer_constraining_base(){

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), &16);

	let c_ref = <Connected<Connected<&BaseGraph>>>::constrain(&g).unwrap();
	assert_eq!(c_ref.connected_fn(), &16);

	let mut c_ref_mut = <Connected<Connected<&mut BaseGraph>>>::constrain(&mut g).unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), &30);

	let c_owned = <Connected<Connected<BaseGraph>>>::constrain(g).unwrap();
	assert_eq!(c_owned.connected_fn(), &30);

}

#[test]
fn base_constrains_self_by_constraint_inference(){
	type ConstrainedGraph<G> = Connected< Connected< Connected<G> > >;

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), &16);

	let c_ref: ConstrainedGraph<&BaseGraph> = (&g).constrain().unwrap();
	assert_eq!(c_ref.connected_fn(), &16);
	let c_ref_unc = c_ref.unconstrain_single();
	assert_eq!(c_ref_unc.connected_fn(), &16);

	let mut c_ref_mut: ConstrainedGraph<&mut BaseGraph> = (&mut g).constrain().unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), &30);
	let mut c_ref_mut_unc = c_ref_mut.unconstrain_single();
	assert_eq!(c_ref_mut_unc.connected_fn(), &30);
	*c_ref_mut_unc.graph_mut() = 31;
	assert_eq!(c_ref_mut_unc.connected_fn(), &31);

	let c_owned: ConstrainedGraph<BaseGraph> = g.constrain().unwrap();
	assert_eq!(c_owned.connected_fn(), &31);
	let c_owned_unc = c_owned.unconstrain_single();
	assert_eq!(c_owned_unc.connected_fn(), &31);
	let g2 = c_owned_unc.unconstrain();
	assert_eq!(g2.base_graph_fn(), 31);
}

#[test]
fn base_constrains_self_by_inline_constraint_inference(){

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn(), &16);

	let c_ref: Connected<Connected<Connected<&BaseGraph>>> = (&g).constrain().unwrap();
	assert_eq!(c_ref.connected_fn(), &16);
	let c_ref_unc = c_ref.unconstrain_single();
	assert_eq!(c_ref_unc.connected_fn(), &16);

	let mut c_ref_mut: Connected<Connected<Connected<&mut BaseGraph>>> = (&mut g).constrain().unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), &30);
	let mut c_ref_mut_unc = c_ref_mut.unconstrain_single();
	assert_eq!(c_ref_mut_unc.connected_fn(), &30);
	*c_ref_mut_unc.graph_mut() = 31;
	assert_eq!(c_ref_mut_unc.connected_fn(), &31);

	let c_owned: Connected<Connected<Connected<BaseGraph>>> = g.constrain().unwrap();
	assert_eq!(c_owned.connected_fn(), &31);
	let c_owned_unc = c_owned.unconstrain_single();
	assert_eq!(c_owned_unc.connected_fn(), &31);
	let g2 = c_owned_unc.unconstrain();
	assert_eq!(g2.base_graph_fn(), 31);
}<commit_msg>Testing trait method now returns a boxed iterator that references the traits associated type.<commit_after>use std::ops::{Deref, DerefMut};

trait Graph {
	type R: PartialOrd<u32>;
	fn graph_fn<'a>(&'a self) -> Box<dyn 'a + Iterator<Item=&'a Self::R>> ;
}
trait GraphMut: Graph {
	fn graph_mut(&mut self) -> &mut Self::R;
}
trait GraphMut2: Graph {
	fn graph_mut2(&mut self) -> &mut Self::R;
}

trait BaseConstraint: Sized {
	type Graph: Graph;
	fn get_graph(&self) -> &Self::Graph;
	fn constrain<G>(self) -> Result<G, ()>
		where G: Constraint<Base=Self>
	{
		G::constrain(self)
	}
}
trait BaseConstraintMut: BaseConstraint {
	fn get_graph_mut(&mut self) -> &mut Self::Graph;
}
trait Constraint: Sized {
	type Base:  BaseConstraint;
	type Constrained: Constraint<Base=Self::Base>;

	fn base_single(&self) -> &Self::Constrained;
	fn unconstrain_single(self) -> Self::Constrained;
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()>;

	fn unconstrain(self) -> Self::Base{
		self.unconstrain_single().unconstrain()
	}
	fn constrain(g: Self::Base) -> Result<Self, ()>{
		Self::constrain_single(Self::Constrained::constrain(g)?)
	}
	fn base(&self) -> &<Self::Base as BaseConstraint>::Graph {
		self.base_single().base()
	}

}
trait ConstraintMut: Constraint<Base=<Self as ConstraintMut>::BaseMut, Constrained=<Self as ConstraintMut>::ConstrainedMut> {
	type BaseMut:  BaseConstraintMut;
	type ConstrainedMut: ConstraintMut<BaseMut=Self::BaseMut>;

	fn base_single_mut(&mut self) -> &mut Self::ConstrainedMut;
	fn base_mut(&mut self) -> &mut <Self::BaseMut as BaseConstraint>::Graph
	{
		self.base_single_mut().base_mut()
	}
}

impl<G: Graph, D: Deref<Target=G>> BaseConstraint for D {
	type Graph = G;
	fn get_graph(&self) -> &Self::Graph {&**self}
}
impl<G: GraphMut, D: DerefMut<Target=G>> BaseConstraintMut for D {
	fn get_graph_mut(&mut self) -> &mut Self::Graph {&mut **self}
}
impl<B: BaseConstraint> Constraint for B {
	type Base = Self;
	type Constrained = Self;

	fn base_single(&self) -> &Self::Constrained { &self }
	fn unconstrain_single(self) -> Self::Constrained { self }
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()> { Ok(g)}

	fn unconstrain(self) -> Self::Base { self }
	fn constrain(g: Self::Base) -> Result<Self, ()>{ Ok(g) }
	fn base(&self) -> &<Self::Base as BaseConstraint>::Graph { self.get_graph() }
}
impl<B: BaseConstraintMut> ConstraintMut for B {
	type BaseMut = Self;
	type ConstrainedMut = Self;
	fn base_single_mut(&mut self) -> &mut Self::ConstrainedMut { self }
	fn base_mut(&mut self) -> &mut <Self::BaseMut as BaseConstraint>::Graph {
		self.get_graph_mut()
	}
}

struct BaseGraph(u32);
impl BaseGraph {
	fn base_graph_fn(&self) -> u32
	{
		self.0
	}
}
impl Graph for BaseGraph{
	type R = u32;
	fn graph_fn<'a>(&'a self) -> Box<dyn 'a + Iterator<Item=&'a u32>> {
		Box::new(vec![&self.0].into_iter())
	}
}
impl GraphMut for BaseGraph {
	fn graph_mut(&mut self) -> &mut u32 { &mut self.0 }
}
impl GraphMut2 for BaseGraph {
	fn graph_mut2(&mut self) -> &mut u32 { &mut self.0 }
}
impl BaseConstraint for BaseGraph {
	type Graph = Self;
	fn get_graph(&self) -> &Self::Graph {self}
}
impl BaseConstraintMut for BaseGraph{
	fn get_graph_mut(&mut self) -> &mut Self::Graph {self}
}

struct Connected<C: Constraint>(C);
impl<C: Constraint> Constraint for Connected<C> {
	type Base = C::Base;
	type Constrained = C;

	fn base_single(&self) -> &Self::Constrained { &self.0 }
	fn unconstrain_single(self) -> Self::Constrained { self.0 }
	fn constrain_single(g: Self::Constrained) -> Result<Self, ()> {
		if g.base().graph_fn().next().unwrap() < &32 {
			Ok(Self(g))
		} else {
			Err(())
		}

	}
}
impl<C: ConstraintMut> ConstraintMut for Connected<C> {
	type BaseMut = C::BaseMut;
	type ConstrainedMut = C;

	fn base_single_mut(&mut self) -> &mut Self::Constrained { &mut self.0 }
}

impl<C: Constraint> Connected<C> {
	fn connected_fn(&self) -> &<<C::Base as BaseConstraint>::Graph as Graph>::R
	{
		self.base().graph_fn().next().unwrap()
	}
}
impl<C: Constraint> Graph for Connected<C>{
	type R = <<C::Base as BaseConstraint>::Graph as Graph>::R;
	fn graph_fn<'a>(&'a self) -> Box<dyn 'a + Iterator<Item=&'a Self::R>> {
		self.base().graph_fn()
	}
}
impl<C: ConstraintMut> GraphMut for Connected<C>
	where <C::Base as BaseConstraint>::Graph: GraphMut {
	fn graph_mut(&mut self) -> &mut <<C::Base as BaseConstraint>::Graph as Graph>::R
	{
		self.0.base_mut().graph_mut()
	}
}
impl<C: ConstraintMut> GraphMut2 for Connected<C>
	where <C::Base as BaseConstraint>::Graph: GraphMut2 {
	fn graph_mut2(&mut self) -> &mut <<C::Base as BaseConstraint>::Graph as Graph>::R { self.0.base_mut().graph_mut2() }
}

#[test]
fn constrainer_constraining_base(){
	type ConstrainedGraphRef<'a> =
	Connected<
		Connected<
			&'a BaseGraph
		>>;

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn().next().unwrap(), &16);

	let c_ref = ConstrainedGraphRef::constrain(&g).unwrap();
	assert_eq!(c_ref.connected_fn(), &16);

	type ConstrainedGraphMut<'a> =
	Connected<
		Connected<
			&'a mut BaseGraph
		>>;

	let mut c_ref_mut = ConstrainedGraphMut::constrain(&mut g).unwrap();
	*c_ref_mut.graph_mut() = 30;
	*c_ref_mut.graph_mut2() = 30;
	assert_eq!(c_ref_mut.connected_fn(), &30);

	type ConstrainedGraph<'a> =
	Connected<
		Connected<
			BaseGraph
		>>;

	let c_owned = ConstrainedGraph::constrain(g).unwrap();
	assert_eq!(c_owned.connected_fn(), &30);

}

#[test]
fn inline_constrainer_constraining_base(){

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn().next().unwrap(), &16);

	let c_ref = <Connected<Connected<&BaseGraph>>>::constrain(&g).unwrap();
	assert_eq!(c_ref.connected_fn(), &16);

	let mut c_ref_mut = <Connected<Connected<&mut BaseGraph>>>::constrain(&mut g).unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), &30);

	let c_owned = <Connected<Connected<BaseGraph>>>::constrain(g).unwrap();
	assert_eq!(c_owned.connected_fn(), &30);

}

#[test]
fn base_constrains_self_by_constraint_inference(){
	type ConstrainedGraph<G> = Connected< Connected< Connected<G> > >;

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn().next().unwrap(), &16);

	let c_ref: ConstrainedGraph<&BaseGraph> = (&g).constrain().unwrap();
	assert_eq!(c_ref.connected_fn(), &16);
	let c_ref_unc = c_ref.unconstrain_single();
	assert_eq!(c_ref_unc.connected_fn(), &16);

	let mut c_ref_mut: ConstrainedGraph<&mut BaseGraph> = (&mut g).constrain().unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), &30);
	let mut c_ref_mut_unc = c_ref_mut.unconstrain_single();
	assert_eq!(c_ref_mut_unc.connected_fn(), &30);
	*c_ref_mut_unc.graph_mut() = 31;
	assert_eq!(c_ref_mut_unc.connected_fn(), &31);

	let c_owned: ConstrainedGraph<BaseGraph> = g.constrain().unwrap();
	assert_eq!(c_owned.connected_fn(), &31);
	let c_owned_unc = c_owned.unconstrain_single();
	assert_eq!(c_owned_unc.connected_fn(), &31);
	let g2 = c_owned_unc.unconstrain();
	assert_eq!(g2.base_graph_fn(), 31);
}

#[test]
fn base_constrains_self_by_inline_constraint_inference(){

	let mut g = BaseGraph(16);
	assert_eq!(g.graph_fn().next().unwrap(), &16);

	let c_ref: Connected<Connected<Connected<&BaseGraph>>> = (&g).constrain().unwrap();
	assert_eq!(c_ref.connected_fn(), &16);
	let c_ref_unc = c_ref.unconstrain_single();
	assert_eq!(c_ref_unc.connected_fn(), &16);

	let mut c_ref_mut: Connected<Connected<Connected<&mut BaseGraph>>> = (&mut g).constrain().unwrap();
	*c_ref_mut.graph_mut() = 30;
	assert_eq!(c_ref_mut.connected_fn(), &30);
	let mut c_ref_mut_unc = c_ref_mut.unconstrain_single();
	assert_eq!(c_ref_mut_unc.connected_fn(), &30);
	*c_ref_mut_unc.graph_mut() = 31;
	assert_eq!(c_ref_mut_unc.connected_fn(), &31);

	let c_owned: Connected<Connected<Connected<BaseGraph>>> = g.constrain().unwrap();
	assert_eq!(c_owned.connected_fn(), &31);
	let c_owned_unc = c_owned.unconstrain_single();
	assert_eq!(c_owned_unc.connected_fn(), &31);
	let g2 = c_owned_unc.unconstrain();
	assert_eq!(g2.base_graph_fn(), 31);
}<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::mem::size_of;
use webcore::value::{Reference, FromReference};
use webcore::try_from::TryInto;
use webapi::array_buffer::ArrayBuffer;

pub trait ArrayKind: Sized {
    fn is_typed_array( reference: &Reference ) -> bool;
    fn into_typed_array( slice: &[Self] ) -> TypedArray< Self >;
    unsafe fn into_typed_array_no_copy( slice: &[Self] ) -> TypedArray< Self >;
    fn from_typed_array( array: &TypedArray< Self > ) -> Vec< Self >;
}

macro_rules! arraykind {
    ($element_type:ty, $js_array_type:ident, $heap_type:ident, $ptr_type:ty) => {
        impl ArrayKind for $element_type {
            fn is_typed_array( reference: &Reference ) -> bool {
                instanceof!( *reference, $js_array_type )
            }

            fn into_typed_array( slice: &[Self] ) -> TypedArray< Self > {
                let slice_ptr = (slice.as_ptr() as usize / size_of::<$element_type>()) as $ptr_type;
                let raw = __js_raw_asm!(
                    concat!(
                        "return Module.STDWEB.acquire_rust_reference( ",
                        stringify!($heap_type),
                        ".slice( $0, $1 ) );"
                    ),
                    slice_ptr,
                    (slice_ptr + slice.len() as $ptr_type)
                );

                let reference = unsafe {
                    Reference::from_raw_unchecked( raw )
                };

                TypedArray::from_reference( reference ).unwrap()
            }

            // This is unsafe due to the erasure of the slice's lifetime.
            unsafe fn into_typed_array_no_copy( slice: &[Self] ) -> TypedArray< Self > {
                let slice_ptr = (slice.as_ptr() as usize / size_of::<$element_type>()) as $ptr_type;
                let raw = __js_raw_asm!(
                    concat!(
                        "return Module.STDWEB.acquire_rust_reference( new $0( ",
                        stringify!($heap_type),
                        ".buffer, $1, $2 ) );"
                    ),
                    stringify!($js_array_type),
                    slice_ptr,
                    slice.len() as $ptr_type
                );

                let reference = Reference::from_raw_unchecked( raw );
                TypedArray::from_reference( reference ).unwrap()
            }

            fn from_typed_array( array: &TypedArray< Self > ) -> Vec< Self > {
                let length = array.len();
                let mut vector = Vec::with_capacity( length );
                let vec_ptr = (vector.as_ptr() as usize / size_of::<$element_type>()) as $ptr_type;

                js!( @(no_return)
                    var array = @{array};
                    var pointer = @{vec_ptr};
                    $heap_type.set( array, pointer );
                );

                unsafe {
                    vector.set_len( length );
                }

                vector
            }
        }

        impl From< TypedArray< $element_type > > for Vec< $element_type > {
            fn from( array: TypedArray< $element_type > ) -> Self {
                <$element_type>::from_typed_array( &array )
            }
        }

        impl< 'a > From< &'a TypedArray< $element_type > > for Vec< $element_type > {
            fn from( array: &'a TypedArray< $element_type > ) -> Self {
                <$element_type>::from_typed_array( array )
            }
        }
    }
}

arraykind!(i8, Int8Array, HEAP8, i32);
arraykind!(u8, Uint8Array, HEAPU8, i32);
arraykind!(i16, Int16Array, HEAP16, i32);
arraykind!(u16, Uint16Array, HEAPU16, i32);
arraykind!(i32, Int32Array, HEAP32, i32);
arraykind!(u32, Uint32Array, HEAPU32, i32);
arraykind!(f32, Float32Array, HEAPF32, i32);
arraykind!(f64, Float64Array, HEAPF64, i32);

/// JavaScript typed arrays are array-like objects and provide a mechanism for accessing raw binary data.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays)
pub struct TypedArray< T: ArrayKind >( Reference, PhantomData< T > );

reference_boilerplate! {
    impl< T > for TypedArray< T > where (T: ArrayKind)
}

impl< T: ArrayKind > FromReference for TypedArray< T > {
    #[inline]
    fn from_reference( reference: Reference ) -> Option< Self > {
        if T::is_typed_array( &reference ) {
            Some( TypedArray( reference, PhantomData ) )
        } else {
            None
        }
    }
}

impl< T: ArrayKind > TypedArray< T > {
    /// Returns the [TypedArray](struct.ArrayBuffer.html) referenced by this typed array.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/buffer)
    pub fn buffer( &self ) -> ArrayBuffer {
        js!( return @{self}.buffer; ).try_into().unwrap()
    }

    /// Returns the number of elements in the buffer.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/length)
    pub fn len( &self ) -> usize {
        let reference = self.as_ref();
        let length: i32 = js!( return @{reference}.length; ).try_into().unwrap();
        length as usize
    }

    /// Copies `self` into a new `Vec`.
    pub fn to_vec( &self ) -> Vec< T > {
        T::from_typed_array( self )
    }
}

impl< 'a, T: ArrayKind > From< &'a [T] > for TypedArray< T > {
    fn from( slice: &'a [T] ) -> Self {
        T::into_typed_array( slice )
    }
}

#[cfg(test)]
mod tests {
    macro_rules! arraykind_test {
        ($element_type: ident, $js_array_type: ident) => {
            mod $element_type {
                use super::super::TypedArray;
                use std;
                use webcore::try_from::TryInto;
                use webcore::value::Value;
                const ARRAY: &[$element_type] = &[
                    std::$element_type::MIN,
                    std::$element_type::MAX
                ];

                #[test]
                fn into() {
                    let typed_array: TypedArray< $element_type > = ARRAY.into();
                    assert_eq!(
                        js!( return @{&typed_array} instanceof $js_array_type; ),
                        Value::Bool( true )
                    );
                    assert_eq!(
                        js!( return @{&typed_array}.length === @{ARRAY.len() as u32}; ),
                        Value::Bool( true )
                    );
                    assert_eq!(
                        js!( return @{&typed_array}[0] === @{ARRAY[0]}; ),
                        Value::Bool( true )
                    );
                    assert_eq!(
                        js!( return @{&typed_array}[1] === @{ARRAY[1]}; ),
                        Value::Bool( true )
                    );
                }

                #[test]
                fn from() {
                    let value = js!( return new $js_array_type( [@{ARRAY[0]}, @{ARRAY[1]}] ); );
                    let typed_array: TypedArray< $element_type > = value.try_into().unwrap();
                    let vec: Vec< $element_type > = typed_array.into();
                    assert_eq!( vec.len(), ARRAY.len() );
                    assert_eq!( vec, ARRAY);
                }
            }
        }
    }

    arraykind_test!(i8, Int8Array);
    arraykind_test!(u8, Uint8Array);
    arraykind_test!(i16, Int16Array);
    arraykind_test!(u16, Uint16Array);
    arraykind_test!(i32, Int32Array);
    arraykind_test!(u32, Uint32Array);
    arraykind_test!(f32, Float32Array);
    arraykind_test!(f64, Float64Array);
}
<commit_msg>Slight cleanups in `typed_array.rs`<commit_after>use std::marker::PhantomData;
use std::mem::size_of;
use webcore::value::{Reference, FromReference};
use webcore::try_from::TryInto;
use webapi::array_buffer::ArrayBuffer;

pub trait ArrayKind: Sized {
    fn is_typed_array( reference: &Reference ) -> bool;
    fn into_typed_array( slice: &[Self] ) -> TypedArray< Self >;
    fn from_typed_array( array: &TypedArray< Self > ) -> Vec< Self >;
}

macro_rules! arraykind {
    ($element_type:ty, $js_array_type:ident, $heap_type:ident) => {
        impl ArrayKind for $element_type {
            fn is_typed_array( reference: &Reference ) -> bool {
                instanceof!( *reference, $js_array_type )
            }

            fn into_typed_array( slice: &[Self] ) -> TypedArray< Self > {
                let slice_ptr = (slice.as_ptr() as usize / size_of::<$element_type>()) as i32;
                let raw = __js_raw_asm!(
                    concat!(
                        "return Module.STDWEB.acquire_rust_reference( ",
                        stringify!($heap_type),
                        ".slice( $0, $1 ) );"
                    ),
                    slice_ptr,
                    (slice_ptr + slice.len() as i32)
                );

                let reference = unsafe {
                    Reference::from_raw_unchecked( raw )
                };

                TypedArray::from_reference( reference ).unwrap()
            }

            fn from_typed_array( array: &TypedArray< Self > ) -> Vec< Self > {
                let length = array.len();
                let mut vector = Vec::with_capacity( length );
                let vec_ptr = (vector.as_ptr() as usize / size_of::<$element_type>()) as i32;

                js!( @(no_return)
                    var array = @{array};
                    var pointer = @{vec_ptr};
                    $heap_type.set( array, pointer );
                );

                unsafe {
                    vector.set_len( length );
                }

                vector
            }
        }

        impl From< TypedArray< $element_type > > for Vec< $element_type > {
            fn from( array: TypedArray< $element_type > ) -> Self {
                <$element_type>::from_typed_array( &array )
            }
        }

        impl< 'a > From< &'a TypedArray< $element_type > > for Vec< $element_type > {
            fn from( array: &'a TypedArray< $element_type > ) -> Self {
                <$element_type>::from_typed_array( array )
            }
        }
    }
}

arraykind!( i8, Int8Array, HEAP8 );
arraykind!( u8, Uint8Array, HEAPU8 );
arraykind!( i16, Int16Array, HEAP16 );
arraykind!( u16, Uint16Array, HEAPU16 );
arraykind!( i32, Int32Array, HEAP32 );
arraykind!( u32, Uint32Array, HEAPU32 );
arraykind!( f32, Float32Array, HEAPF32 );
arraykind!( f64, Float64Array, HEAPF64 );

/// JavaScript typed arrays are array-like objects and provide a mechanism for accessing raw binary data.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays)
pub struct TypedArray< T: ArrayKind >( Reference, PhantomData< T > );

reference_boilerplate! {
    impl< T > for TypedArray< T > where (T: ArrayKind)
}

impl< T: ArrayKind > FromReference for TypedArray< T > {
    #[inline]
    fn from_reference( reference: Reference ) -> Option< Self > {
        if T::is_typed_array( &reference ) {
            Some( TypedArray( reference, PhantomData ) )
        } else {
            None
        }
    }
}

impl< T: ArrayKind > TypedArray< T > {
    /// Returns the [TypedArray](struct.ArrayBuffer.html) referenced by this typed array.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/buffer)
    pub fn buffer( &self ) -> ArrayBuffer {
        js!( return @{self}.buffer; ).try_into().unwrap()
    }

    /// Returns the number of elements in the buffer.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/length)
    pub fn len( &self ) -> usize {
        let reference = self.as_ref();
        let length: i32 = js!( return @{reference}.length; ).try_into().unwrap();
        length as usize
    }

    /// Copies `self` into a new `Vec`.
    pub fn to_vec( &self ) -> Vec< T > {
        T::from_typed_array( self )
    }
}

impl< 'a, T: ArrayKind > From< &'a [T] > for TypedArray< T > {
    fn from( slice: &'a [T] ) -> Self {
        T::into_typed_array( slice )
    }
}

#[cfg(test)]
mod tests {
    macro_rules! arraykind_test {
        ($element_type: ident, $js_array_type: ident) => {
            mod $element_type {
                use super::super::TypedArray;
                use std;
                use webcore::try_from::TryInto;
                use webcore::value::Value;
                const ARRAY: &[$element_type] = &[
                    std::$element_type::MIN,
                    std::$element_type::MAX
                ];

                #[test]
                fn into() {
                    let typed_array: TypedArray< $element_type > = ARRAY.into();
                    assert_eq!(
                        js!( return @{&typed_array} instanceof $js_array_type; ),
                        Value::Bool( true )
                    );
                    assert_eq!(
                        js!( return @{&typed_array}.length === @{ARRAY.len() as u32}; ),
                        Value::Bool( true )
                    );
                    assert_eq!(
                        js!( return @{&typed_array}[0] === @{ARRAY[0]}; ),
                        Value::Bool( true )
                    );
                    assert_eq!(
                        js!( return @{&typed_array}[1] === @{ARRAY[1]}; ),
                        Value::Bool( true )
                    );
                }

                #[test]
                fn from() {
                    let value = js!( return new $js_array_type( [@{ARRAY[0]}, @{ARRAY[1]}] ); );
                    let typed_array: TypedArray< $element_type > = value.try_into().unwrap();
                    let vec: Vec< $element_type > = typed_array.into();
                    assert_eq!( vec.len(), ARRAY.len() );
                    assert_eq!( vec, ARRAY);
                }
            }
        }
    }

    arraykind_test!(i8, Int8Array);
    arraykind_test!(u8, Uint8Array);
    arraykind_test!(i16, Int16Array);
    arraykind_test!(u16, Uint16Array);
    arraykind_test!(i32, Int32Array);
    arraykind_test!(u32, Uint32Array);
    arraykind_test!(f32, Float32Array);
    arraykind_test!(f64, Float64Array);
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{convert::TryInto, fs::File, io::Write, path::PathBuf};

use assert_cmd::Command;
use tempdir::TempDir;

static MAIN_RS: &str = include_str!("../../../demo/src/main.rs");
static INPUT_H: &str = include_str!("../../../demo/src/input.h");

#[test]
fn test_help() -> Result<(), Box<dyn std::error::Error>> {
    let mut cmd = Command::cargo_bin("autocxx-gen")?;
    cmd.arg("-h").assert().success();
    Ok(())
}

#[test]
fn test_gen() -> Result<(), Box<dyn std::error::Error>> {
    let tmp_dir = TempDir::new("example")?;
    let demo_code_dir = tmp_dir.path().join("demo");
    std::fs::create_dir(&demo_code_dir).unwrap();
    write_to_file(&demo_code_dir, "input.h", INPUT_H.as_bytes());
    write_to_file(&demo_code_dir, "main.rs", MAIN_RS.as_bytes());
    let demo_rs = demo_code_dir.join("main.rs");
    let mut cmd = Command::cargo_bin("autocxx-gen")?;
    cmd.arg("--inc")
        .arg(demo_code_dir.to_str().unwrap())
        .arg(demo_rs)
        .arg("--outdir")
        .arg(tmp_dir.path().to_str().unwrap())
        .arg("--gen-cpp")
        .arg("--gen-rs-include")
        .assert()
        .success();
    assert_contentful(&tmp_dir, "gen0.cc");
    Ok(())
}

#[test]
fn test_gen_fixed_num() -> Result<(), Box<dyn std::error::Error>> {
    let tmp_dir = TempDir::new("example")?;
    let demo_code_dir = tmp_dir.path().join("demo");
    std::fs::create_dir(&demo_code_dir).unwrap();
    write_to_file(&demo_code_dir, "input.h", INPUT_H.as_bytes());
    write_to_file(&demo_code_dir, "main.rs", MAIN_RS.as_bytes());
    let demo_rs = demo_code_dir.join("main.rs");
    let mut cmd = Command::cargo_bin("autocxx-gen")?;
    cmd.arg("-I")
        .arg(demo_code_dir.to_str().unwrap())
        .arg(demo_rs)
        .arg("--outdir")
        .arg(tmp_dir.path().to_str().unwrap())
        .arg("--gen-cpp")
        .arg("--gen-rs-include")
        .arg("--generate-exact")
        .arg("3")
        .arg("--fix-rs-include-name")
        .assert()
        .success();
    assert_contentful(&tmp_dir, "gen0.cc");
    assert_contentful(&tmp_dir, "gen1.cc");
    assert_exists(&tmp_dir, "gen2.cc");
    assert_contentful(&tmp_dir, "gen0.include.rs");
    assert_exists(&tmp_dir, "gen1.include.rs");
    assert_exists(&tmp_dir, "gen2.include.rs");
    Ok(())
}

fn write_to_file(dir: &PathBuf, filename: &str, content: &[u8]) {
    let path = dir.join(filename);
    let mut f = File::create(&path).expect("Unable to create file");
    f.write_all(content).expect("Unable to write file");
}

fn assert_contentful(outdir: &TempDir, fname: &str) {
    let p = outdir.path().join(fname);
    if !p.exists() {
        panic!("File {} didn't exist", p.to_string_lossy());
    }
    assert!(p.metadata().unwrap().len() > super::BLANK.len().try_into().unwrap());
}

fn assert_exists(outdir: &TempDir, fname: &str) {
    let p = outdir.path().join(fname);
    if !p.exists() {
        panic!("File {} didn't exist", p.to_string_lossy());
    }
}
<commit_msg>Test fix.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{convert::TryInto, fs::File, io::Write, path::PathBuf};

use assert_cmd::Command;
use tempdir::TempDir;

static MAIN_RS: &str = include_str!("../../../demo/src/main.rs");
static INPUT_H: &str = include_str!("../../../demo/src/input.h");

#[test]
fn test_help() -> Result<(), Box<dyn std::error::Error>> {
    let mut cmd = Command::cargo_bin("autocxx-gen")?;
    cmd.arg("-h").assert().success();
    Ok(())
}

#[test]
fn test_gen() -> Result<(), Box<dyn std::error::Error>> {
    let tmp_dir = TempDir::new("example")?;
    let demo_code_dir = tmp_dir.path().join("demo");
    std::fs::create_dir(&demo_code_dir).unwrap();
    write_to_file(&demo_code_dir, "input.h", INPUT_H.as_bytes());
    write_to_file(&demo_code_dir, "main.rs", MAIN_RS.as_bytes());
    let demo_rs = demo_code_dir.join("main.rs");
    let mut cmd = Command::cargo_bin("autocxx-gen")?;
    cmd.arg("--inc")
        .arg(demo_code_dir.to_str().unwrap())
        .arg(demo_rs)
        .arg("--outdir")
        .arg(tmp_dir.path().to_str().unwrap())
        .arg("--gen-cpp")
        .arg("--gen-rs-include")
        .assert()
        .success();
    assert_contentful(&tmp_dir, "gen0.cc");
    Ok(())
}

#[test]
fn test_gen_fixed_num() -> Result<(), Box<dyn std::error::Error>> {
    let tmp_dir = TempDir::new("example")?;
    let demo_code_dir = tmp_dir.path().join("demo");
    std::fs::create_dir(&demo_code_dir).unwrap();
    write_to_file(&demo_code_dir, "input.h", INPUT_H.as_bytes());
    write_to_file(&demo_code_dir, "main.rs", MAIN_RS.as_bytes());
    let demo_rs = demo_code_dir.join("main.rs");
    let mut cmd = Command::cargo_bin("autocxx-gen")?;
    cmd.arg("-I")
        .arg(demo_code_dir.to_str().unwrap())
        .arg(demo_rs)
        .arg("--outdir")
        .arg(tmp_dir.path().to_str().unwrap())
        .arg("--gen-cpp")
        .arg("--gen-rs-include")
        .arg("--generate-exact")
        .arg("3")
        .arg("--fix-rs-include-name")
        .assert()
        .success();
    assert_contentful(&tmp_dir, "gen0.cc");
    assert_exists(&tmp_dir, "gen1.cc");
    assert_exists(&tmp_dir, "gen2.cc");
    assert_contentful(&tmp_dir, "gen0.include.rs");
    assert_exists(&tmp_dir, "gen1.include.rs");
    assert_exists(&tmp_dir, "gen2.include.rs");
    Ok(())
}

fn write_to_file(dir: &PathBuf, filename: &str, content: &[u8]) {
    let path = dir.join(filename);
    let mut f = File::create(&path).expect("Unable to create file");
    f.write_all(content).expect("Unable to write file");
}

fn assert_contentful(outdir: &TempDir, fname: &str) {
    let p = outdir.path().join(fname);
    if !p.exists() {
        panic!("File {} didn't exist", p.to_string_lossy());
    }
    assert!(p.metadata().unwrap().len() > super::BLANK.len().try_into().unwrap());
}

fn assert_exists(outdir: &TempDir, fname: &str) {
    let p = outdir.path().join(fname);
    if !p.exists() {
        panic!("File {} didn't exist", p.to_string_lossy());
    }
}
<|endoftext|>


<commit_before>use std::ptr;

struct TssContext { handle: u32 }
struct TssTpm<'context> { context: &'context TssContext, handle: u32 }

type TssHContext = u32;
type TssHTPM = u32;
type TssResult = u32;
type TssUnicode = u16;

const TSS_SUCCESS: TssResult = 0;

#[link(name = "tspi")]
extern {
    fn Tspi_Context_Create(phContext: *mut TssHContext) -> TssResult;
    fn Tspi_Context_Connect(phContext: TssHContext, wszDestination: *const TssUnicode) -> TssResult;
    fn Tspi_Context_GetTpmObject(phContext: TssHContext, phTPM: *mut TssHTPM) -> TssResult;
    fn Tspi_Context_FreeMemory(phContext: TssHContext, rgbMemory: *mut u8) -> TssResult;
    fn Tspi_Context_Close(phContext: TssHContext) -> TssResult;
    fn Tspi_TPM_PcrRead(hTPM: TssHTPM, ulPcrIndex: u32, pulPcrValueLength: *mut u32, prgbPcrValue: *mut *mut u8) -> TssResult;
}

impl TssContext {
    fn new() -> Result<TssContext, TssResult> {
        let mut handle = 0;
        let result = unsafe {
            Tspi_Context_Create(&mut handle)
        };
        if result != TSS_SUCCESS {
            Err(result)
        } else {
            Ok(TssContext { handle: handle })
        }
    }

    // TODO: support destination
    fn connect(&self) -> Result<(), TssResult> {
        let result = unsafe {
            Tspi_Context_Connect(self.handle, ptr::null())
        };
        if result != TSS_SUCCESS {
            Err(result)
        } else {
            Ok(())
        }
    }

    fn get_tpm_object(&self) -> Result<TssTpm, TssResult> {
        let mut handle = 0;
        let result = unsafe {
            Tspi_Context_GetTpmObject(self.handle, &mut handle)
        };
        if result != TSS_SUCCESS {
            Err(result)
        } else {
            Ok(TssTpm { context: self, handle: handle })
        }
    }
}

impl Drop for TssContext {
    fn drop(&mut self) {
        unsafe {
            Tspi_Context_FreeMemory(self.handle, 0 as *mut u8);
            Tspi_Context_Close(self.handle);
        }
    }
}

impl<'context> TssTpm<'context> {
    fn pcr_read(&self, pcr_index: u32) -> Result<Vec<u8>, TssResult> {
        let mut ulPcrValueLength = -1;
        let mut pRgbPcrValue = 0 as *mut u8;
        let result = unsafe {
            Tspi_TPM_PcrRead(self.handle, pcr_index, &mut ulPcrValueLength, &mut pRgbPcrValue)
        };
        if result != TSS_SUCCESS {
            Err(result)
        } else {
            let mut vec = Vec::new();
            unsafe {
                for i in 0..ulPcrValueLength {
                    vec.push(*pRgbPcrValue.offset(i as isize));
                }
                Tspi_Context_FreeMemory(self.context.handle, pRgbPcrValue);
            }
            Ok(vec)
        }
    }
}

fn main() {
    // TODO: Any cleaner way to write this?
    let contextresult = TssContext::new();
    if let Ok(context) = contextresult {
        if let Ok(_) = context.connect() {
            if let Ok(tpm) = context.get_tpm_object() {
                println!("I'M IN UR TPM READING UR PCRZ (From Rust!)");
                println!("TPM handle: {:?}", tpm.handle);
                for i in 0..24 {
                    if let Ok(vec) = tpm.pcr_read(i) {
                        print!("PCR {:02}", i);
                        for j in 0..19 {
                            print!(" {:02x}", vec[j]);
                        }
                        print!("\n");
                    }
                }
            } else {
                println!("Failed to get TPM handle :(")
            }
        } else {
            println!("Failed to connect :(");
        }
    } else {
        println!("Failed :(");
    }

    /*
    match blah {
        Ok(context) => println!("Context created! {:?}", context.handle),
        Err(e) => println!("Context failed with err {:?}", e),
    }
    println!("Hello world!");
    */
}
<commit_msg>Return instead of if/else for non TSS_SUCCESS<commit_after>use std::ptr;

struct TssContext { handle: u32 }
struct TssTpm<'context> { context: &'context TssContext, handle: u32 }

type TssHContext = u32;
type TssHTPM = u32;
type TssResult = u32;
type TssUnicode = u16;

const TSS_SUCCESS: TssResult = 0;

#[link(name = "tspi")]
extern {
    fn Tspi_Context_Create(phContext: *mut TssHContext) -> TssResult;
    fn Tspi_Context_Connect(phContext: TssHContext, wszDestination: *const TssUnicode) -> TssResult;
    fn Tspi_Context_GetTpmObject(phContext: TssHContext, phTPM: *mut TssHTPM) -> TssResult;
    fn Tspi_Context_FreeMemory(phContext: TssHContext, rgbMemory: *mut u8) -> TssResult;
    fn Tspi_Context_Close(phContext: TssHContext) -> TssResult;
    fn Tspi_TPM_PcrRead(hTPM: TssHTPM, ulPcrIndex: u32, pulPcrValueLength: *mut u32, prgbPcrValue: *mut *mut u8) -> TssResult;
}

impl TssContext {
    fn new() -> Result<TssContext, TssResult> {
        let mut handle = 0;
        let result = unsafe {
            Tspi_Context_Create(&mut handle)
        };
        if result != TSS_SUCCESS {
            return Err(result);
        }
        Ok(TssContext { handle: handle })
    }

    // TODO: support destination
    fn connect(&self) -> Result<(), TssResult> {
        let result = unsafe {
            Tspi_Context_Connect(self.handle, ptr::null())
        };
        if result != TSS_SUCCESS {
            return Err(result);
        }
        Ok(())
    }

    fn get_tpm_object(&self) -> Result<TssTpm, TssResult> {
        let mut handle = 0;
        let result = unsafe {
            Tspi_Context_GetTpmObject(self.handle, &mut handle)
        };
        if result != TSS_SUCCESS {
            return Err(result);
        }
        Ok(TssTpm { context: self, handle: handle })
    }
}

impl Drop for TssContext {
    fn drop(&mut self) {
        unsafe {
            Tspi_Context_FreeMemory(self.handle, 0 as *mut u8);
            Tspi_Context_Close(self.handle);
        }
    }
}

impl<'context> TssTpm<'context> {
    fn pcr_read(&self, pcr_index: u32) -> Result<Vec<u8>, TssResult> {
        let mut ulPcrValueLength = -1;
        let mut pRgbPcrValue = 0 as *mut u8;
        let result = unsafe {
            Tspi_TPM_PcrRead(self.handle, pcr_index, &mut ulPcrValueLength, &mut pRgbPcrValue)
        };
        if result != TSS_SUCCESS {
            return Err(result);
        }
        let mut vec = Vec::new();
        unsafe {
            for i in 0..ulPcrValueLength {
                vec.push(*pRgbPcrValue.offset(i as isize));
            }
            Tspi_Context_FreeMemory(self.context.handle, pRgbPcrValue);
        }
        Ok(vec)
    }
}

fn main() {
    // TODO: Any cleaner way to write this?
    let contextresult = TssContext::new();
    if let Ok(context) = contextresult {
        if let Ok(_) = context.connect() {
            if let Ok(tpm) = context.get_tpm_object() {
                println!("I'M IN UR TPM READING UR PCRZ (From Rust!)");
                println!("TPM handle: {:?}", tpm.handle);
                for i in 0..24 {
                    if let Ok(vec) = tpm.pcr_read(i) {
                        print!("PCR {:02}", i);
                        for j in 0..19 {
                            print!(" {:02x}", vec[j]);
                        }
                        print!("\n");
                    }
                }
            } else {
                println!("Failed to get TPM handle :(")
            }
        } else {
            println!("Failed to connect :(");
        }
    } else {
        println!("Failed :(");
    }

    /*
    match blah {
        Ok(context) => println!("Context created! {:?}", context.handle),
        Err(e) => println!("Context failed with err {:?}", e),
    }
    println!("Hello world!");
    */
}
<|endoftext|>


<commit_before>// vim: tw=80
use super::*;
use quote::ToTokens;
use syn::parse::{Parse, ParseStream};

fn find_ident_from_path(path: &Path) -> (Ident, PathArguments) {
        if path.segments.len() != 1 {
            compile_error(path.span(),
                "mockall_derive only supports structs defined in the current module");
            return (Ident::new("", path.span()), PathArguments::None);
        }
        let last_seg = path.segments.last().unwrap();
        (last_seg.ident.clone(), last_seg.arguments.clone())
}

/// Performs transformations on the method to make it mockable
fn mockable_method(mut meth: ImplItemMethod, name: &Ident, generics: &Generics)
    -> ImplItemMethod
{
    demutify(&mut meth.sig.inputs);
    deimplify(&mut meth.sig.output);
    if let ReturnType::Type(_, ty) = &mut meth.sig.output {
        deselfify(ty, name, generics);
    }
    meth
}

/// Performs transformations on the method to make it mockable
fn mockable_trait_method(
    meth: &mut TraitItemMethod,
    name: &Ident,
    generics: &Generics)
{
    demutify(&mut meth.sig.inputs);
    deimplify(&mut meth.sig.output);
    if let ReturnType::Type(_, ty) = &mut meth.sig.output {
        deselfify(ty, name, generics);
    }
}

/// Performs transformations on the trait to make it mockable
fn mockable_trait(mut trait_: ItemTrait, name: &Ident, generics: &Generics)
    -> ItemTrait
{
    for item in trait_.items.iter_mut() {
        if let TraitItem::Method(tim) = item {
            mockable_trait_method(tim, name, generics);
        }
    }
    trait_
}

/// Converts a TraitItemMethod into an ImplItemMethod
fn tim2iim(m: syn::TraitItemMethod, vis: &syn::Visibility)
    -> syn::ImplItemMethod
{
    let empty_block = Block {
        brace_token: token::Brace::default(),
        stmts: Vec::new()
    };
    syn::ImplItemMethod{
        attrs: m.attrs,
        vis: vis.clone(),
        defaultness: None,
        sig: m.sig,
        block: empty_block
    }
}

pub(crate) struct MockableStruct {
    pub attrs: Vec<Attribute>,
    pub generics: Generics,
    /// Inherent methods of the mockable struct
    pub methods: Vec<ImplItemMethod>,
    pub name: Ident,
    /// Name of the original struct.
    pub original_name: Ident,
    pub vis: Visibility,
    pub traits: Vec<ItemTrait>
}

impl From<(Attrs, ItemTrait)> for MockableStruct {
    fn from((attrs, item_trait): (Attrs, ItemTrait)) -> MockableStruct {
        let trait_ = attrs.substitute_trait(&item_trait);
        let attrs = trait_.attrs.clone();
        let vis = trait_.vis.clone();
        let name = gen_mock_ident(&trait_.ident);
        let generics = trait_.generics.clone();
        let original_name = trait_.ident.clone();
        let traits = vec![mockable_trait(trait_, &name, &generics)];
        MockableStruct {
            attrs,
            vis,
            name,
            generics,
            methods: Vec::new(),
            original_name,
            traits
        }
    }
}

impl From<ItemImpl> for MockableStruct {
    fn from(item_impl: ItemImpl) -> MockableStruct {
        let (name, original_name) = match *item_impl.self_ty {
            Type::Path(type_path) => {
                let n = find_ident_from_path(&type_path.path).0;
                (gen_mock_ident(&n), n)
            },
            x => {
                compile_error(x.span(),
                    "mockall_derive only supports mocking traits and structs");
                (Ident::new("", Span::call_site()),
                 Ident::new("", Span::call_site()))
            }
        };
        let mut methods = Vec::new();
        let pub_token = Token![pub](Span::call_site());
        let vis = Visibility::Public(VisPublic{pub_token});
        let mut traits = Vec::new();
        if let Some((bang, path, _)) = item_impl.trait_ {
            if bang.is_some() {
                compile_error(bang.span(), "Unsupported by automock");
            }
            assert!(path.segments.last().unwrap().arguments.is_empty(), "TODO");

            // Regenerate the trait that this block is implementing
            let generics = &item_impl.generics;
            let traitname = &path.segments.last().unwrap().ident;
            let mut items = Vec::new();
            let mut attrs = Attrs::default();
            for item in item_impl.items.into_iter() {
                match item {
                    ImplItem::Method(meth) =>
                        items.push(
                            TraitItem::Method(TraitItemMethod {
                                attrs: meth.attrs,
                                sig: meth.sig,
                                default: None,
                                semi_token: Some(Token![;](Span::call_site()))
                            })
                        ),
                    ImplItem::Type(ty) => {
                        attrs.attrs.insert(ty.ident.clone(), ty.ty.clone());
                        items.push(
                            TraitItem::Type(TraitItemType {
                                attrs: ty.attrs,
                                type_token: ty.type_token,
                                ident: ty.ident,
                                generics: ty.generics,
                                colon_token: None,
                                bounds: Punctuated::new(),
                                default: Some((ty.eq_token, ty.ty.clone())),
                                semi_token: ty.semi_token
                            })
                        );
                    },
                    x => compile_error(x.span(), "Unsupported by automock")
                }
            }
            let trait_ = ItemTrait {
                attrs: item_impl.attrs.clone(),
                vis: vis.clone(),
                unsafety: item_impl.unsafety,
                auto_token: None,
                trait_token: Token![trait](Span::call_site()),
                ident: traitname.clone(),
                generics: generics.clone(),
                colon_token: None,
                supertraits: Punctuated::new(),
                brace_token: token::Brace::default(),
                items
            };
            let trait_ = attrs.substitute_trait(&trait_);
            traits.push(mockable_trait(trait_, traitname, &generics));
        } else {
            for item in item_impl.items.into_iter() {
                if let ImplItem::Method(meth) = item {
                    methods.push(
                        mockable_method(meth, &name, &item_impl.generics)
                    );
                }
            }
        };
        MockableStruct {
            attrs: item_impl.attrs,
            name,
            generics: item_impl.generics,
            methods,
            original_name,
            traits,
            vis
        }
    }
}

impl Parse for MockableStruct {
    fn parse(input: ParseStream) -> syn::parse::Result<Self> {
        let attrs = input.call(syn::Attribute::parse_outer)?;
        let vis: syn::Visibility = input.parse()?;
        let original_name: syn::Ident = input.parse()?;
        let mut generics: syn::Generics = input.parse()?;
        let wc: Option<syn::WhereClause> = input.parse()?;
        generics.where_clause = wc;
        let name = gen_mock_ident(&original_name);

        let impl_content;
        let _brace_token = braced!(impl_content in input);
        let mut methods = Vec::new();
        while !impl_content.is_empty() {
            let method: syn::TraitItem = impl_content.parse()?;
            match method {
                syn::TraitItem::Method(mut meth) => {
                    mockable_trait_method(&mut meth, &name, &generics);
                    methods.push(tim2iim(meth, &vis))
                },
                _ => {
                    return Err(input.error("Unsupported in this context"));
                }
            }
        }

        let mut traits = Vec::new();
        while !input.is_empty() {
            let trait_: syn::ItemTrait = input.parse()?;
            traits.push(mockable_trait(trait_, &name, &generics));
        }

        Ok(
            MockableStruct {
                attrs: attrs,
                vis,
                name,
                generics,
                methods,
                original_name,
                traits
            }
        )
    }
}
<commit_msg>Fix automock for generic trait implementations<commit_after>// vim: tw=80
use super::*;
use quote::ToTokens;
use syn::parse::{Parse, ParseStream};

fn find_ident_from_path(path: &Path) -> (Ident, PathArguments) {
        if path.segments.len() != 1 {
            compile_error(path.span(),
                "mockall_derive only supports structs defined in the current module");
            return (Ident::new("", path.span()), PathArguments::None);
        }
        let last_seg = path.segments.last().unwrap();
        (last_seg.ident.clone(), last_seg.arguments.clone())
}

/// Performs transformations on the method to make it mockable
fn mockable_method(mut meth: ImplItemMethod, name: &Ident, generics: &Generics)
    -> ImplItemMethod
{
    demutify(&mut meth.sig.inputs);
    deimplify(&mut meth.sig.output);
    if let ReturnType::Type(_, ty) = &mut meth.sig.output {
        deselfify(ty, name, generics);
    }
    meth
}

/// Performs transformations on the method to make it mockable
fn mockable_trait_method(
    meth: &mut TraitItemMethod,
    name: &Ident,
    generics: &Generics)
{
    demutify(&mut meth.sig.inputs);
    deimplify(&mut meth.sig.output);
    if let ReturnType::Type(_, ty) = &mut meth.sig.output {
        deselfify(ty, name, generics);
    }
}

/// Performs transformations on the trait to make it mockable
fn mockable_trait(mut trait_: ItemTrait, name: &Ident, generics: &Generics)
    -> ItemTrait
{
    for item in trait_.items.iter_mut() {
        if let TraitItem::Method(tim) = item {
            mockable_trait_method(tim, name, generics);
        }
    }
    trait_
}

/// Converts a TraitItemMethod into an ImplItemMethod
fn tim2iim(m: syn::TraitItemMethod, vis: &syn::Visibility)
    -> syn::ImplItemMethod
{
    let empty_block = Block {
        brace_token: token::Brace::default(),
        stmts: Vec::new()
    };
    syn::ImplItemMethod{
        attrs: m.attrs,
        vis: vis.clone(),
        defaultness: None,
        sig: m.sig,
        block: empty_block
    }
}

pub(crate) struct MockableStruct {
    pub attrs: Vec<Attribute>,
    pub generics: Generics,
    /// Inherent methods of the mockable struct
    pub methods: Vec<ImplItemMethod>,
    pub name: Ident,
    /// Name of the original struct.
    pub original_name: Ident,
    pub vis: Visibility,
    pub traits: Vec<ItemTrait>
}

impl From<(Attrs, ItemTrait)> for MockableStruct {
    fn from((attrs, item_trait): (Attrs, ItemTrait)) -> MockableStruct {
        let trait_ = attrs.substitute_trait(&item_trait);
        let attrs = trait_.attrs.clone();
        let vis = trait_.vis.clone();
        let name = gen_mock_ident(&trait_.ident);
        let generics = trait_.generics.clone();
        let original_name = trait_.ident.clone();
        let traits = vec![mockable_trait(trait_, &name, &generics)];
        MockableStruct {
            attrs,
            vis,
            name,
            generics,
            methods: Vec::new(),
            original_name,
            traits
        }
    }
}

impl From<ItemImpl> for MockableStruct {
    fn from(item_impl: ItemImpl) -> MockableStruct {
        let (name, original_name) = match *item_impl.self_ty {
            Type::Path(type_path) => {
                let n = find_ident_from_path(&type_path.path).0;
                (gen_mock_ident(&n), n)
            },
            x => {
                compile_error(x.span(),
                    "mockall_derive only supports mocking traits and structs");
                (Ident::new("", Span::call_site()),
                 Ident::new("", Span::call_site()))
            }
        };
        let mut methods = Vec::new();
        let pub_token = Token![pub](Span::call_site());
        let vis = Visibility::Public(VisPublic{pub_token});
        let mut traits = Vec::new();
        if let Some((bang, path, _)) = item_impl.trait_ {
            if bang.is_some() {
                compile_error(bang.span(), "Unsupported by automock");
            }

            // Regenerate the trait that this block is implementing
            let generics = &item_impl.generics;
            let traitname = &path.segments.last().unwrap().ident;
            let mut items = Vec::new();
            let mut attrs = Attrs::default();
            for item in item_impl.items.into_iter() {
                match item {
                    ImplItem::Method(meth) =>
                        items.push(
                            TraitItem::Method(TraitItemMethod {
                                attrs: meth.attrs,
                                sig: meth.sig,
                                default: None,
                                semi_token: Some(Token![;](Span::call_site()))
                            })
                        ),
                    ImplItem::Type(ty) => {
                        attrs.attrs.insert(ty.ident.clone(), ty.ty.clone());
                        items.push(
                            TraitItem::Type(TraitItemType {
                                attrs: ty.attrs,
                                type_token: ty.type_token,
                                ident: ty.ident,
                                generics: ty.generics,
                                colon_token: None,
                                bounds: Punctuated::new(),
                                default: Some((ty.eq_token, ty.ty.clone())),
                                semi_token: ty.semi_token
                            })
                        );
                    },
                    x => compile_error(x.span(), "Unsupported by automock")
                }
            }
            let trait_ = ItemTrait {
                attrs: item_impl.attrs.clone(),
                vis: vis.clone(),
                unsafety: item_impl.unsafety,
                auto_token: None,
                trait_token: Token![trait](Span::call_site()),
                ident: traitname.clone(),
                generics: generics.clone(),
                colon_token: None,
                supertraits: Punctuated::new(),
                brace_token: token::Brace::default(),
                items
            };
            let trait_ = attrs.substitute_trait(&trait_);
            traits.push(mockable_trait(trait_, traitname, &generics));
        } else {
            for item in item_impl.items.into_iter() {
                if let ImplItem::Method(meth) = item {
                    methods.push(
                        mockable_method(meth, &name, &item_impl.generics)
                    );
                }
            }
        };
        MockableStruct {
            attrs: item_impl.attrs,
            name,
            generics: item_impl.generics,
            methods,
            original_name,
            traits,
            vis
        }
    }
}

impl Parse for MockableStruct {
    fn parse(input: ParseStream) -> syn::parse::Result<Self> {
        let attrs = input.call(syn::Attribute::parse_outer)?;
        let vis: syn::Visibility = input.parse()?;
        let original_name: syn::Ident = input.parse()?;
        let mut generics: syn::Generics = input.parse()?;
        let wc: Option<syn::WhereClause> = input.parse()?;
        generics.where_clause = wc;
        let name = gen_mock_ident(&original_name);

        let impl_content;
        let _brace_token = braced!(impl_content in input);
        let mut methods = Vec::new();
        while !impl_content.is_empty() {
            let method: syn::TraitItem = impl_content.parse()?;
            match method {
                syn::TraitItem::Method(mut meth) => {
                    mockable_trait_method(&mut meth, &name, &generics);
                    methods.push(tim2iim(meth, &vis))
                },
                _ => {
                    return Err(input.error("Unsupported in this context"));
                }
            }
        }

        let mut traits = Vec::new();
        while !input.is_empty() {
            let trait_: syn::ItemTrait = input.parse()?;
            traits.push(mockable_trait(trait_, &name, &generics));
        }

        Ok(
            MockableStruct {
                attrs: attrs,
                vis,
                name,
                generics,
                methods,
                original_name,
                traits
            }
        )
    }
}
<|endoftext|>


<commit_before>extern crate alloc;

use crate::{
	block_current_task, get_priority, getpid, wakeup_task, yield_now, Priority, Tid, NO_PRIORITIES,
};
use alloc::collections::vec_deque::VecDeque;
use core::cell::UnsafeCell;
use core::hint;
use core::ops::{Deref, DerefMut, Drop};
use core::sync::atomic::{AtomicUsize, Ordering};

/// This type provides a lock based on busy waiting to realize mutual exclusion
///
/// # Description
///
/// This structure behaves a lot like a common mutex. There are some differences:
///
/// - By using busy waiting, it can be used outside the runtime.
/// - It is a so called ticket lock and is completely fair.
#[cfg_attr(target_arch = "x86_64", repr(align(128)))]
#[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
struct Spinlock<T: ?Sized> {
	queue: AtomicUsize,
	dequeue: AtomicUsize,
	data: UnsafeCell<T>,
}

unsafe impl<T: ?Sized + Send> Sync for Spinlock<T> {}
unsafe impl<T: ?Sized + Send> Send for Spinlock<T> {}

/// A guard to which the protected data can be accessed
///
/// When the guard falls out of scope it will release the lock.
struct SpinlockGuard<'a, T: ?Sized + 'a> {
	dequeue: &'a AtomicUsize,
	data: &'a mut T,
}

impl<T> Spinlock<T> {
	pub const fn new(user_data: T) -> Spinlock<T> {
		Spinlock {
			queue: AtomicUsize::new(0),
			dequeue: AtomicUsize::new(1),
			data: UnsafeCell::new(user_data),
		}
	}

	#[inline]
	fn obtain_lock(&self) {
		let ticket = self.queue.fetch_add(1, Ordering::SeqCst) + 1;
		let mut counter: u16 = 0;
		while self.dequeue.load(Ordering::SeqCst) != ticket {
			counter += 1;
			if counter < 100 {
				hint::spin_loop();
			} else {
				counter = 0;
				unsafe {
					yield_now();
				}
			}
		}
	}

	#[inline]
	pub unsafe fn lock(&self) -> SpinlockGuard<'_, T> {
		self.obtain_lock();
		SpinlockGuard {
			dequeue: &self.dequeue,
			data: &mut *self.data.get(),
		}
	}
}

impl<T: ?Sized + Default> Default for Spinlock<T> {
	fn default() -> Spinlock<T> {
		Spinlock::new(Default::default())
	}
}

impl<'a, T: ?Sized> Deref for SpinlockGuard<'a, T> {
	type Target = T;
	fn deref(&self) -> &T {
		&*self.data
	}
}

impl<'a, T: ?Sized> DerefMut for SpinlockGuard<'a, T> {
	fn deref_mut(&mut self) -> &mut T {
		&mut *self.data
	}
}

impl<'a, T: ?Sized> Drop for SpinlockGuard<'a, T> {
	/// The dropping of the SpinlockGuard will release the lock it was created from.
	fn drop(&mut self) {
		self.dequeue.fetch_add(1, Ordering::SeqCst);
	}
}

/// Realize a priority queue for tasks
pub struct PriorityQueue {
	queues: [Option<VecDeque<Tid>>; NO_PRIORITIES],
	prio_bitmap: u64,
}

impl PriorityQueue {
	pub const fn new() -> PriorityQueue {
		PriorityQueue {
			queues: [
				None, None, None, None, None, None, None, None, None, None, None, None, None, None,
				None, None, None, None, None, None, None, None, None, None, None, None, None, None,
				None, None, None,
			],
			prio_bitmap: 0,
		}
	}

	/// Add a task id by its priority to the queue
	pub fn push(&mut self, prio: Priority, id: Tid) {
		let i: usize = prio.into().into();
		self.prio_bitmap |= (1 << i) as u64;
		if let Some(queue) = &mut self.queues[i] {
			queue.push_back(id);
		} else {
			let mut queue = VecDeque::new();
			queue.push_back(id);
			self.queues[i] = Some(queue);
		}
	}

	fn pop_from_queue(&mut self, queue_index: usize) -> Option<Tid> {
		if let Some(queue) = &mut self.queues[queue_index] {
			let id = queue.pop_front();

			if queue.is_empty() {
				self.prio_bitmap &= !(1 << queue_index as u64);
			}

			id
		} else {
			None
		}
	}

	/// Pop the task handle with the highest priority from the queue
	pub fn pop(&mut self) -> Option<Tid> {
		for i in 0..NO_PRIORITIES {
			if self.prio_bitmap & (1 << i) != 0 {
				return self.pop_from_queue(i);
			}
		}

		None
	}
}

struct MutexInner {
	locked: bool,
	blocked_task: PriorityQueue,
}

impl MutexInner {
	pub const fn new() -> MutexInner {
		MutexInner {
			locked: false,
			blocked_task: PriorityQueue::new(),
		}
	}
}

pub struct Mutex {
	inner: Spinlock<MutexInner>,
}

pub type MovableMutex = Mutex;

unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}

impl Mutex {
	pub const fn new() -> Mutex {
		Mutex {
			inner: Spinlock::new(MutexInner::new()),
		}
	}

	#[inline]
	pub unsafe fn init(&mut self) {
		self.inner = Spinlock::new(MutexInner::new());
	}

	#[inline]
	pub unsafe fn lock(&self) {
		loop {
			let mut guard = self.inner.lock();
			if !guard.locked {
				guard.locked = true;
				return;
			} else {
				let prio = get_priority();
				let id = getpid();

				guard.blocked_task.push(prio, id);
				block_current_task();
				drop(guard);
				yield_now();
			}
		}
	}

	#[inline]
	pub unsafe fn unlock(&self) {
		let mut guard = self.inner.lock();
		guard.locked = false;
		if let Some(tid) = guard.blocked_task.pop() {
			wakeup_task(tid);
		}
	}

	#[inline]
	pub unsafe fn try_lock(&self) -> bool {
		let mut guard = self.inner.lock();
		if guard.locked == false {
			guard.locked = true;
		}
		guard.locked
	}

	#[inline]
	pub unsafe fn destroy(&self) {}
}
<commit_msg>remove obsolete definition of MoveableMutex<commit_after>extern crate alloc;

use crate::{
	block_current_task, get_priority, getpid, wakeup_task, yield_now, Priority, Tid, NO_PRIORITIES,
};
use alloc::collections::vec_deque::VecDeque;
use core::cell::UnsafeCell;
use core::hint;
use core::ops::{Deref, DerefMut, Drop};
use core::sync::atomic::{AtomicUsize, Ordering};

/// This type provides a lock based on busy waiting to realize mutual exclusion
///
/// # Description
///
/// This structure behaves a lot like a common mutex. There are some differences:
///
/// - By using busy waiting, it can be used outside the runtime.
/// - It is a so called ticket lock and is completely fair.
#[cfg_attr(target_arch = "x86_64", repr(align(128)))]
#[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
struct Spinlock<T: ?Sized> {
	queue: AtomicUsize,
	dequeue: AtomicUsize,
	data: UnsafeCell<T>,
}

unsafe impl<T: ?Sized + Send> Sync for Spinlock<T> {}
unsafe impl<T: ?Sized + Send> Send for Spinlock<T> {}

/// A guard to which the protected data can be accessed
///
/// When the guard falls out of scope it will release the lock.
struct SpinlockGuard<'a, T: ?Sized + 'a> {
	dequeue: &'a AtomicUsize,
	data: &'a mut T,
}

impl<T> Spinlock<T> {
	pub const fn new(user_data: T) -> Spinlock<T> {
		Spinlock {
			queue: AtomicUsize::new(0),
			dequeue: AtomicUsize::new(1),
			data: UnsafeCell::new(user_data),
		}
	}

	#[inline]
	fn obtain_lock(&self) {
		let ticket = self.queue.fetch_add(1, Ordering::SeqCst) + 1;
		let mut counter: u16 = 0;
		while self.dequeue.load(Ordering::SeqCst) != ticket {
			counter += 1;
			if counter < 100 {
				hint::spin_loop();
			} else {
				counter = 0;
				unsafe {
					yield_now();
				}
			}
		}
	}

	#[inline]
	pub unsafe fn lock(&self) -> SpinlockGuard<'_, T> {
		self.obtain_lock();
		SpinlockGuard {
			dequeue: &self.dequeue,
			data: &mut *self.data.get(),
		}
	}
}

impl<T: ?Sized + Default> Default for Spinlock<T> {
	fn default() -> Spinlock<T> {
		Spinlock::new(Default::default())
	}
}

impl<'a, T: ?Sized> Deref for SpinlockGuard<'a, T> {
	type Target = T;
	fn deref(&self) -> &T {
		&*self.data
	}
}

impl<'a, T: ?Sized> DerefMut for SpinlockGuard<'a, T> {
	fn deref_mut(&mut self) -> &mut T {
		&mut *self.data
	}
}

impl<'a, T: ?Sized> Drop for SpinlockGuard<'a, T> {
	/// The dropping of the SpinlockGuard will release the lock it was created from.
	fn drop(&mut self) {
		self.dequeue.fetch_add(1, Ordering::SeqCst);
	}
}

/// Realize a priority queue for tasks
pub struct PriorityQueue {
	queues: [Option<VecDeque<Tid>>; NO_PRIORITIES],
	prio_bitmap: u64,
}

impl PriorityQueue {
	pub const fn new() -> PriorityQueue {
		PriorityQueue {
			queues: [
				None, None, None, None, None, None, None, None, None, None, None, None, None, None,
				None, None, None, None, None, None, None, None, None, None, None, None, None, None,
				None, None, None,
			],
			prio_bitmap: 0,
		}
	}

	/// Add a task id by its priority to the queue
	pub fn push(&mut self, prio: Priority, id: Tid) {
		let i: usize = prio.into().into();
		self.prio_bitmap |= (1 << i) as u64;
		if let Some(queue) = &mut self.queues[i] {
			queue.push_back(id);
		} else {
			let mut queue = VecDeque::new();
			queue.push_back(id);
			self.queues[i] = Some(queue);
		}
	}

	fn pop_from_queue(&mut self, queue_index: usize) -> Option<Tid> {
		if let Some(queue) = &mut self.queues[queue_index] {
			let id = queue.pop_front();

			if queue.is_empty() {
				self.prio_bitmap &= !(1 << queue_index as u64);
			}

			id
		} else {
			None
		}
	}

	/// Pop the task handle with the highest priority from the queue
	pub fn pop(&mut self) -> Option<Tid> {
		for i in 0..NO_PRIORITIES {
			if self.prio_bitmap & (1 << i) != 0 {
				return self.pop_from_queue(i);
			}
		}

		None
	}
}

struct MutexInner {
	locked: bool,
	blocked_task: PriorityQueue,
}

impl MutexInner {
	pub const fn new() -> MutexInner {
		MutexInner {
			locked: false,
			blocked_task: PriorityQueue::new(),
		}
	}
}

pub struct Mutex {
	inner: Spinlock<MutexInner>,
}

unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}

impl Mutex {
	pub const fn new() -> Mutex {
		Mutex {
			inner: Spinlock::new(MutexInner::new()),
		}
	}

	#[inline]
	pub unsafe fn init(&mut self) {
		self.inner = Spinlock::new(MutexInner::new());
	}

	#[inline]
	pub unsafe fn lock(&self) {
		loop {
			let mut guard = self.inner.lock();
			if !guard.locked {
				guard.locked = true;
				return;
			} else {
				let prio = get_priority();
				let id = getpid();

				guard.blocked_task.push(prio, id);
				block_current_task();
				drop(guard);
				yield_now();
			}
		}
	}

	#[inline]
	pub unsafe fn unlock(&self) {
		let mut guard = self.inner.lock();
		guard.locked = false;
		if let Some(tid) = guard.blocked_task.pop() {
			wakeup_task(tid);
		}
	}

	#[inline]
	pub unsafe fn try_lock(&self) -> bool {
		let mut guard = self.inner.lock();
		if guard.locked == false {
			guard.locked = true;
		}
		guard.locked
	}

	#[inline]
	pub unsafe fn destroy(&self) {}
}
<|endoftext|>


<commit_before><commit_msg>Put attribute directly on if let<commit_after><|endoftext|>


<commit_before>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate serde_json;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate task_hookrs;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;
extern crate libimagtodo;

use std::process::exit;
use std::process::{Command, Stdio};
use std::io::stdin;
use std::io::BufRead;

use task_hookrs::import::{import_task, import_tasks};

use libimagrt::runtime::Runtime;
use libimagtodo::task::IntoTask;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;
fn main() {
    let name = "imag-todo";
    let version = &version!()[..];
    let about = "Interface with taskwarrior";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));

    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.unwrap_err());
            exit(1);
        }
    };

    match rt.cli().subcommand_name() {
        Some("tw-hook") => tw_hook(&rt),
        Some("list") => list(&rt),
        _ => unimplemented!(),
    } // end match scmd
} // end main

fn tw_hook(rt: &Runtime) {
    let subcmd = rt.cli().subcommand_matches("tw-hook").unwrap();
    if subcmd.is_present("add") {
        let stdin     = stdin();
        let mut stdin = stdin.lock();
        let mut line  = String::new();

        if let Err(e) = stdin.read_line(&mut line) {
            trace_error(&e);
            exit(1);
        };

        if let Ok(ttask) = import_task(&line.as_str()) {
            match serde_json::ser::to_string(&ttask) {
                Ok(val) => println!("{}", val),
                Err(e) => {
                    trace_error(&e);
                    exit(1);
                }
            }

            let uuid = *ttask.uuid();
            match ttask.into_filelockentry(rt.store()) {
                Ok(val) => {
                    println!("Task {} stored in imag", uuid);
                    val
                },
                Err(e) => {
                    trace_error(&e);
                    exit(1);
                }
            };
        } else {
            error!("No usable input");
            exit(1);
        }
    } else if subcmd.is_present("delete") {
        // The used hook is "on-modify". This hook gives two json-objects
        // per usage und wants one (the second one) back.
        let mut counter   = 0;
        let stdin         = stdin();
        let stdin         = stdin.lock();

        match import_tasks(stdin) {
            Ok(ttasks) => for ttask in ttasks {
                if counter % 2 == 1 {
                    // Only every second task is needed, the first one is the
                    // task before the change, and the second one after
                    // the change. The (maybe modified) second one is
                    // expected by taskwarrior.
                    match serde_json::ser::to_string(&ttask) {
                        Ok(val) => println!("{}", val),
                        Err(e) => {
                            trace_error(&e);
                            exit(1);
                        }
                    }

                    match ttask.status() {
                        &task_hookrs::status::TaskStatus::Deleted => {
                            match libimagtodo::delete::delete(rt.store(), *ttask.uuid()) {
                                Ok(_) => println!("Deleted task {}", *ttask.uuid()),
                                Err(e) => {
                                    trace_error(&e);
                                    exit(1);
                                }
                            }
                        }
                        _ => {
                        }
                    } // end match ttask.status()
                } // end if c % 2
                counter += 1;
            },
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
        }
    } else {
        // Should not be possible, as one argument is required via
        // ArgGroup
        unreachable!();
    }
}

fn list(rt: &Runtime) {
    let subcmd   = rt.cli().subcommand_matches("list").unwrap();
    let mut args = Vec::new();
    let verbose  = subcmd.is_present("verbose");
    let iter     = match libimagtodo::read::get_todo_iterator(rt.store()) {
        Err(e) => {
            trace_error(&e);
            exit(1);
        }
        Ok(val) => val,
    };

    for task in iter {
        match task {
            Ok(val) => {
                let uuid = match val.flentry.get_header().read("todo.uuid") {
                    Ok(Some(u)) => u,
                    Ok(None)    => continue,
                    Err(e)      => {
                        trace_error(&e);
                        continue;
                    }
                };

                if verbose {
                    args.clear();
                    args.push(format!("uuid:{} information", uuid));
                    let tw_process = Command::new("task").stdin(Stdio::null()).args(&args).spawn()
                        .unwrap_or_else(|e| {
                            trace_error(&e);
                            panic!("failed");
                        });
                    let output = tw_process.wait_with_output().unwrap_or_else(|e| {
                        panic!("failed to unwrap output: {}", e);
                    });
                    let outstring = String::from_utf8(output.stdout).unwrap_or_else(|e| {
                        panic!("failed to execute: {}", e);
                    });
                    println!("{}", outstring);
                } else {
                    println!("{}", match uuid {
                        toml::Value::String(s) => s,
                        _ => {
                            error!("Unexpected type for todo.uuid: {}", uuid);
                            continue;
                        },
                    });
                }
            }
            Err(e) => {
                trace_error(&e);
                continue;
            }
        } // end match task
    } // end for
}

<commit_msg>Format code<commit_after>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate serde_json;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate task_hookrs;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;
extern crate libimagtodo;

use std::process::exit;
use std::process::{Command, Stdio};
use std::io::stdin;
use std::io::BufRead;

use task_hookrs::import::{import_task, import_tasks};

use libimagrt::runtime::Runtime;
use libimagtodo::task::IntoTask;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;
fn main() {
    let name    = "imag-todo";
    let version = &version!()[..];
    let about   = "Interface with taskwarrior";
    let ui      = build_ui(Runtime::get_default_cli_builder(name, version, about));

    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.unwrap_err());
            exit(1);
        }
    };

    match rt.cli().subcommand_name() {
        Some("tw-hook") => tw_hook(&rt),
        Some("list") => list(&rt),
        _ => unimplemented!(),
    } // end match scmd
} // end main

fn tw_hook(rt: &Runtime) {
    let subcmd = rt.cli().subcommand_matches("tw-hook").unwrap();
    if subcmd.is_present("add") {
        let stdin     = stdin();
        let mut stdin = stdin.lock();
        let mut line  = String::new();

        if let Err(e) = stdin.read_line(&mut line) {
            trace_error(&e);
            exit(1);
        };

        if let Ok(ttask) = import_task(&line.as_str()) {
            match serde_json::ser::to_string(&ttask) {
                Ok(val) => println!("{}", val),
                Err(e) => {
                    trace_error(&e);
                    exit(1);
                }
            }

            let uuid = *ttask.uuid();
            match ttask.into_filelockentry(rt.store()) {
                Ok(val) => {
                    println!("Task {} stored in imag", uuid);
                    val
                },
                Err(e) => {
                    trace_error(&e);
                    exit(1);
                }
            };
        } else {
            error!("No usable input");
            exit(1);
        }
    } else if subcmd.is_present("delete") {
        // The used hook is "on-modify". This hook gives two json-objects
        // per usage und wants one (the second one) back.
        let mut counter   = 0;
        let stdin         = stdin();
        let stdin         = stdin.lock();

        match import_tasks(stdin) {
            Ok(ttasks) => for ttask in ttasks {
                if counter % 2 == 1 {
                    // Only every second task is needed, the first one is the
                    // task before the change, and the second one after
                    // the change. The (maybe modified) second one is
                    // expected by taskwarrior.
                    match serde_json::ser::to_string(&ttask) {
                        Ok(val) => println!("{}", val),
                        Err(e) => {
                            trace_error(&e);
                            exit(1);
                        }
                    }

                    match ttask.status() {
                        &task_hookrs::status::TaskStatus::Deleted => {
                            match libimagtodo::delete::delete(rt.store(), *ttask.uuid()) {
                                Ok(_) => println!("Deleted task {}", *ttask.uuid()),
                                Err(e) => {
                                    trace_error(&e);
                                    exit(1);
                                }
                            }
                        }
                        _ => {
                        }
                    } // end match ttask.status()
                } // end if c % 2
                counter += 1;
            },
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
        }
    } else {
        // Should not be possible, as one argument is required via
        // ArgGroup
        unreachable!();
    }
}

fn list(rt: &Runtime) {
    let subcmd   = rt.cli().subcommand_matches("list").unwrap();
    let mut args = Vec::new();
    let verbose  = subcmd.is_present("verbose");
    let iter     = match libimagtodo::read::get_todo_iterator(rt.store()) {
        Err(e) => {
            trace_error(&e);
            exit(1);
        }
        Ok(val) => val,
    };

    for task in iter {
        match task {
            Ok(val) => {
                let uuid = match val.flentry.get_header().read("todo.uuid") {
                    Ok(Some(u)) => u,
                    Ok(None)    => continue,
                    Err(e)      => {
                        trace_error(&e);
                        continue;
                    }
                };

                if verbose {
                    args.clear();
                    args.push(format!("uuid:{} information", uuid));

                    let tw_process = Command::new("task")
                        .stdin(Stdio::null())
                        .args(&args)
                        .spawn()
                        .unwrap_or_else(|e| {
                            trace_error(&e);
                            panic!("failed");
                        });
                    let output = tw_process
                        .wait_with_output()
                        .unwrap_or_else(|e| panic!("failed to unwrap output: {}", e));
                    let outstring = String::from_utf8(output.stdout)
                        .unwrap_or_else(|e| panic!("failed to execute: {}", e));

                    println!("{}", outstring);
                } else {
                    println!("{}", match uuid {
                        toml::Value::String(s) => s,
                        _ => {
                            error!("Unexpected type for todo.uuid: {}", uuid);
                            continue;
                        },
                    });
                }
            }
            Err(e) => {
                trace_error(&e);
                continue;
            }
        } // end match task
    } // end for
}

<|endoftext|>


<commit_before>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate serde_json;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate task_hookrs;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;
extern crate libimagtodo;

use std::process::exit;
use std::process::{Command, Stdio};
use std::io::stdin;

use toml::Value;

use task_hookrs::import::import_tasks;
use task_hookrs::status::TaskStatus;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagtodo::task::Task;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;
fn main() {
    let rt = generate_runtime_setup("imag-todo",
                                    &version!()[..],
                                    "Interface with taskwarrior",
                                    build_ui);

    match rt.cli().subcommand_name() {
        Some("tw-hook") => tw_hook(&rt),
        Some("list") => list(&rt),
        _ => unreachable!(),
    } // end match scmd
} // end main

fn tw_hook(rt: &Runtime) {
    let subcmd = rt.cli().subcommand_matches("tw-hook").unwrap();
    if subcmd.is_present("add") {
        let stdin = stdin();
        let stdin = stdin.lock(); // implements BufRead which is required for `Task::import()`

        match Task::import(rt.store(), stdin) {
            Ok((_, line, uuid)) => info!("{}\nTask {} stored in imag", line, uuid),
            Err(e) => {
                trace_error(&e);
                exit(1);
            }
        }
    } else if subcmd.is_present("delete") {
        // The used hook is "on-modify". This hook gives two json-objects
        // per usage und wants one (the second one) back.
        let stdin         = stdin();
        let stdin         = stdin.lock();

        match import_tasks(stdin) {
            Ok(ttasks) => for (counter, ttask) in ttasks.iter().enumerate() {
                if counter % 2 == 1 {
                    // Only every second task is needed, the first one is the
                    // task before the change, and the second one after
                    // the change. The (maybe modified) second one is
                    // expected by taskwarrior.
                    match serde_json::ser::to_string(&ttask) {
                        Ok(val) => println!("{}", val),
                        Err(e) => {
                            trace_error(&e);
                            exit(1);
                        }
                    }

                    // Taskwarrior does not have the concept of deleted tasks, but only modified
                    // ones.
                    //
                    // Here we check if the status of a task is deleted and if yes, we delete it
                    // from the store.
                    if *ttask.status() == TaskStatus::Deleted {
                        match Task::delete_by_uuid(rt.store(), *ttask.uuid()) {
                            Ok(_) => println!("Deleted task {}", *ttask.uuid()),
                            Err(e) => {
                                trace_error(&e);
                                exit(1);
                            }
                        }
                    }
                } // end if c % 2
            },
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
        }
    } else {
        // Should not be possible, as one argument is required via
        // ArgGroup
        unreachable!();
    }
}

fn list(rt: &Runtime) {
    let subcmd  = rt.cli().subcommand_matches("list").unwrap();
    let verbose = subcmd.is_present("verbose");

    let res = Task::all(rt.store()) // get all tasks
        .map(|iter| { // and if this succeeded
            // filter out the ones were we can read the uuid
            let uuids : Vec<_> = iter.filter_map(|t| match t {
                Ok(v) => match v.get_header().read("todo.uuid") {
                    Ok(Some(Value::String(ref u))) => Some(u.clone()),
                    Ok(Some(_)) => {
                        warn!("Header type error");
                        None
                    },
                    Ok(None) => None,
                    Err(e) => {
                        trace_error(&e);
                        None
                    }
                },
                Err(e) => {
                    trace_error(&e);
                    None
                }
            })
            .collect();

            // compose a `task` call with them, ...
            let outstring = if verbose { // ... if verbose
                let output = Command::new("task")
                    .stdin(Stdio::null())
                    .args(&uuids)
                    .spawn()
                    .unwrap_or_else(|e| {
                        trace_error(&e);
                        panic!("Failed to execute `task` on the commandline. I'm dying now.");
                    })
                    .wait_with_output()
                    .unwrap_or_else(|e| panic!("failed to unwrap output: {}", e));

                String::from_utf8(output.stdout)
                    .unwrap_or_else(|e| panic!("failed to execute: {}", e))
            } else { // ... else just join them
                uuids.join("\n")
            };

            /// and then print that
            println!("{}", outstring);
        });

    if let Err(e) = res {
        trace_error(&e);
    }
}

<commit_msg>Fix comment which broke the build<commit_after>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate serde_json;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate task_hookrs;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;
extern crate libimagtodo;

use std::process::exit;
use std::process::{Command, Stdio};
use std::io::stdin;

use toml::Value;

use task_hookrs::import::import_tasks;
use task_hookrs::status::TaskStatus;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagtodo::task::Task;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;
fn main() {
    let rt = generate_runtime_setup("imag-todo",
                                    &version!()[..],
                                    "Interface with taskwarrior",
                                    build_ui);

    match rt.cli().subcommand_name() {
        Some("tw-hook") => tw_hook(&rt),
        Some("list") => list(&rt),
        _ => unreachable!(),
    } // end match scmd
} // end main

fn tw_hook(rt: &Runtime) {
    let subcmd = rt.cli().subcommand_matches("tw-hook").unwrap();
    if subcmd.is_present("add") {
        let stdin = stdin();
        let stdin = stdin.lock(); // implements BufRead which is required for `Task::import()`

        match Task::import(rt.store(), stdin) {
            Ok((_, line, uuid)) => info!("{}\nTask {} stored in imag", line, uuid),
            Err(e) => {
                trace_error(&e);
                exit(1);
            }
        }
    } else if subcmd.is_present("delete") {
        // The used hook is "on-modify". This hook gives two json-objects
        // per usage und wants one (the second one) back.
        let stdin         = stdin();
        let stdin         = stdin.lock();

        match import_tasks(stdin) {
            Ok(ttasks) => for (counter, ttask) in ttasks.iter().enumerate() {
                if counter % 2 == 1 {
                    // Only every second task is needed, the first one is the
                    // task before the change, and the second one after
                    // the change. The (maybe modified) second one is
                    // expected by taskwarrior.
                    match serde_json::ser::to_string(&ttask) {
                        Ok(val) => println!("{}", val),
                        Err(e) => {
                            trace_error(&e);
                            exit(1);
                        }
                    }

                    // Taskwarrior does not have the concept of deleted tasks, but only modified
                    // ones.
                    //
                    // Here we check if the status of a task is deleted and if yes, we delete it
                    // from the store.
                    if *ttask.status() == TaskStatus::Deleted {
                        match Task::delete_by_uuid(rt.store(), *ttask.uuid()) {
                            Ok(_) => println!("Deleted task {}", *ttask.uuid()),
                            Err(e) => {
                                trace_error(&e);
                                exit(1);
                            }
                        }
                    }
                } // end if c % 2
            },
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
        }
    } else {
        // Should not be possible, as one argument is required via
        // ArgGroup
        unreachable!();
    }
}

fn list(rt: &Runtime) {
    let subcmd  = rt.cli().subcommand_matches("list").unwrap();
    let verbose = subcmd.is_present("verbose");

    let res = Task::all(rt.store()) // get all tasks
        .map(|iter| { // and if this succeeded
            // filter out the ones were we can read the uuid
            let uuids : Vec<_> = iter.filter_map(|t| match t {
                Ok(v) => match v.get_header().read("todo.uuid") {
                    Ok(Some(Value::String(ref u))) => Some(u.clone()),
                    Ok(Some(_)) => {
                        warn!("Header type error");
                        None
                    },
                    Ok(None) => None,
                    Err(e) => {
                        trace_error(&e);
                        None
                    }
                },
                Err(e) => {
                    trace_error(&e);
                    None
                }
            })
            .collect();

            // compose a `task` call with them, ...
            let outstring = if verbose { // ... if verbose
                let output = Command::new("task")
                    .stdin(Stdio::null())
                    .args(&uuids)
                    .spawn()
                    .unwrap_or_else(|e| {
                        trace_error(&e);
                        panic!("Failed to execute `task` on the commandline. I'm dying now.");
                    })
                    .wait_with_output()
                    .unwrap_or_else(|e| panic!("failed to unwrap output: {}", e));

                String::from_utf8(output.stdout)
                    .unwrap_or_else(|e| panic!("failed to execute: {}", e))
            } else { // ... else just join them
                uuids.join("\n")
            };

            // and then print that
            println!("{}", outstring);
        });

    if let Err(e) = res {
        trace_error(&e);
    }
}

<|endoftext|>