<commit_before>//! Boxed slices for `PrimaryMap`.

use crate::iter::{Iter, IterMut};
use crate::keys::Keys;
use crate::EntityRef;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
use std::slice;

/// A slice mapping `K -> V` allocating dense entity references.
///
/// The `BoxedSlice` data structure uses the dense index space to implement a map with a boxed
/// slice.
#[derive(Debug, Clone)]
pub struct BoxedSlice<K, V>
where
    K: EntityRef,
{
    elems: Box<[V]>,
    unused: PhantomData<K>,
}

impl<K, V> BoxedSlice<K, V>
where
    K: EntityRef,
{
    /// Create a new slice from a raw pointer. A safer way to create slices is
    /// to use `PrimaryMap::into_boxed_slice()`.
    pub unsafe fn from_raw(raw: *mut [V]) -> Self {
        Self {
            elems: Box::from_raw(raw),
            unused: PhantomData,
        }
    }

    /// Check if `k` is a valid key in the map.
    pub fn is_valid(&self, k: K) -> bool {
        k.index() < self.elems.len()
    }

    /// Get the element at `k` if it exists.
    pub fn get(&self, k: K) -> Option<&V> {
        self.elems.get(k.index())
    }

    /// Get the element at `k` if it exists, mutable version.
    pub fn get_mut(&mut self, k: K) -> Option<&mut V> {
        self.elems.get_mut(k.index())
    }

    /// Is this map completely empty?
    pub fn is_empty(&self) -> bool {
        self.elems.is_empty()
    }

    /// Get the total number of entity references created.
    pub fn len(&self) -> usize {
        self.elems.len()
    }

    /// Iterate over all the keys in this map.
    pub fn keys(&self) -> Keys<K> {
        Keys::with_len(self.elems.len())
    }

    /// Iterate over all the values in this map.
    pub fn values(&self) -> slice::Iter<V> {
        self.elems.iter()
    }

    /// Iterate over all the values in this map, mutable edition.
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        self.elems.iter_mut()
    }

    /// Iterate over all the keys and values in this map.
    pub fn iter(&self) -> Iter<K, V> {
        Iter::new(self.elems.iter())
    }

    /// Iterate over all the keys and values in this map, mutable edition.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        IterMut::new(self.elems.iter_mut())
    }

    /// Get the key that will be assigned to the next pushed value.
    pub fn next_key(&self) -> K {
        K::new(self.elems.len())
    }

    /// Returns the last element that was inserted in the map.
    pub fn last(&self) -> Option<&V> {
        self.elems.last()
    }
}

/// Immutable indexing into a `BoxedSlice`.
/// The indexed value must be in the map.
impl<K, V> Index<K> for BoxedSlice<K, V>
where
    K: EntityRef,
{
    type Output = V;

    fn index(&self, k: K) -> &V {
        &self.elems[k.index()]
    }
}

/// Mutable indexing into a `BoxedSlice`.
impl<K, V> IndexMut<K> for BoxedSlice<K, V>
where
    K: EntityRef,
{
    fn index_mut(&mut self, k: K) -> &mut V {
        &mut self.elems[k.index()]
    }
}

impl<'a, K, V> IntoIterator for &'a BoxedSlice<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        Iter::new(self.elems.iter())
    }
}

impl<'a, K, V> IntoIterator for &'a mut BoxedSlice<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        IterMut::new(self.elems.iter_mut())
    }
}

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

    // `EntityRef` impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let p = PrimaryMap::<E, isize>::new();
        let m = p.into_boxed_slice();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);

        assert!(!m.is_valid(r0));
        assert!(!m.is_valid(r1));
    }

    #[test]
    fn iter() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let mut m = p.into_boxed_slice();

        let mut i = 0;
        for (key, value) in &m {
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for (key_mut, value_mut) in m.iter_mut() {
            assert_eq!(key_mut.index(), i);
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn iter_rev() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let mut m = p.into_boxed_slice();

        let mut i = 2;
        for (key, value) in m.iter().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }

        i = 2;
        for (key, value) in m.iter_mut().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
    }
    #[test]
    fn keys() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let m = p.into_boxed_slice();

        let mut i = 0;
        for key in m.keys() {
            assert_eq!(key.index(), i);
            i += 1;
        }
    }

    #[test]
    fn keys_rev() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let m = p.into_boxed_slice();

        let mut i = 2;
        for key in m.keys().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
        }
    }

    #[test]
    fn values() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let mut m = p.into_boxed_slice();

        let mut i = 0;
        for value in m.values() {
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for value_mut in m.values_mut() {
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn values_rev() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let mut m = p.into_boxed_slice();

        let mut i = 2;
        for value in m.values().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
        i = 2;
        for value_mut in m.values_mut().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
        }
    }
}
<commit_msg>Remove `BoxedSlice`'s `next_key()` function, which is unneeded.<commit_after>//! Boxed slices for `PrimaryMap`.

use crate::iter::{Iter, IterMut};
use crate::keys::Keys;
use crate::EntityRef;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
use std::slice;

/// A slice mapping `K -> V` allocating dense entity references.
///
/// The `BoxedSlice` data structure uses the dense index space to implement a map with a boxed
/// slice.
#[derive(Debug, Clone)]
pub struct BoxedSlice<K, V>
where
    K: EntityRef,
{
    elems: Box<[V]>,
    unused: PhantomData<K>,
}

impl<K, V> BoxedSlice<K, V>
where
    K: EntityRef,
{
    /// Create a new slice from a raw pointer. A safer way to create slices is
    /// to use `PrimaryMap::into_boxed_slice()`.
    pub unsafe fn from_raw(raw: *mut [V]) -> Self {
        Self {
            elems: Box::from_raw(raw),
            unused: PhantomData,
        }
    }

    /// Check if `k` is a valid key in the map.
    pub fn is_valid(&self, k: K) -> bool {
        k.index() < self.elems.len()
    }

    /// Get the element at `k` if it exists.
    pub fn get(&self, k: K) -> Option<&V> {
        self.elems.get(k.index())
    }

    /// Get the element at `k` if it exists, mutable version.
    pub fn get_mut(&mut self, k: K) -> Option<&mut V> {
        self.elems.get_mut(k.index())
    }

    /// Is this map completely empty?
    pub fn is_empty(&self) -> bool {
        self.elems.is_empty()
    }

    /// Get the total number of entity references created.
    pub fn len(&self) -> usize {
        self.elems.len()
    }

    /// Iterate over all the keys in this map.
    pub fn keys(&self) -> Keys<K> {
        Keys::with_len(self.elems.len())
    }

    /// Iterate over all the values in this map.
    pub fn values(&self) -> slice::Iter<V> {
        self.elems.iter()
    }

    /// Iterate over all the values in this map, mutable edition.
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        self.elems.iter_mut()
    }

    /// Iterate over all the keys and values in this map.
    pub fn iter(&self) -> Iter<K, V> {
        Iter::new(self.elems.iter())
    }

    /// Iterate over all the keys and values in this map, mutable edition.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        IterMut::new(self.elems.iter_mut())
    }

    /// Returns the last element that was inserted in the map.
    pub fn last(&self) -> Option<&V> {
        self.elems.last()
    }
}

/// Immutable indexing into a `BoxedSlice`.
/// The indexed value must be in the map.
impl<K, V> Index<K> for BoxedSlice<K, V>
where
    K: EntityRef,
{
    type Output = V;

    fn index(&self, k: K) -> &V {
        &self.elems[k.index()]
    }
}

/// Mutable indexing into a `BoxedSlice`.
impl<K, V> IndexMut<K> for BoxedSlice<K, V>
where
    K: EntityRef,
{
    fn index_mut(&mut self, k: K) -> &mut V {
        &mut self.elems[k.index()]
    }
}

impl<'a, K, V> IntoIterator for &'a BoxedSlice<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        Iter::new(self.elems.iter())
    }
}

impl<'a, K, V> IntoIterator for &'a mut BoxedSlice<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        IterMut::new(self.elems.iter_mut())
    }
}

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

    // `EntityRef` impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let p = PrimaryMap::<E, isize>::new();
        let m = p.into_boxed_slice();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);

        assert!(!m.is_valid(r0));
        assert!(!m.is_valid(r1));
    }

    #[test]
    fn iter() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let mut m = p.into_boxed_slice();

        let mut i = 0;
        for (key, value) in &m {
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for (key_mut, value_mut) in m.iter_mut() {
            assert_eq!(key_mut.index(), i);
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn iter_rev() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let mut m = p.into_boxed_slice();

        let mut i = 2;
        for (key, value) in m.iter().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }

        i = 2;
        for (key, value) in m.iter_mut().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
    }
    #[test]
    fn keys() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let m = p.into_boxed_slice();

        let mut i = 0;
        for key in m.keys() {
            assert_eq!(key.index(), i);
            i += 1;
        }
    }

    #[test]
    fn keys_rev() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let m = p.into_boxed_slice();

        let mut i = 2;
        for key in m.keys().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
        }
    }

    #[test]
    fn values() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let mut m = p.into_boxed_slice();

        let mut i = 0;
        for value in m.values() {
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for value_mut in m.values_mut() {
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn values_rev() {
        let mut p: PrimaryMap<E, usize> = PrimaryMap::new();
        p.push(12);
        p.push(33);
        let mut m = p.into_boxed_slice();

        let mut i = 2;
        for value in m.values().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
        i = 2;
        for value_mut in m.values_mut().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
        }
    }
}
<|endoftext|>


<commit_before>use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
use quote::{format_ident, quote, ToTokens};
use std::iter::once;
use syn::parse::{Nothing, Parse, ParseStream};
use syn::{
    braced, bracketed, parenthesized, token, Attribute, Error, Field, Ident, Index, LitInt, LitStr,
    Result, Token,
};

pub struct Display {
    pub fmt: LitStr,
    pub args: TokenStream,
    pub was_shorthand: bool,
}

impl Parse for Display {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut display = Display {
            fmt: input.parse()?,
            args: parse_token_expr(input, false)?,
            was_shorthand: false,
        };
        display.expand_shorthand();
        Ok(display)
    }
}

fn parse_token_expr(input: ParseStream, mut last_is_comma: bool) -> Result<TokenStream> {
    let mut tokens = TokenStream::new();
    while !input.is_empty() {
        if last_is_comma && input.peek(Token![.]) {
            if input.peek2(Ident) {
                input.parse::<Token![.]>()?;
                last_is_comma = false;
                continue;
            }
            if input.peek2(LitInt) {
                input.parse::<Token![.]>()?;
                let int: Index = input.parse()?;
                let ident = format_ident!("_{}", int.index, span = int.span);
                tokens.extend(once(TokenTree::Ident(ident)));
                last_is_comma = false;
                continue;
            }
        }
        last_is_comma = input.peek(Token![,]);
        let token: TokenTree = if input.peek(token::Paren) {
            let content;
            let delimiter = parenthesized!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Parenthesis, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else if input.peek(token::Brace) {
            let content;
            let delimiter = braced!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Brace, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else if input.peek(token::Bracket) {
            let content;
            let delimiter = bracketed!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Bracket, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else {
            input.parse()?
        };
        tokens.extend(once(token));
    }
    Ok(tokens)
}

impl ToTokens for Display {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let fmt = &self.fmt;
        let args = &self.args;
        if self.was_shorthand && fmt.value() == "{}" {
            let arg = args.clone().into_iter().skip(1).next().unwrap();
            tokens.extend(quote! {
                std::fmt::Display::fmt(#arg, formatter)
            });
        } else if self.was_shorthand && fmt.value() == "{:?}" {
            let arg = args.clone().into_iter().skip(1).next().unwrap();
            tokens.extend(quote! {
                std::fmt::Debug::fmt(#arg, formatter)
            });
        } else {
            tokens.extend(quote! {
                write!(formatter, #fmt #args)
            });
        }
    }
}

pub fn is_source(field: &Field) -> Result<bool> {
    for attr in &field.attrs {
        if attr.path.is_ident("source") {
            syn::parse2::<Nothing>(attr.tokens.clone())?;
            return Ok(true);
        }
    }
    Ok(false)
}

pub fn display(attrs: &[Attribute]) -> Result<Option<Display>> {
    let mut display = None;

    for attr in attrs {
        if attr.path.is_ident("error") {
            if display.is_some() {
                return Err(Error::new_spanned(
                    attr,
                    "only one #[error(...)] attribute is allowed",
                ));
            }
            display = Some(attr.parse_args()?);
        }
    }

    Ok(display)
}
<commit_msg>Resolve iter_skip_next lint<commit_after>use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
use quote::{format_ident, quote, ToTokens};
use std::iter::once;
use syn::parse::{Nothing, Parse, ParseStream};
use syn::{
    braced, bracketed, parenthesized, token, Attribute, Error, Field, Ident, Index, LitInt, LitStr,
    Result, Token,
};

pub struct Display {
    pub fmt: LitStr,
    pub args: TokenStream,
    pub was_shorthand: bool,
}

impl Parse for Display {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut display = Display {
            fmt: input.parse()?,
            args: parse_token_expr(input, false)?,
            was_shorthand: false,
        };
        display.expand_shorthand();
        Ok(display)
    }
}

fn parse_token_expr(input: ParseStream, mut last_is_comma: bool) -> Result<TokenStream> {
    let mut tokens = TokenStream::new();
    while !input.is_empty() {
        if last_is_comma && input.peek(Token![.]) {
            if input.peek2(Ident) {
                input.parse::<Token![.]>()?;
                last_is_comma = false;
                continue;
            }
            if input.peek2(LitInt) {
                input.parse::<Token![.]>()?;
                let int: Index = input.parse()?;
                let ident = format_ident!("_{}", int.index, span = int.span);
                tokens.extend(once(TokenTree::Ident(ident)));
                last_is_comma = false;
                continue;
            }
        }
        last_is_comma = input.peek(Token![,]);
        let token: TokenTree = if input.peek(token::Paren) {
            let content;
            let delimiter = parenthesized!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Parenthesis, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else if input.peek(token::Brace) {
            let content;
            let delimiter = braced!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Brace, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else if input.peek(token::Bracket) {
            let content;
            let delimiter = bracketed!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Bracket, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else {
            input.parse()?
        };
        tokens.extend(once(token));
    }
    Ok(tokens)
}

impl ToTokens for Display {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let fmt = &self.fmt;
        let args = &self.args;
        if self.was_shorthand && fmt.value() == "{}" {
            let arg = args.clone().into_iter().nth(1).unwrap();
            tokens.extend(quote! {
                std::fmt::Display::fmt(#arg, formatter)
            });
        } else if self.was_shorthand && fmt.value() == "{:?}" {
            let arg = args.clone().into_iter().nth(1).unwrap();
            tokens.extend(quote! {
                std::fmt::Debug::fmt(#arg, formatter)
            });
        } else {
            tokens.extend(quote! {
                write!(formatter, #fmt #args)
            });
        }
    }
}

pub fn is_source(field: &Field) -> Result<bool> {
    for attr in &field.attrs {
        if attr.path.is_ident("source") {
            syn::parse2::<Nothing>(attr.tokens.clone())?;
            return Ok(true);
        }
    }
    Ok(false)
}

pub fn display(attrs: &[Attribute]) -> Result<Option<Display>> {
    let mut display = None;

    for attr in attrs {
        if attr.path.is_ident("error") {
            if display.is_some() {
                return Err(Error::new_spanned(
                    attr,
                    "only one #[error(...)] attribute is allowed",
                ));
            }
            display = Some(attr.parse_args()?);
        }
    }

    Ok(display)
}
<|endoftext|>


<commit_before>//! The rusty-machine crate.
//!
//! Crate built for machine learning with some linear algebra thrown in.

extern crate num as libnum;
extern crate rand;

/// Module for linear algebra.
pub mod linalg {

    /// Trait for linear algebra metrics.
    ///
    /// Currently only implements basic euclidean norm.
    pub trait Metric<T> {

        /// Computes the euclidean norm.
        fn norm(&self) -> T;
	}

    pub mod matrix;
    pub mod vector;
    pub mod utils;
    pub mod macros;
}

/// Module for machine learning.
pub mod learning {
    pub mod lin_reg;
    pub mod k_means;
    pub mod nnet;
    pub mod gp;

    /// Trait for supervised model.
    pub trait SupModel<T,U> {

        /// Predict output from data.
        fn predict(&self, data: &T) -> U;

        /// Train the model using data and outputs.
        fn train(&mut self, data: &T, value: &U);
	}

    /// Trait for unsupervised model.
	pub trait UnSupModel<T, U> {

        /// Predict output from data.
        fn predict(&self, data: &T) -> U;

        /// Train the model using data.
        fn train(&mut self, data: &T);
	}

    /// Module for optimization in machine learning setting.
    pub mod optim {

        /// Trait for models which can be gradient-optimized.
        pub trait Optimizable {
            /// The input data type to the model.
            type Data;
            /// The target data type to the model.
            type Target;

            /// Compute the gradient for the model.
            fn compute_grad(&self, params: &[f64], data: &Self::Data, target: &Self::Target) -> Vec<f64>;
        }

        /// Trait for optimization algorithms.
        pub trait OptimAlgorithm<M : Optimizable> {

            /// Return the optimized parameter using gradient optimization.
            ///
            /// Takes in a set of starting parameters and related model data.
            fn optimize(&self, model: &M, start: &[f64], data: &M::Data, outputs: &M::Target) -> Vec<f64>;
        }

        pub mod grad_desc;
    }

    /// Module for learning tools.
    pub mod toolkit {
        pub mod link_fn;
        pub mod kernel;
    }
}
<commit_msg>Big chunk of crate level documentation.<commit_after>//! # The rusty-machine crate.
//!
//! Crate built for machine learning with some linear algebra thrown in.
//!
//! ---
//!
//! ## Structure
//!
//! The crate is made up of two primary modules: learning and linalg.
//!
//! ### learning
//!
//! The learning module contains all of the machine learning modules.
//! This means the algorithms, models and related tools.
//!
//! The currently supported techniques are:
//!
//! - Gaussian Process Regression
//! - K-means classification
//! - Linear Regression
//! - Neural Networks (simple feed forward).
//!
//! ### linalg
//!
//! The linalg module contains all of the linear algebra tools and structures.
//! This module is efficient but not state of the art. Development of this module
//! is not a key focus as I'm waiting for a clear community winner.
//!
//! ---
//!
//! # Usage
//!
//! Specific usage of modules is described within the modules themselves. This section
//! will focus on the general workflow for this library.
//!
//! The models contained within the learning module should implement either SupModel or UnSupModel.
//! These both provide a `train` and a `predict` function which provide an interface to the model.
//!
//! You should instantiate the model, with your chosen options and then train using the training data.
//! Followed by predicting with your test data. *For now* cross-validation, data handling, and many
//! other things are left explicitly to the user.
//!
//! Here is an example usage for Gaussian Process Regression:
//!
//! ```
//! use rusty_machine::linalg::matrix::Matrix;
//! use rusty_machine::learning::gp::GaussianProcess;
//! use rusty_machine::learning::gp::ConstMean;
//! use rusty_machine::learning::toolkit::kernel;
//! use rusty_machine::learning::SupModel;
//!
//! // Some example training data.
//! let train_data = Matrix::new(3,3,vec![1.,1.,1.,2.,2.,2.,3.,3.,3.]);
//! let train_outputs = Matrix::new(3,3, vec![0.,0.,0.,1.,1.,1.,0.,0.,0.]);
//!
//! // Some example test data.
//! let test_data = Matrix::new(2,3, vec![1.5,1.5,1.5,2.5,2.5,2.5]);
//!
//! // A squared exponential kernel with lengthscale 2, and amplitude 1.
//! let ker = kernel::SquaredExp::new(2., 1.);
//!
//! // The zero function
//! let zero_mean = ConstMean::default();
//!
//! // Construct a GP with the specified kernel, mean, and a noise of 0.5.
//! let mut gp = GaussianProcess::new(ker, zero_mean, 0.5);
//!
//! // Train the model!
//! gp.train(&train_data, &train_outputs);
//!
//! // Predict output from test data
//! let outputs = gp.predict(&test_data);
//! ```
//!
//! Of course this code could have been a lot simpler if we had simply adopted
//! `let mut gp = GaussianProcess::default();`. Conversely, you could also implement
//! your own kernels and mean functions by using the appropriate traits.

extern crate num as libnum;
extern crate rand;

/// Module for linear algebra.
pub mod linalg {

    /// Trait for linear algebra metrics.
    ///
    /// Currently only implements basic euclidean norm.
    pub trait Metric<T> {

        /// Computes the euclidean norm.
        fn norm(&self) -> T;
	}

    pub mod matrix;
    pub mod vector;
    pub mod utils;
    pub mod macros;
}

/// Module for machine learning.
pub mod learning {
    pub mod lin_reg;
    pub mod k_means;
    pub mod nnet;
    pub mod gp;

    /// Trait for supervised model.
    pub trait SupModel<T,U> {

        /// Predict output from data.
        fn predict(&self, data: &T) -> U;

        /// Train the model using data and outputs.
        fn train(&mut self, data: &T, value: &U);
	}

    /// Trait for unsupervised model.
	pub trait UnSupModel<T, U> {

        /// Predict output from data.
        fn predict(&self, data: &T) -> U;

        /// Train the model using data.
        fn train(&mut self, data: &T);
	}

    /// Module for optimization in machine learning setting.
    pub mod optim {

        /// Trait for models which can be gradient-optimized.
        pub trait Optimizable {
            /// The input data type to the model.
            type Data;
            /// The target data type to the model.
            type Target;

            /// Compute the gradient for the model.
            fn compute_grad(&self, params: &[f64], data: &Self::Data, target: &Self::Target) -> Vec<f64>;
        }

        /// Trait for optimization algorithms.
        pub trait OptimAlgorithm<M : Optimizable> {

            /// Return the optimized parameter using gradient optimization.
            ///
            /// Takes in a set of starting parameters and related model data.
            fn optimize(&self, model: &M, start: &[f64], data: &M::Data, outputs: &M::Target) -> Vec<f64>;
        }

        pub mod grad_desc;
    }

    /// Module for learning tools.
    pub mod toolkit {
        pub mod link_fn;
        pub mod kernel;
    }
}
<|endoftext|>


<commit_before>use crate::ty::subst::SubstsRef;
use crate::ty::{self, Ty, TyCtxt};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_macros::HashStable;
use rustc_span::Span;

#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
pub enum PointerCast {
    /// Go from a fn-item type to a fn-pointer type.
    ReifyFnPointer,

    /// Go from a safe fn pointer to an unsafe fn pointer.
    UnsafeFnPointer,

    /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
    /// It cannot convert a closure that requires unsafe.
    ClosureFnPointer(hir::Unsafety),

    /// Go from a mut raw pointer to a const raw pointer.
    MutToConstPointer,

    /// Go from `*const [T; N]` to `*const T`
    ArrayToPointer,

    /// Unsize a pointer/reference value, e.g., `&[T; n]` to
    /// `&[T]`. Note that the source could be a thin or fat pointer.
    /// This will do things like convert thin pointers to fat
    /// pointers, or convert structs containing thin pointers to
    /// structs containing fat pointers, or convert between fat
    /// pointers. We don't store the details of how the transform is
    /// done (in fact, we don't know that, because it might depend on
    /// the precise type parameters). We just store the target
    /// type. Codegen backends and miri figure out what has to be done
    /// based on the precise source/target type at hand.
    Unsize,
}

/// Represents coercing a value to a different type of value.
///
/// We transform values by following a number of `Adjust` steps in order.
/// See the documentation on variants of `Adjust` for more details.
///
/// Here are some common scenarios:
///
/// 1. The simplest cases are where a pointer is not adjusted fat vs thin.
///    Here the pointer will be dereferenced N times (where a dereference can
///    happen to raw or borrowed pointers or any smart pointer which implements
///    Deref, including Box<_>). The types of dereferences is given by
///    `autoderefs`. It can then be auto-referenced zero or one times, indicated
///    by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
///    `false`.
///
/// 2. A thin-to-fat coercion involves unsizing the underlying data. We start
///    with a thin pointer, deref a number of times, unsize the underlying data,
///    then autoref. The 'unsize' phase may change a fixed length array to a
///    dynamically sized one, a concrete object to a trait object, or statically
///    sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is
///    represented by:
///
///    ```
///    Deref(None) -> [i32; 4],
///    Borrow(AutoBorrow::Ref) -> &[i32; 4],
///    Unsize -> &[i32],
///    ```
///
///    Note that for a struct, the 'deep' unsizing of the struct is not recorded.
///    E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
///    The autoderef and -ref are the same as in the above example, but the type
///    stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
///    the underlying conversions from `[i32; 4]` to `[i32]`.
///
/// 3. Coercing a `Box<T>` to `Box<dyn Trait>` is an interesting special case. In
///    that case, we have the pointer we need coming in, so there are no
///    autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
///    At some point, of course, `Box` should move out of the compiler, in which
///    case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->
///    Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct Adjustment<'tcx> {
    pub kind: Adjust<'tcx>,
    pub target: Ty<'tcx>,
}

impl Adjustment<'tcx> {
    pub fn is_region_borrow(&self) -> bool {
        matches!(self.kind, Adjust::Borrow(AutoBorrow::Ref(..)))
    }
}

#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub enum Adjust<'tcx> {
    /// Go from ! to any type.
    NeverToAny,

    /// Dereference once, producing a place.
    Deref(Option<OverloadedDeref<'tcx>>),

    /// Take the address and produce either a `&` or `*` pointer.
    Borrow(AutoBorrow<'tcx>),

    Pointer(PointerCast),
}

/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.
/// The target type is `U` in both cases, with the region and mutability
/// being those shared by both the receiver and the returned reference.
#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct OverloadedDeref<'tcx> {
    pub region: ty::Region<'tcx>,
    pub mutbl: hir::Mutability,
    /// The `Span` associated with the field access or method call
    /// that triggered this overloaded deref.
    pub span: Span,
}

impl<'tcx> OverloadedDeref<'tcx> {
    pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) {
        let trait_def_id = match self.mutbl {
            hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None),
            hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None),
        };
        let method_def_id = tcx
            .associated_items(trait_def_id)
            .in_definition_order()
            .find(|m| m.kind == ty::AssocKind::Fn)
            .unwrap()
            .def_id;
        (method_def_id, tcx.mk_substs_trait(source, &[]))
    }
}

/// At least for initial deployment, we want to limit two-phase borrows to
/// only a few specific cases. Right now, those are mostly "things that desugar"
/// into method calls:
/// - using `x.some_method()` syntax, where some_method takes `&mut self`,
/// - using `Foo::some_method(&mut x, ...)` syntax,
/// - binary assignment operators (`+=`, `-=`, `*=`, etc.).
/// Anything else should be rejected until generalized two-phase borrow support
/// is implemented. Right now, dataflow can't handle the general case where there
/// is more than one use of a mutable borrow, and we don't want to accept too much
/// new code via two-phase borrows, so we try to limit where we create two-phase
/// capable mutable borrows.
/// See #49434 for tracking.
#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum AllowTwoPhase {
    Yes,
    No,
}

#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum AutoBorrowMutability {
    Mut { allow_two_phase_borrow: AllowTwoPhase },
    Not,
}

impl From<AutoBorrowMutability> for hir::Mutability {
    fn from(m: AutoBorrowMutability) -> Self {
        match m {
            AutoBorrowMutability::Mut { .. } => hir::Mutability::Mut,
            AutoBorrowMutability::Not => hir::Mutability::Not,
        }
    }
}

#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub enum AutoBorrow<'tcx> {
    /// Converts from T to &T.
    Ref(ty::Region<'tcx>, AutoBorrowMutability),

    /// Converts from T to *T.
    RawPtr(hir::Mutability),
}

/// Information for `CoerceUnsized` impls, storing information we
/// have computed about the coercion.
///
/// This struct can be obtained via the `coerce_impl_info` query.
/// Demanding this struct also has the side-effect of reporting errors
/// for inappropriate impls.
#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
pub struct CoerceUnsizedInfo {
    /// If this is a "custom coerce" impl, then what kind of custom
    /// coercion is it? This applies to impls of `CoerceUnsized` for
    /// structs, primarily, where we store a bit of info about which
    /// fields need to be coerced.
    pub custom_kind: Option<CustomCoerceUnsized>,
}

#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum CustomCoerceUnsized {
    /// Records the index of the field being coerced.
    Struct(usize),
}
<commit_msg>Add some backticks to the `rustc_middle::ty::adjustment::Adjustment` docs<commit_after>use crate::ty::subst::SubstsRef;
use crate::ty::{self, Ty, TyCtxt};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_macros::HashStable;
use rustc_span::Span;

#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
pub enum PointerCast {
    /// Go from a fn-item type to a fn-pointer type.
    ReifyFnPointer,

    /// Go from a safe fn pointer to an unsafe fn pointer.
    UnsafeFnPointer,

    /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
    /// It cannot convert a closure that requires unsafe.
    ClosureFnPointer(hir::Unsafety),

    /// Go from a mut raw pointer to a const raw pointer.
    MutToConstPointer,

    /// Go from `*const [T; N]` to `*const T`
    ArrayToPointer,

    /// Unsize a pointer/reference value, e.g., `&[T; n]` to
    /// `&[T]`. Note that the source could be a thin or fat pointer.
    /// This will do things like convert thin pointers to fat
    /// pointers, or convert structs containing thin pointers to
    /// structs containing fat pointers, or convert between fat
    /// pointers. We don't store the details of how the transform is
    /// done (in fact, we don't know that, because it might depend on
    /// the precise type parameters). We just store the target
    /// type. Codegen backends and miri figure out what has to be done
    /// based on the precise source/target type at hand.
    Unsize,
}

/// Represents coercing a value to a different type of value.
///
/// We transform values by following a number of `Adjust` steps in order.
/// See the documentation on variants of `Adjust` for more details.
///
/// Here are some common scenarios:
///
/// 1. The simplest cases are where a pointer is not adjusted fat vs thin.
///    Here the pointer will be dereferenced N times (where a dereference can
///    happen to raw or borrowed pointers or any smart pointer which implements
///    `Deref`, including `Box<_>`). The types of dereferences is given by
///    `autoderefs`. It can then be auto-referenced zero or one times, indicated
///    by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
///    `false`.
///
/// 2. A thin-to-fat coercion involves unsizing the underlying data. We start
///    with a thin pointer, deref a number of times, unsize the underlying data,
///    then autoref. The 'unsize' phase may change a fixed length array to a
///    dynamically sized one, a concrete object to a trait object, or statically
///    sized struct to a dynamically sized one. E.g., `&[i32; 4]` -> `&[i32]` is
///    represented by:
///
///    ```
///    Deref(None) -> [i32; 4],
///    Borrow(AutoBorrow::Ref) -> &[i32; 4],
///    Unsize -> &[i32],
///    ```
///
///    Note that for a struct, the 'deep' unsizing of the struct is not recorded.
///    E.g., `struct Foo<T> { x: T }` we can coerce `&Foo<[i32; 4]>` to `&Foo<[i32]>`
///    The autoderef and -ref are the same as in the above example, but the type
///    stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
///    the underlying conversions from `[i32; 4]` to `[i32]`.
///
/// 3. Coercing a `Box<T>` to `Box<dyn Trait>` is an interesting special case. In
///    that case, we have the pointer we need coming in, so there are no
///    autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
///    At some point, of course, `Box` should move out of the compiler, in which
///    case this is analogous to transforming a struct. E.g., `Box<[i32; 4]>` ->
///    `Box<[i32]>` is an `Adjust::Unsize` with the target `Box<[i32]>`.
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct Adjustment<'tcx> {
    pub kind: Adjust<'tcx>,
    pub target: Ty<'tcx>,
}

impl Adjustment<'tcx> {
    pub fn is_region_borrow(&self) -> bool {
        matches!(self.kind, Adjust::Borrow(AutoBorrow::Ref(..)))
    }
}

#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub enum Adjust<'tcx> {
    /// Go from ! to any type.
    NeverToAny,

    /// Dereference once, producing a place.
    Deref(Option<OverloadedDeref<'tcx>>),

    /// Take the address and produce either a `&` or `*` pointer.
    Borrow(AutoBorrow<'tcx>),

    Pointer(PointerCast),
}

/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.
/// The target type is `U` in both cases, with the region and mutability
/// being those shared by both the receiver and the returned reference.
#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct OverloadedDeref<'tcx> {
    pub region: ty::Region<'tcx>,
    pub mutbl: hir::Mutability,
    /// The `Span` associated with the field access or method call
    /// that triggered this overloaded deref.
    pub span: Span,
}

impl<'tcx> OverloadedDeref<'tcx> {
    pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) {
        let trait_def_id = match self.mutbl {
            hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None),
            hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None),
        };
        let method_def_id = tcx
            .associated_items(trait_def_id)
            .in_definition_order()
            .find(|m| m.kind == ty::AssocKind::Fn)
            .unwrap()
            .def_id;
        (method_def_id, tcx.mk_substs_trait(source, &[]))
    }
}

/// At least for initial deployment, we want to limit two-phase borrows to
/// only a few specific cases. Right now, those are mostly "things that desugar"
/// into method calls:
/// - using `x.some_method()` syntax, where some_method takes `&mut self`,
/// - using `Foo::some_method(&mut x, ...)` syntax,
/// - binary assignment operators (`+=`, `-=`, `*=`, etc.).
/// Anything else should be rejected until generalized two-phase borrow support
/// is implemented. Right now, dataflow can't handle the general case where there
/// is more than one use of a mutable borrow, and we don't want to accept too much
/// new code via two-phase borrows, so we try to limit where we create two-phase
/// capable mutable borrows.
/// See #49434 for tracking.
#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum AllowTwoPhase {
    Yes,
    No,
}

#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum AutoBorrowMutability {
    Mut { allow_two_phase_borrow: AllowTwoPhase },
    Not,
}

impl From<AutoBorrowMutability> for hir::Mutability {
    fn from(m: AutoBorrowMutability) -> Self {
        match m {
            AutoBorrowMutability::Mut { .. } => hir::Mutability::Mut,
            AutoBorrowMutability::Not => hir::Mutability::Not,
        }
    }
}

#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub enum AutoBorrow<'tcx> {
    /// Converts from T to &T.
    Ref(ty::Region<'tcx>, AutoBorrowMutability),

    /// Converts from T to *T.
    RawPtr(hir::Mutability),
}

/// Information for `CoerceUnsized` impls, storing information we
/// have computed about the coercion.
///
/// This struct can be obtained via the `coerce_impl_info` query.
/// Demanding this struct also has the side-effect of reporting errors
/// for inappropriate impls.
#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
pub struct CoerceUnsizedInfo {
    /// If this is a "custom coerce" impl, then what kind of custom
    /// coercion is it? This applies to impls of `CoerceUnsized` for
    /// structs, primarily, where we store a bit of info about which
    /// fields need to be coerced.
    pub custom_kind: Option<CustomCoerceUnsized>,
}

#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum CustomCoerceUnsized {
    /// Records the index of the field being coerced.
    Struct(usize),
}
<|endoftext|>


<commit_before>extern crate errno;

extern crate libc;

use super::constants::*;
use super::ffi::*;

use std::ffi::CString;
use std::os::unix::raw::{gid_t, uid_t};
use std::ptr;
use std::result;
use std::str;

pub type Error = errno::Errno;
pub type Result<T> = result::Result<T, Error>;

fn check_call<T>(res: libc::c_long, value: T) -> Result<T> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(value)
    }
}

fn check_call_ret(res: libc::c_long) -> Result<libc::c_long> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(res)
    }
}

fn get_keyring(id: KeyringSerial, create: bool) -> Result<Keyring> {
    let res = unsafe { keyctl_get_keyring_ID(id, create as libc::c_int) };
    check_call(res as libc::c_long, Keyring { id: res, })
}

pub struct Keyring {
    id: KeyringSerial,
}

impl Keyring {
    pub fn set_default(keyring: DefaultKeyring) -> Result<()> {
        check_call(unsafe { keyctl_set_reqkey_keyring(keyring.serial()) }, ())
    }

    pub fn attach(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, false)
    }

    pub fn attach_or_create(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, true)
    }

    pub fn join_anonymous_session() -> Result<Self> {
        let res = unsafe { keyctl_join_session_keyring(ptr::null()) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn join_session(name: &str) -> Result<Self> {
        let nameptr = CString::new(name).unwrap().as_ptr();
        let res = unsafe { keyctl_join_session_keyring(nameptr) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn clear(&mut self) -> Result<()> {
        check_call(unsafe { keyctl_clear(self.id) }, ())
    }

    pub fn link(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_link(key.id, self.id) }, ())
    }

    pub fn unlink(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_unlink(key.id, self.id) }, ())
    }

    pub fn search(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { keyctl_search(self.id, typeptr, descptr, self.id) };
        check_call(res, Key { id: res as key_serial_t, })
    }

    pub fn read(&self) -> Result<Vec<Key>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        // TODO: turn bytestream into vec of keys
        unimplemented!()
    }

    pub fn attach_persistent(&mut self) -> Result<Keyring> {
        let res = unsafe { keyctl_get_persistent(-1, self.id) };
        check_call(res, Keyring { id: res as key_serial_t, })
    }

    pub fn add_key(&mut self, description: &str, payload: &[u8]) -> Result<Key> {
        let typeptr = CString::new("user").unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, descptr, payload.as_ptr() as *const libc::c_void, payload.len(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn add_keyring(&mut self) -> Result<Keyring> {
        let typeptr = CString::new("keyring").unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, ptr::null(), ptr::null(), 0, self.id) };
        check_call(res as libc::c_long, Keyring { id: res, })
    }

    pub fn find_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { find_key_by_type_and_desc(typeptr, descptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, ptr::null(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key_with_fallback(&mut self, type_: &str, description: &str, info: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let infoptr = CString::new(info).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, infoptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }
}

pub struct Key {
    id: KeyringSerial,
}

extern fn unlink_cb(
    parent:     key_serial_t,
    key:        key_serial_t,
    desc:       *mut libc::c_char,
    desc_len:   libc::c_int,
    data:       *mut libc::c_void)
    -> libc::c_int {
    unimplemented!()
}

impl Key {
    pub fn request(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key(type_, description)
    }

    pub fn request_with_fallback(type_: &str, description: &str, info: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key_with_fallback(type_, description, info)
    }

    pub fn find(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.find_key(type_, description)
    }

    pub fn search(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.search(type_, description)
    }

    pub fn keyring(&self) -> Result<Keyring> {
        get_keyring(self.id, false)
    }

    pub fn update(&mut self, data: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_update(self.id, data.as_ptr() as *const libc::c_void, data.len()) }, ())
    }

    pub fn unlink_from(&mut self, keyring: &mut Keyring) -> usize {
        let data: *mut KeyringSerial = &mut self.id;
        let ret = unsafe { recursive_key_scan(keyring.id, unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn unlink_from_session(&mut self) -> usize {
        let data: *mut KeyringSerial = &mut self.id;
        let ret = unsafe { recursive_session_key_scan(unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn revoke(self) -> Result<()> {
        check_call(unsafe { keyctl_revoke(self.id) }, ())
    }

    pub fn chown(&mut self, uid: uid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, uid, -1) }, ())
    }

    pub fn chgrp(&mut self, gid: gid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, -1, gid) }, ())
    }

    pub fn set_permissions(&mut self, perms: KeyPermissions) -> Result<()> {
        check_call(unsafe { keyctl_setperm(self.id, perms) }, ())
    }

    pub fn description(&self) -> Result<KeyDescription> {
        self.description_raw().map(|desc| {
            KeyDescription::parse(desc)
        })
    }

    fn description_raw(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_describe(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_describe(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn read(&self) -> Result<Vec<u8>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        Ok(buffer)
    }

    pub fn set_timeout(&mut self, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_set_timeout(self.id, timeout) }, ())
    }

    pub fn get_security(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_get_security(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_get_security(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn invalidate(self) -> Result<()> {
        check_call(unsafe { keyctl_invalidate(self.id) }, ())
    }

    pub fn manage(&mut self) -> Result<KeyManager> {
        check_call(unsafe { keyctl_assume_authority(self.id) }, KeyManager {
            key: Key {
                id: self.id,
            },
        })
    }
}

pub struct KeyDescription {
    pub type_:          String,
    pub uid:            uid_t,
    pub gid:            gid_t,
    pub perms:          KeyPermissions,
    pub description:    String,
}

impl KeyDescription {
    fn parse(desc: String) -> KeyDescription {
        unimplemented!()
    }
}

pub struct KeyManager {
    key: Key,
}

impl KeyManager {
    pub fn instantiate(self, keyring: &Keyring, payload: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_instantiate(self.key.id, payload.as_ptr() as *const libc::c_void, payload.len(), keyring.id) }, ())
    }

    pub fn reject(self, keyring: &Keyring, timeout: u32, error: errno::Errno) -> Result<()> {
        let errno::Errno(errval) = error;
        check_call(unsafe { keyctl_reject(self.key.id, timeout, errval as u32, keyring.id) }, ())
    }

    pub fn negate(self, keyring: &Keyring, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_negate(self.key.id, timeout, keyring.id) }, ())
    }
}
<commit_msg>api: move unlink to the key<commit_after>extern crate errno;

extern crate libc;

use super::constants::*;
use super::ffi::*;

use std::ffi::CString;
use std::os::unix::raw::{gid_t, uid_t};
use std::ptr;
use std::result;
use std::str;

pub type Error = errno::Errno;
pub type Result<T> = result::Result<T, Error>;

fn check_call<T>(res: libc::c_long, value: T) -> Result<T> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(value)
    }
}

fn check_call_ret(res: libc::c_long) -> Result<libc::c_long> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(res)
    }
}

fn get_keyring(id: KeyringSerial, create: bool) -> Result<Keyring> {
    let res = unsafe { keyctl_get_keyring_ID(id, create as libc::c_int) };
    check_call(res as libc::c_long, Keyring { id: res, })
}

pub struct Keyring {
    id: KeyringSerial,
}

impl Keyring {
    pub fn set_default(keyring: DefaultKeyring) -> Result<()> {
        check_call(unsafe { keyctl_set_reqkey_keyring(keyring.serial()) }, ())
    }

    pub fn attach(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, false)
    }

    pub fn attach_or_create(id: KeyringSerial) -> Result<Self> {
        get_keyring(id, true)
    }

    pub fn join_anonymous_session() -> Result<Self> {
        let res = unsafe { keyctl_join_session_keyring(ptr::null()) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn join_session(name: &str) -> Result<Self> {
        let nameptr = CString::new(name).unwrap().as_ptr();
        let res = unsafe { keyctl_join_session_keyring(nameptr) };
        check_call(res as libc::c_long, Keyring { id: res })
    }

    pub fn clear(&mut self) -> Result<()> {
        check_call(unsafe { keyctl_clear(self.id) }, ())
    }

    pub fn link(&mut self, key: &Key) -> Result<()> {
        check_call(unsafe { keyctl_link(key.id, self.id) }, ())
    }

    pub fn search(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { keyctl_search(self.id, typeptr, descptr, self.id) };
        check_call(res, Key { id: res as key_serial_t, })
    }

    pub fn read(&self) -> Result<Vec<Key>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        // TODO: turn bytestream into vec of keys
        unimplemented!()
    }

    pub fn attach_persistent(&mut self) -> Result<Keyring> {
        let res = unsafe { keyctl_get_persistent(-1, self.id) };
        check_call(res, Keyring { id: res as key_serial_t, })
    }

    pub fn add_key(&mut self, description: &str, payload: &[u8]) -> Result<Key> {
        let typeptr = CString::new("user").unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, descptr, payload.as_ptr() as *const libc::c_void, payload.len(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn add_keyring(&mut self) -> Result<Keyring> {
        let typeptr = CString::new("keyring").unwrap().as_ptr();
        let res = unsafe { add_key(typeptr, ptr::null(), ptr::null(), 0, self.id) };
        check_call(res as libc::c_long, Keyring { id: res, })
    }

    pub fn find_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { find_key_by_type_and_desc(typeptr, descptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key(&mut self, type_: &str, description: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, ptr::null(), self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }

    pub fn request_key_with_fallback(&mut self, type_: &str, description: &str, info: &str) -> Result<Key> {
        let typeptr = CString::new(type_).unwrap().as_ptr();
        let descptr = CString::new(description).unwrap().as_ptr();
        let infoptr = CString::new(info).unwrap().as_ptr();
        let res = unsafe { request_key(typeptr, descptr, infoptr, self.id) };
        check_call(res as libc::c_long, Key { id: res, })
    }
}

pub struct Key {
    id: KeyringSerial,
}

extern fn unlink_cb(
    parent:     key_serial_t,
    key:        key_serial_t,
    desc:       *mut libc::c_char,
    desc_len:   libc::c_int,
    data:       *mut libc::c_void)
    -> libc::c_int {
    unimplemented!()
}

impl Key {
    pub fn request(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key(type_, description)
    }

    pub fn request_with_fallback(type_: &str, description: &str, info: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.request_key_with_fallback(type_, description, info)
    }

    pub fn find(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.find_key(type_, description)
    }

    pub fn search(type_: &str, description: &str) -> Result<Key> {
        let mut keyring = Keyring { id: 0, };
        keyring.search(type_, description)
    }

    pub fn keyring(&self) -> Result<Keyring> {
        get_keyring(self.id, false)
    }

    pub fn update(&mut self, data: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_update(self.id, data.as_ptr() as *const libc::c_void, data.len()) }, ())
    }

    pub fn unlink(self, keyring: &Keyring) -> Result<()> {
        check_call(unsafe { keyctl_unlink(self.id, keyring.id) }, ())
    }

    pub fn unlink_from(&mut self, keyring: &mut Keyring) -> usize {
        let data: *mut KeyringSerial = &mut self.id;
        let ret = unsafe { recursive_key_scan(keyring.id, unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn unlink_from_session(&mut self) -> usize {
        let data: *mut KeyringSerial = &mut self.id;
        let ret = unsafe { recursive_session_key_scan(unlink_cb, data as *mut libc::c_void) };
        ret as usize
    }

    pub fn revoke(self) -> Result<()> {
        check_call(unsafe { keyctl_revoke(self.id) }, ())
    }

    pub fn chown(&mut self, uid: uid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, uid, -1) }, ())
    }

    pub fn chgrp(&mut self, gid: gid_t) -> Result<()> {
        check_call(unsafe { keyctl_chown(self.id, -1, gid) }, ())
    }

    pub fn set_permissions(&mut self, perms: KeyPermissions) -> Result<()> {
        check_call(unsafe { keyctl_setperm(self.id, perms) }, ())
    }

    pub fn description(&self) -> Result<KeyDescription> {
        self.description_raw().map(|desc| {
            KeyDescription::parse(desc)
        })
    }

    fn description_raw(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_describe(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_describe(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn read(&self) -> Result<Vec<u8>> {
        let sz = try!(check_call_ret(unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_read(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        Ok(buffer)
    }

    pub fn set_timeout(&mut self, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_set_timeout(self.id, timeout) }, ())
    }

    pub fn get_security(&self) -> Result<String> {
        let sz = try!(check_call_ret(unsafe { keyctl_get_security(self.id, ptr::null_mut(), 0) }));
        let mut buffer = Vec::with_capacity(sz as usize);
        try!(check_call_ret(unsafe { keyctl_get_security(self.id, buffer.as_mut_ptr() as *mut libc::c_char, sz as usize) }));
        let str_slice = str::from_utf8(&buffer[..]).unwrap();
        Ok(str_slice.to_owned())
    }

    pub fn invalidate(self) -> Result<()> {
        check_call(unsafe { keyctl_invalidate(self.id) }, ())
    }

    pub fn manage(&mut self) -> Result<KeyManager> {
        check_call(unsafe { keyctl_assume_authority(self.id) }, KeyManager {
            key: Key {
                id: self.id,
            },
        })
    }
}

pub struct KeyDescription {
    pub type_:          String,
    pub uid:            uid_t,
    pub gid:            gid_t,
    pub perms:          KeyPermissions,
    pub description:    String,
}

impl KeyDescription {
    fn parse(desc: String) -> KeyDescription {
        unimplemented!()
    }
}

pub struct KeyManager {
    key: Key,
}

impl KeyManager {
    pub fn instantiate(self, keyring: &Keyring, payload: &[u8]) -> Result<()> {
        check_call(unsafe { keyctl_instantiate(self.key.id, payload.as_ptr() as *const libc::c_void, payload.len(), keyring.id) }, ())
    }

    pub fn reject(self, keyring: &Keyring, timeout: u32, error: errno::Errno) -> Result<()> {
        let errno::Errno(errval) = error;
        check_call(unsafe { keyctl_reject(self.key.id, timeout, errval as u32, keyring.id) }, ())
    }

    pub fn negate(self, keyring: &Keyring, timeout: u32) -> Result<()> {
        check_call(unsafe { keyctl_negate(self.key.id, timeout, keyring.id) }, ())
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use display_list::{AuxiliaryLists, AuxiliaryListsDescriptor, BuiltDisplayList};
use display_list::{BuiltDisplayListDescriptor};
use euclid::{Point2D, Size2D};
use ipc_channel::ipc::{self, IpcBytesSender, IpcSender};
use stacking_context::StackingContext;
use std::cell::Cell;
use types::{ColorF, DisplayListId, Epoch, FontKey, StackingContextId};
use types::{ImageKey, ImageFormat, NativeFontHandle, PipelineId};
use webgl::{WebGLContextId, WebGLCommand};
use offscreen_gl_context::GLContextAttributes;

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct IdNamespace(pub u32);

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct ResourceId(pub u32);

#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum ScrollEventPhase {
    /// The user started scrolling.
    Start,
    /// The user performed a scroll. The Boolean flag indicates whether the user's fingers are
    /// down, if a touchpad is in use. (If false, the event is a touchpad fling.)
    Move(bool),
    /// The user ended scrolling.
    End,
}

#[derive(Serialize, Deserialize)]
pub enum ApiMsg {
    AddRawFont(FontKey, Vec<u8>),
    AddNativeFont(FontKey, NativeFontHandle),
    AddImage(ImageKey, u32, u32, ImageFormat, Vec<u8>),
    UpdateImage(ImageKey, u32, u32, ImageFormat, Vec<u8>),
    CloneApi(IpcSender<IdNamespace>),
    /// Supplies a new frame to WebRender.
    ///
    /// The first `StackingContextId` describes the root stacking context. The actual stacking
    /// contexts are supplied as the sixth parameter, while the display lists that make up those
    /// stacking contexts are supplied as the seventh parameter.
    ///
    /// After receiving this message, WebRender will read the display lists, followed by the
    /// auxiliary lists, from the payload channel.
    SetRootStackingContext(StackingContextId,
                           ColorF,
                           Epoch,
                           PipelineId,
                           Size2D<f32>,
                           Vec<(StackingContextId, StackingContext)>,
                           Vec<(DisplayListId, BuiltDisplayListDescriptor)>,
                           AuxiliaryListsDescriptor),
    SetRootPipeline(PipelineId),
    Scroll(Point2D<f32>, Point2D<f32>, ScrollEventPhase),
    TickScrollingBounce,
    TranslatePointToLayerSpace(Point2D<f32>, IpcSender<Point2D<f32>>),
    RequestWebGLContext(Size2D<i32>, GLContextAttributes, IpcSender<Result<WebGLContextId, String>>),
    WebGLCommand(WebGLContextId, WebGLCommand),
}

#[derive(Serialize, Deserialize, Clone)]
pub struct RenderApiSender {
    api_sender: IpcSender<ApiMsg>,
    payload_sender: IpcBytesSender,
}

impl RenderApiSender {
    pub fn new(api_sender: IpcSender<ApiMsg>, payload_sender: IpcBytesSender) -> RenderApiSender {
        RenderApiSender {
            api_sender: api_sender,
            payload_sender: payload_sender,
        }
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender {
            ref api_sender,
            ref payload_sender
        } = *self;
        let (sync_tx, sync_rx) = ipc::channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        api_sender.send(msg).unwrap();
        RenderApi {
            api_sender: api_sender.clone(),
            payload_sender: payload_sender.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub api_sender: IpcSender<ApiMsg>,
    pub payload_sender: IpcBytesSender,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     format: ImageFormat,
                     bytes: Vec<u8>) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
    }

    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.api_sender.send(msg).unwrap();
    }

    /// Supplies a new frame to WebRender.
    ///
    /// Arguments:
    /// * `stacking_context_id`: The ID of the root stacking context.
    /// * `background_color`: The background color of this pipeline.
    /// * `epoch`: A monotonically increasing timestamp.
    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
    /// * `viewport_size`: The size of the viewport for this frame.
    /// * `stacking_contexts`: Stacking contexts used in this frame.
    /// * `display_lists`: Display lists used in this frame.
    /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
    pub fn set_root_stacking_context(&self,
                                     stacking_context_id: StackingContextId,
                                     background_color: ColorF,
                                     epoch: Epoch,
                                     pipeline_id: PipelineId,
                                     viewport_size: Size2D<f32>,
                                     stacking_contexts: Vec<(StackingContextId, StackingContext)>,
                                     display_lists: Vec<(DisplayListId, BuiltDisplayList)>,
                                     auxiliary_lists: AuxiliaryLists) {
        let display_list_descriptors = display_lists.iter().map(|&(display_list_id,
                                                                   ref built_display_list)| {
            (display_list_id, (*built_display_list.descriptor()).clone())
        }).collect();
        let msg = ApiMsg::SetRootStackingContext(stacking_context_id,
                                                 background_color,
                                                 epoch,
                                                 pipeline_id,
                                                 viewport_size,
                                                 stacking_contexts,
                                                 display_list_descriptors,
                                                 *auxiliary_lists.descriptor());
        self.api_sender.send(msg).unwrap();

        for &(_, ref built_display_list) in &display_lists {
            self.payload_sender.send(built_display_list.data()).unwrap();
        }

        self.payload_sender.send(auxiliary_lists.data()).unwrap();
    }

    pub fn scroll(&self, delta: Point2D<f32>, cursor: Point2D<f32>, phase: ScrollEventPhase) {
        let msg = ApiMsg::Scroll(delta, cursor, phase);
        self.api_sender.send(msg).unwrap();
    }

    pub fn tick_scrolling_bounce_animations(&self) {
        let msg = ApiMsg::TickScrollingBounce;
        self.api_sender.send(msg).unwrap();
    }

    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>) -> Point2D<f32> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn request_webgl_context(&self, size: &Size2D<i32>, attributes: GLContextAttributes)
                                 -> Result<WebGLContextId, String> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
        let msg = ApiMsg::WebGLCommand(context_id, command);
        self.api_sender.send(msg).unwrap();
    }

    #[inline]
    pub fn next_stacking_context_id(&self) -> StackingContextId {
        let new_id = self.next_unique_id();
        StackingContextId(new_id.0, new_id.1)
    }

    #[inline]
    pub fn next_display_list_id(&self) -> DisplayListId {
        let new_id = self.next_unique_id();
        DisplayListId(new_id.0, new_id.1)
    }

    #[inline]
    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}

<commit_msg>webgl: Make the RequestWebGLContext return the GLLimits structure<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use display_list::{AuxiliaryLists, AuxiliaryListsDescriptor, BuiltDisplayList};
use display_list::{BuiltDisplayListDescriptor};
use euclid::{Point2D, Size2D};
use ipc_channel::ipc::{self, IpcBytesSender, IpcSender};
use stacking_context::StackingContext;
use std::cell::Cell;
use types::{ColorF, DisplayListId, Epoch, FontKey, StackingContextId};
use types::{ImageKey, ImageFormat, NativeFontHandle, PipelineId};
use webgl::{WebGLContextId, WebGLCommand};
use offscreen_gl_context::{GLContextAttributes, GLLimits};

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct IdNamespace(pub u32);

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct ResourceId(pub u32);

#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum ScrollEventPhase {
    /// The user started scrolling.
    Start,
    /// The user performed a scroll. The Boolean flag indicates whether the user's fingers are
    /// down, if a touchpad is in use. (If false, the event is a touchpad fling.)
    Move(bool),
    /// The user ended scrolling.
    End,
}

#[derive(Serialize, Deserialize)]
pub enum ApiMsg {
    AddRawFont(FontKey, Vec<u8>),
    AddNativeFont(FontKey, NativeFontHandle),
    AddImage(ImageKey, u32, u32, ImageFormat, Vec<u8>),
    UpdateImage(ImageKey, u32, u32, ImageFormat, Vec<u8>),
    CloneApi(IpcSender<IdNamespace>),
    /// Supplies a new frame to WebRender.
    ///
    /// The first `StackingContextId` describes the root stacking context. The actual stacking
    /// contexts are supplied as the sixth parameter, while the display lists that make up those
    /// stacking contexts are supplied as the seventh parameter.
    ///
    /// After receiving this message, WebRender will read the display lists, followed by the
    /// auxiliary lists, from the payload channel.
    SetRootStackingContext(StackingContextId,
                           ColorF,
                           Epoch,
                           PipelineId,
                           Size2D<f32>,
                           Vec<(StackingContextId, StackingContext)>,
                           Vec<(DisplayListId, BuiltDisplayListDescriptor)>,
                           AuxiliaryListsDescriptor),
    SetRootPipeline(PipelineId),
    Scroll(Point2D<f32>, Point2D<f32>, ScrollEventPhase),
    TickScrollingBounce,
    TranslatePointToLayerSpace(Point2D<f32>, IpcSender<Point2D<f32>>),
    RequestWebGLContext(Size2D<i32>, GLContextAttributes, IpcSender<Result<(WebGLContextId, GLLimits), String>>),
    WebGLCommand(WebGLContextId, WebGLCommand),
}

#[derive(Serialize, Deserialize, Clone)]
pub struct RenderApiSender {
    api_sender: IpcSender<ApiMsg>,
    payload_sender: IpcBytesSender,
}

impl RenderApiSender {
    pub fn new(api_sender: IpcSender<ApiMsg>, payload_sender: IpcBytesSender) -> RenderApiSender {
        RenderApiSender {
            api_sender: api_sender,
            payload_sender: payload_sender,
        }
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender {
            ref api_sender,
            ref payload_sender
        } = *self;
        let (sync_tx, sync_rx) = ipc::channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        api_sender.send(msg).unwrap();
        RenderApi {
            api_sender: api_sender.clone(),
            payload_sender: payload_sender.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub api_sender: IpcSender<ApiMsg>,
    pub payload_sender: IpcBytesSender,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     format: ImageFormat,
                     bytes: Vec<u8>) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
    }

    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.api_sender.send(msg).unwrap();
    }

    /// Supplies a new frame to WebRender.
    ///
    /// Arguments:
    /// * `stacking_context_id`: The ID of the root stacking context.
    /// * `background_color`: The background color of this pipeline.
    /// * `epoch`: A monotonically increasing timestamp.
    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
    /// * `viewport_size`: The size of the viewport for this frame.
    /// * `stacking_contexts`: Stacking contexts used in this frame.
    /// * `display_lists`: Display lists used in this frame.
    /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
    pub fn set_root_stacking_context(&self,
                                     stacking_context_id: StackingContextId,
                                     background_color: ColorF,
                                     epoch: Epoch,
                                     pipeline_id: PipelineId,
                                     viewport_size: Size2D<f32>,
                                     stacking_contexts: Vec<(StackingContextId, StackingContext)>,
                                     display_lists: Vec<(DisplayListId, BuiltDisplayList)>,
                                     auxiliary_lists: AuxiliaryLists) {
        let display_list_descriptors = display_lists.iter().map(|&(display_list_id,
                                                                   ref built_display_list)| {
            (display_list_id, (*built_display_list.descriptor()).clone())
        }).collect();
        let msg = ApiMsg::SetRootStackingContext(stacking_context_id,
                                                 background_color,
                                                 epoch,
                                                 pipeline_id,
                                                 viewport_size,
                                                 stacking_contexts,
                                                 display_list_descriptors,
                                                 *auxiliary_lists.descriptor());
        self.api_sender.send(msg).unwrap();

        for &(_, ref built_display_list) in &display_lists {
            self.payload_sender.send(built_display_list.data()).unwrap();
        }

        self.payload_sender.send(auxiliary_lists.data()).unwrap();
    }

    pub fn scroll(&self, delta: Point2D<f32>, cursor: Point2D<f32>, phase: ScrollEventPhase) {
        let msg = ApiMsg::Scroll(delta, cursor, phase);
        self.api_sender.send(msg).unwrap();
    }

    pub fn tick_scrolling_bounce_animations(&self) {
        let msg = ApiMsg::TickScrollingBounce;
        self.api_sender.send(msg).unwrap();
    }

    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>) -> Point2D<f32> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn request_webgl_context(&self, size: &Size2D<i32>, attributes: GLContextAttributes)
                                 -> Result<(WebGLContextId, GLLimits), String> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
        let msg = ApiMsg::WebGLCommand(context_id, command);
        self.api_sender.send(msg).unwrap();
    }

    #[inline]
    pub fn next_stacking_context_id(&self) -> StackingContextId {
        let new_id = self.next_unique_id();
        StackingContextId(new_id.0, new_id.1)
    }

    #[inline]
    pub fn next_display_list_id(&self) -> DisplayListId {
        let new_id = self.next_unique_id();
        DisplayListId(new_id.0, new_id.1)
    }

    #[inline]
    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}

<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use hex::encode;
use ligature::{Attribute, Entity, Statement, Value, Bytes};

/// Writes out an Entity to a String.
pub fn write_entity(entity: &Entity) -> String {
    format!("<{}>", entity.id())
}

pub fn write_attribute(attribute: &Attribute) -> String {
    format!("@<{}>", attribute.name())
}

pub fn write_value(value: &Value) -> String {
    match value {
        Value::Entity(entity) => write_entity(entity),
        Value::IntegerLiteral(integer) => write_integer(integer),
        Value::FloatLiteral(float) => write_float(float),
        Value::StringLiteral(string) => write_string(string),
        Value::BytesLiteral(bytes) => write_bytes(bytes),
    }
}

pub fn write_integer(integer: &i64) -> String {
    format!("{}", integer)
}

pub fn write_float(float: &f64) -> String {
    let res = format!("{}", float);
    if res.contains(".") {
        res
    } else {
        res + ".0"
    }
}

pub fn write_string(string: &str) -> String {
    format!("\"{}\"", string) //TODO doesn't escape
}

pub fn write_bytes(bytes: &Bytes) -> String {
    format!("0x{}", encode(bytes))
}

pub fn write_statement(statement: &Statement) -> String {
    format!(
        "{} {} {} {}\n",
        write_entity(&statement.entity),
        write_attribute(&statement.attribute),
        write_value(&statement.value),
        write_entity(&statement.context)
    )
}

pub fn write(statements: std::slice::Iter<Statement>) -> String {
    let mut result = String::new();
    for statement in statements {
        result += &*write_statement(statement);
    }
    result
}
<commit_msg>improving write_string<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use hex::encode;
use ligature::{Attribute, Entity, Statement, Value, Bytes};

/// Writes out an Entity to a String.
pub fn write_entity(entity: &Entity) -> String {
    format!("<{}>", entity.id())
}

pub fn write_attribute(attribute: &Attribute) -> String {
    format!("@<{}>", attribute.name())
}

pub fn write_value(value: &Value) -> String {
    match value {
        Value::Entity(entity) => write_entity(entity),
        Value::IntegerLiteral(integer) => write_integer(integer),
        Value::FloatLiteral(float) => write_float(float),
        Value::StringLiteral(string) => write_string(string),
        Value::BytesLiteral(bytes) => write_bytes(bytes),
    }
}

pub fn write_integer(integer: &i64) -> String {
    format!("{}", integer)
}

pub fn write_float(float: &f64) -> String {
    let res = format!("{}", float);
    if res.contains(".") {
        res
    } else {
        res + ".0"
    }
}

pub fn write_string(string: &str) -> String {
    //TODO this could be done better
    let escaped_string = string.replace("\"", "\\\"")
        //.replace("\f", "\\b") <-- TODO not sure how to handle this or if I really need to
        //.replace("\b", "\\b") <-- TODO not sure how to handle this or if I really need to
        .replace("\n", "\\n")
        .replace("\r", "\\r")
        .replace("\t", "\\t")
        .replace("\\", "\\\\");
    format!("\"{}\"", escaped_string)
}

pub fn write_bytes(bytes: &Bytes) -> String {
    format!("0x{}", encode(bytes))
}

pub fn write_statement(statement: &Statement) -> String {
    format!(
        "{} {} {} {}\n",
        write_entity(&statement.entity),
        write_attribute(&statement.attribute),
        write_value(&statement.value),
        write_entity(&statement.context)
    )
}

pub fn write(statements: std::slice::Iter<Statement>) -> String {
    let mut result = String::new();
    for statement in statements {
        result += &*write_statement(statement);
    }
    result
}
<|endoftext|>