<commit_before>//! Licensed under the Apache License, Version 2.0
//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license
//! http://opensource.org/licenses/MIT, at your
//! option. This file may not be copied, modified, or distributed
//! except according to those terms.

use std::kinds;
use std::mem;
use std::num;
use std::ptr;
use std::fmt;

/// Similar to the slice iterator, but with a certain number of steps
/// (stride) skipped per iteration.
///
/// Does not support zero-sized `A`.
///
/// Iterator element type is `&'a A`
pub struct Stride<'a, A> {
    // begin is NULL when the iterator is exhausted, because
    // both begin and end are inclusive endpoints.
    begin: *const A,
    // Unlike the slice iterator, end is inclusive and the last
    // pointer we will visit. This makes it possible to have
    // safe stride iterators for columns in matrices etc.
    end: *const A,
    stride: int,
    life: kinds::marker::ContravariantLifetime<'a>,
}

/// Stride with mutable elements
///
/// Iterator element type is `&'a mut A`
pub struct StrideMut<'a, A> {
    begin: *mut A,
    end: *mut A,
    stride: int,
    life: kinds::marker::ContravariantLifetime<'a>,
    nocopy: kinds::marker::NoCopy
}

impl<'a, A> Stride<'a, A>
{
    /// Create Stride iterator from a slice and the element step count
    ///
    /// ## Example
    ///
    /// ```
    /// let xs = [0i, 1, 2, 3, 4, 5];
    /// let mut iter = Stride::from_slice(xs.as_slice(), 2);
    /// ```
    pub fn from_slice(xs: &'a [A], step: uint) -> Stride<'a, A>
    {
        assert!(step != 0);
        assert!(mem::size_of::<A>() != 0);
        let mut begin = ptr::null();
        let mut end = ptr::null();
        let (d, r) = num::div_rem(xs.len(), step);
        let nelem = d + if r > 0 { 1 } else { 0 };
        unsafe {
            if nelem != 0 {
                begin = xs.as_ptr();
                end = begin.offset(((nelem - 1) * step) as int);
            }
            Stride::from_ptrs(begin, end, step as int)
        }
    }

    /// Create Stride iterator from raw pointers from the *inclusive*
    /// pointer range [begin, end].
    ///
    /// **Note:** `end` **must** be a whole number of `stride` steps away
    /// from `begin`
    pub unsafe fn from_ptrs(begin: *const A, end: *const A, stride: int) -> Stride<'a, A>
    {
        Stride {
            begin: begin,
            end: end,
            stride: stride,
            life: kinds::marker::ContravariantLifetime,
        }
    }

    /// Create Stride iterator from an existing Stride iterator
    pub fn from_stride(it: Stride<'a, A>, step: uint) -> Stride<'a, A>
    {
        assert!(step != 0);
        let newstride = it.stride * (step as int);
        let begin = it.begin;
        let mut end = it.end;
        unsafe {
            if !begin.is_null() {
                let nelem = (end as int - begin as int)
                            / (mem::size_of::<A>() as int)
                            / newstride;

                end = begin.offset(nelem * newstride);
            }
            Stride::from_ptrs(begin, end, newstride)
        }
    }

    /// Swap the begin and end pointer and reverse the stride,
    /// in effect reversing the iterator.
    #[inline]
    pub fn swap_ends(&mut self) {
        if !self.begin.is_null() {
            mem::swap(&mut self.begin, &mut self.end);
            self.stride = -self.stride;
        }
    }
}

impl<'a, A> StrideMut<'a, A>
{
    /// Create Stride iterator from a slice and the element step count
    ///
    /// ## Example
    ///
    /// ```
    /// let xs = [0i, 1, 2, 3, 4, 5];
    /// let mut iter = StrideMut::from_slice(xs.as_slice(), 2);
    /// ```
    pub fn from_slice(xs: &'a mut [A], step: uint) -> StrideMut<'a, A>
    {
        assert!(step != 0);
        assert!(mem::size_of::<A>() != 0);
        let mut begin = ptr::mut_null();
        let mut end = ptr::mut_null();
        let (d, r) = num::div_rem(xs.len(), step);
        let nelem = d + if r > 0 { 1 } else { 0 };
        unsafe {
            if nelem != 0 {
                begin = xs.as_mut_ptr();
                end = begin.offset(((nelem - 1) * step) as int);
            }
            StrideMut::from_ptrs(begin, end, step as int)
        }
    }

    /// Create Stride iterator from raw pointers from the *inclusive*
    /// pointer range [begin, end].
    ///
    /// **Note:** `end` **must** be a whole number of `stride` steps away
    /// from `begin`
    pub unsafe fn from_ptrs(begin: *mut A, end: *mut A, stride: int) -> StrideMut<'a, A>
    {
        StrideMut {
            begin: begin,
            end: end,
            stride: stride,
            life: kinds::marker::ContravariantLifetime,
            nocopy: kinds::marker::NoCopy
        }
    }

    /// Create StrideMut iterator from an existing StrideMut iterator
    pub fn from_stride(it: StrideMut<'a, A>, step: uint) -> StrideMut<'a, A>
    {
        assert!(step != 0);
        let newstride = it.stride * (step as int);
        let begin = it.begin;
        let mut end = it.end;
        unsafe {
            if !begin.is_null() {
                let nelem = (end as int - begin as int)
                            / (mem::size_of::<A>() as int)
                            / newstride;

                end = begin.offset(nelem * newstride);
            }
            StrideMut::from_ptrs(begin, end, newstride)
        }
    }

    /// Swap the begin and end pointer and reverse the stride,
    /// in effect reversing the iterator.
    #[inline]
    pub fn swap_ends(&mut self) {
        if !self.begin.is_null() {
            mem::swap(&mut self.begin, &mut self.end);
            self.stride = -self.stride;
        }
    }
}
macro_rules! stride_iterator {
    (struct $name:ident -> $ptr:ty, $elem:ty, $null:expr) => {
        impl<'a, A> Iterator<$elem> for $name<'a, A>
        {
            #[inline]
            fn next(&mut self) -> Option<$elem>
            {
                if self.begin.is_null() {
                    None
                } else {
                    unsafe {
                        let elt: $elem = mem::transmute(self.begin);
                        if self.begin == self.end {
                            self.begin = $null;
                        } else {
                            self.begin = self.begin.offset(self.stride);
                        }
                        Some(elt)
                    }
                }
            }

            fn size_hint(&self) -> (uint, Option<uint>)
            {
                let len;
                if self.begin.is_null() {
                    len = 0;
                } else {
                    len = (self.end as uint - self.begin as uint) as int / self.stride
                        / mem::size_of::<A>() as int + 1;
                }

                (len as uint, Some(len as uint))
            }
        }

        impl<'a, A> DoubleEndedIterator<$elem> for $name<'a, A>
        {
            #[inline]
            fn next_back(&mut self) -> Option<$elem>
            {
                if self.begin.is_null() {
                    None
                } else {
                    unsafe {
                        let elt: $elem = mem::transmute(self.end);
                        if self.begin == self.end {
                            self.begin = $null;
                        } else {
                            self.end = self.end.offset(-self.stride);
                        }
                        Some(elt)
                    }
                }
            }
        }

        impl<'a, A> ExactSize<$elem> for $name<'a, A> { }

        impl<'a, A> Index<uint, A> for $name<'a, A>
        {
            fn index<'b>(&'b self, i: &uint) -> &'b A
            {
                assert!(*i < self.size_hint().val0());
                unsafe {
                    let ptr = self.begin.offset(self.stride * (*i as int));
                    mem::transmute(ptr)
                }
            }
        }
    }
}

stride_iterator!{struct Stride -> *const A, &'a A, ptr::null()}
stride_iterator!{struct StrideMut -> *mut A, &'a mut A, ptr::mut_null()}

impl<'a, A: fmt::Show> fmt::Show for Stride<'a, A>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        let it = *self;
        try!(write!(f, "["));
        for (i, elt) in it.enumerate() {
            if i != 0 {
                try!(write!(f, ", "));
            }
            try!(write!(f, "{}", *elt));
        }
        write!(f, "]")
    }
}

impl<'a, A> Clone for Stride<'a, A>
{
    fn clone(&self) -> Stride<'a, A>
    {
        *self
    }
}
<commit_msg>stride: Small simplification in iterator macro<commit_after>//! Licensed under the Apache License, Version 2.0
//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license
//! http://opensource.org/licenses/MIT, at your
//! option. This file may not be copied, modified, or distributed
//! except according to those terms.

use std::kinds;
use std::mem;
use std::num;
use std::ptr;
use std::fmt;

/// Similar to the slice iterator, but with a certain number of steps
/// (stride) skipped per iteration.
///
/// Does not support zero-sized `A`.
///
/// Iterator element type is `&'a A`
pub struct Stride<'a, A> {
    // begin is NULL when the iterator is exhausted, because
    // both begin and end are inclusive endpoints.
    begin: *const A,
    // Unlike the slice iterator, end is inclusive and the last
    // pointer we will visit. This makes it possible to have
    // safe stride iterators for columns in matrices etc.
    end: *const A,
    stride: int,
    life: kinds::marker::ContravariantLifetime<'a>,
}

/// Stride with mutable elements
///
/// Iterator element type is `&'a mut A`
pub struct StrideMut<'a, A> {
    begin: *mut A,
    end: *mut A,
    stride: int,
    life: kinds::marker::ContravariantLifetime<'a>,
    nocopy: kinds::marker::NoCopy
}

impl<'a, A> Stride<'a, A>
{
    /// Create Stride iterator from a slice and the element step count
    ///
    /// ## Example
    ///
    /// ```
    /// let xs = [0i, 1, 2, 3, 4, 5];
    /// let mut iter = Stride::from_slice(xs.as_slice(), 2);
    /// ```
    pub fn from_slice(xs: &'a [A], step: uint) -> Stride<'a, A>
    {
        assert!(step != 0);
        assert!(mem::size_of::<A>() != 0);
        let mut begin = ptr::null();
        let mut end = ptr::null();
        let (d, r) = num::div_rem(xs.len(), step);
        let nelem = d + if r > 0 { 1 } else { 0 };
        unsafe {
            if nelem != 0 {
                begin = xs.as_ptr();
                end = begin.offset(((nelem - 1) * step) as int);
            }
            Stride::from_ptrs(begin, end, step as int)
        }
    }

    /// Create Stride iterator from raw pointers from the *inclusive*
    /// pointer range [begin, end].
    ///
    /// **Note:** `end` **must** be a whole number of `stride` steps away
    /// from `begin`
    pub unsafe fn from_ptrs(begin: *const A, end: *const A, stride: int) -> Stride<'a, A>
    {
        Stride {
            begin: begin,
            end: end,
            stride: stride,
            life: kinds::marker::ContravariantLifetime,
        }
    }

    /// Create Stride iterator from an existing Stride iterator
    pub fn from_stride(it: Stride<'a, A>, step: uint) -> Stride<'a, A>
    {
        assert!(step != 0);
        let newstride = it.stride * (step as int);
        let begin = it.begin;
        let mut end = it.end;
        unsafe {
            if !begin.is_null() {
                let nelem = (end as int - begin as int)
                            / (mem::size_of::<A>() as int)
                            / newstride;

                end = begin.offset(nelem * newstride);
            }
            Stride::from_ptrs(begin, end, newstride)
        }
    }

    /// Swap the begin and end pointer and reverse the stride,
    /// in effect reversing the iterator.
    #[inline]
    pub fn swap_ends(&mut self) {
        if !self.begin.is_null() {
            mem::swap(&mut self.begin, &mut self.end);
            self.stride = -self.stride;
        }
    }
}

impl<'a, A> StrideMut<'a, A>
{
    /// Create Stride iterator from a slice and the element step count
    ///
    /// ## Example
    ///
    /// ```
    /// let xs = [0i, 1, 2, 3, 4, 5];
    /// let mut iter = StrideMut::from_slice(xs.as_slice(), 2);
    /// ```
    pub fn from_slice(xs: &'a mut [A], step: uint) -> StrideMut<'a, A>
    {
        assert!(step != 0);
        assert!(mem::size_of::<A>() != 0);
        let mut begin = ptr::mut_null();
        let mut end = ptr::mut_null();
        let (d, r) = num::div_rem(xs.len(), step);
        let nelem = d + if r > 0 { 1 } else { 0 };
        unsafe {
            if nelem != 0 {
                begin = xs.as_mut_ptr();
                end = begin.offset(((nelem - 1) * step) as int);
            }
            StrideMut::from_ptrs(begin, end, step as int)
        }
    }

    /// Create Stride iterator from raw pointers from the *inclusive*
    /// pointer range [begin, end].
    ///
    /// **Note:** `end` **must** be a whole number of `stride` steps away
    /// from `begin`
    pub unsafe fn from_ptrs(begin: *mut A, end: *mut A, stride: int) -> StrideMut<'a, A>
    {
        StrideMut {
            begin: begin,
            end: end,
            stride: stride,
            life: kinds::marker::ContravariantLifetime,
            nocopy: kinds::marker::NoCopy
        }
    }

    /// Create StrideMut iterator from an existing StrideMut iterator
    pub fn from_stride(it: StrideMut<'a, A>, step: uint) -> StrideMut<'a, A>
    {
        assert!(step != 0);
        let newstride = it.stride * (step as int);
        let begin = it.begin;
        let mut end = it.end;
        unsafe {
            if !begin.is_null() {
                let nelem = (end as int - begin as int)
                            / (mem::size_of::<A>() as int)
                            / newstride;

                end = begin.offset(nelem * newstride);
            }
            StrideMut::from_ptrs(begin, end, newstride)
        }
    }

    /// Swap the begin and end pointer and reverse the stride,
    /// in effect reversing the iterator.
    #[inline]
    pub fn swap_ends(&mut self) {
        if !self.begin.is_null() {
            mem::swap(&mut self.begin, &mut self.end);
            self.stride = -self.stride;
        }
    }
}

macro_rules! stride_iterator {
    (struct $name:ident -> $ptr:ty, $elem:ty) => {
        impl<'a, A> Iterator<$elem> for $name<'a, A>
        {
            #[inline]
            fn next(&mut self) -> Option<$elem>
            {
                if self.begin.is_null() {
                    None
                } else {
                    unsafe {
                        let elt: $elem = mem::transmute(self.begin);
                        if self.begin == self.end {
                            self.begin = RawPtr::null();
                        } else {
                            self.begin = self.begin.offset(self.stride);
                        }
                        Some(elt)
                    }
                }
            }

            fn size_hint(&self) -> (uint, Option<uint>)
            {
                let len;
                if self.begin.is_null() {
                    len = 0;
                } else {
                    len = (self.end as uint - self.begin as uint) as int / self.stride
                        / mem::size_of::<A>() as int + 1;
                }

                (len as uint, Some(len as uint))
            }
        }

        impl<'a, A> DoubleEndedIterator<$elem> for $name<'a, A>
        {
            #[inline]
            fn next_back(&mut self) -> Option<$elem>
            {
                if self.begin.is_null() {
                    None
                } else {
                    unsafe {
                        let elt: $elem = mem::transmute(self.end);
                        if self.begin == self.end {
                            self.begin = RawPtr::null();
                        } else {
                            self.end = self.end.offset(-self.stride);
                        }
                        Some(elt)
                    }
                }
            }
        }

        impl<'a, A> ExactSize<$elem> for $name<'a, A> { }

        impl<'a, A> Index<uint, A> for $name<'a, A>
        {
            fn index<'b>(&'b self, i: &uint) -> &'b A
            {
                assert!(*i < self.size_hint().val0());
                unsafe {
                    let ptr = self.begin.offset(self.stride * (*i as int));
                    mem::transmute(ptr)
                }
            }
        }
    }
}

stride_iterator!{struct Stride -> *const A, &'a A}
stride_iterator!{struct StrideMut -> *mut A, &'a mut A}

impl<'a, A: fmt::Show> fmt::Show for Stride<'a, A>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        let it = *self;
        try!(write!(f, "["));
        for (i, elt) in it.enumerate() {
            if i != 0 {
                try!(write!(f, ", "));
            }
            try!(write!(f, "{}", *elt));
        }
        write!(f, "]")
    }
}

impl<'a, A> Clone for Stride<'a, A>
{
    fn clone(&self) -> Stride<'a, A>
    {
        *self
    }
}
<|endoftext|>


<commit_before>use std::collections::{VecDeque};
use from_ascii::{FromAsciiRadix, ParseIntError};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        InvalidValue {
            from(ParseIntError)
        }
        UnexpectedEnd
    }
}

fn oct_to_digit(c: u8) -> Result<u8, Error> {
    Ok(match c {
        b'0' ... b'7' => c - b'0',
        _ => return Err(Error::InvalidValue),
    })
}

pub fn unescape(s: &[u8], unicode: bool) -> Result<Vec<u8>, Error> {
    let mut buf = Vec::with_capacity(s.len());
    let mut oct_buf = VecDeque::with_capacity(3);

    let mut i = 0;

    macro_rules! read {
        () => ({
            match s.get(i) {
                None => return Err(Error::UnexpectedEnd),
                Some(c) => {
                    i += 1;
                    *c
                }
            }
        })
    }

    macro_rules! peek {
        () => ({
            s.get(i).map(|c| *c)
        })
    }

    loop {
        if i >= s.len() {
            return Ok(buf)
        }

        let c = read!();

        if c != b'\\' {
            buf.push(c);
            continue
        }

        let marker = read!();

        match marker {
            b'\n' => (),
            b'\\' => buf.push(b'\\'),
            b'\'' => buf.push(b'\''),
            b'"' => buf.push(b'"'),
            b'a' => buf.push(b'\x07'),
            b'b' => buf.push(b'\x08'),
            b'f' => buf.push(b'\x0c'),
            b'n' => buf.push(b'\n'),
            b'r' => buf.push(b'\r'),
            b't' => buf.push(b'\t'),
            b'v' => buf.push(b'\x0b'),
            b'x' => {
                let hex_buf = [read!(), read!()];
                buf.push(try!(u8::from_ascii_radix(&hex_buf, 16)))
            }
            b'0' ... b'7' => {
                oct_buf.push_front(try!(oct_to_digit(marker)));
                peek!().and_then(|c| oct_to_digit(c).ok()).map(|s| {
                    oct_buf.push_front(s);
                    i += 1;

                    peek!().and_then(|c| oct_to_digit(c).ok()).map(|s| {
                        oct_buf.push_front(s);
                        i += 1;
                    });
                });
                let value = oct_buf.iter().enumerate().fold(0u16, |acc, (i, &v)| acc + v as u16 * (8u16.pow(i as u32)));
                oct_buf.clear();
                buf.push(if value > 255 {
                    255
                } else {
                    value as u8
                });
                continue
            },
            b'u' if unicode => unimplemented!(),
            b'U' if unicode => unimplemented!(),
            _ => {
                buf.push(b'\\');
                buf.push(marker);
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::{unescape};

    #[test]
    fn test_unescape() {
        assert_eq!(unescape(b"foo", false).unwrap(), b"foo");
        assert_eq!(unescape(b"f\\noo", false).unwrap(), b"f\noo");
        assert_eq!(unescape(b"f\\x01oo", false).unwrap(), b"f\x01oo");
        assert_eq!(unescape(b"f\\375oo", false).unwrap(), b"f\xfdoo");
        assert_eq!(unescape(b"f\\75oo", false).unwrap(), b"f\x3doo");
        assert_eq!(unescape(b"f\\5oo", false).unwrap(), b"f\x05oo");
        assert_eq!(unescape(b"f\\oo", false).unwrap(), b"f\\oo");
        assert_eq!(unescape(b"f\\coo", false).unwrap(), b"f\\coo");
    }
}<commit_msg>Use FromAsciiRadix in octal unescape<commit_after>use std::collections::{VecDeque};
use from_ascii::{FromAsciiRadix, ParseIntError};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        InvalidValue {
            from(ParseIntError)
        }
        UnexpectedEnd
    }
}

pub fn unescape(s: &[u8], unicode: bool) -> Result<Vec<u8>, Error> {
    let mut buf = Vec::with_capacity(s.len());
    let mut oct_buf = VecDeque::with_capacity(3);

    let mut i = 0;

    macro_rules! read {
        () => ({
            match s.get(i) {
                None => return Err(Error::UnexpectedEnd),
                Some(c) => {
                    i += 1;
                    *c
                }
            }
        })
    }

    macro_rules! peek {
        () => ({
            s.get(i).map(|c| *c)
        })
    }

    loop {
        if i >= s.len() {
            return Ok(buf)
        }

        let c = read!();

        if c != b'\\' {
            buf.push(c);
            continue
        }

        let marker = read!();

        match marker {
            b'\n' => (),
            b'\\' => buf.push(b'\\'),
            b'\'' => buf.push(b'\''),
            b'"' => buf.push(b'"'),
            b'a' => buf.push(b'\x07'),
            b'b' => buf.push(b'\x08'),
            b'f' => buf.push(b'\x0c'),
            b'n' => buf.push(b'\n'),
            b'r' => buf.push(b'\r'),
            b't' => buf.push(b'\t'),
            b'v' => buf.push(b'\x0b'),
            b'x' => {
                let hex_buf = [read!(), read!()];
                buf.push(try!(u8::from_ascii_radix(&hex_buf, 16)))
            }
            b'0' ... b'7' => {
                oct_buf.push_back(marker);
                peek!().map(|c| {
                    if c >= b'0' && c <= b'7' {
                        oct_buf.push_back(c);
                        i += 1;

                        peek!().map(|c| {
                            if c >= b'0' && c <= b'7' {
                                oct_buf.push_back(c);
                                i += 1;
                            }
                        });
                    }
                });

                let value = try!(u16::from_ascii_radix(oct_buf.as_slices().0, 8));
                oct_buf.clear();
                buf.push(if value > 255 {
                    255
                } else {
                    value as u8
                });
                continue
            },
            b'u' if unicode => unimplemented!(),
            b'U' if unicode => unimplemented!(),
            _ => {
                buf.push(b'\\');
                buf.push(marker);
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::{unescape};

    #[test]
    fn test_unescape() {
        assert_eq!(unescape(b"foo", false).unwrap(), b"foo");
        assert_eq!(unescape(b"f\\noo", false).unwrap(), b"f\noo");
        assert_eq!(unescape(b"f\\x01oo", false).unwrap(), b"f\x01oo");
        assert_eq!(unescape(b"f\\375oo", false).unwrap(), b"f\xfdoo");
        assert_eq!(unescape(b"f\\75oo", false).unwrap(), b"f\x3doo");
        assert_eq!(unescape(b"f\\5oo", false).unwrap(), b"f\x05oo");
        assert_eq!(unescape(b"f\\oo", false).unwrap(), b"f\\oo");
        assert_eq!(unescape(b"f\\coo", false).unwrap(), b"f\\coo");
    }
}<|endoftext|>


<commit_before>use std::net::IpAddr;
use std::path::PathBuf;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::os::unix::io::RawFd;

use regex::{Regex, Captures};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use quire::validate::{Structure, Sequence, Scalar, Numeric, Enum};
use quire::validate::{Mapping, Nothing, Anything};
use id_map::{IdMap, IdMapExt, mapping_validator};

use sandbox_config::SandboxConfig;
use utils::{in_range};

pub const DEFAULT_KILL_TIMEOUT: f32 = 5.;

lazy_static! {
    static ref VARIABLE_REGEX: Regex = Regex::new(r#"@\{([^}]*)\}"#).unwrap();
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq, Eq)]
pub struct TmpfsInfo {
    pub size: usize,
    pub mode: u32,
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq, Eq)]
pub struct PersistentInfo {
    pub path: PathBuf,
    pub mkdir: bool,
    pub mode: u32,
    pub user: u32,
    pub group: u32,
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq, Eq)]
pub struct StatedirInfo {
    pub path: PathBuf,
    pub mode: u32,
    pub user: u32,
    pub group: u32,
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq, Eq)]
pub enum Volume {
    Readonly(PathBuf),
    Persistent(PersistentInfo),
    Tmpfs(TmpfsInfo),
    Statedir(StatedirInfo),
}

#[derive(RustcDecodable, RustcEncodable, Serialize, Debug, PartialEq, Eq)]
#[derive(Clone, Copy)]
pub enum ContainerKind {
    Daemon,
    Command,
}

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct ResolvConf {
    pub copy_from_host: bool,
}

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct HostsFile {
    pub copy_from_host: bool,
    pub localhost: Option<bool>,
    pub public_hostname: Option<bool>,
}

#[derive(Clone, Debug)]
pub struct Host(pub IpAddr);

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct TcpPort {
    pub host: Host,
    pub fd: RawFd,
    pub reuse_addr: bool,
    pub reuse_port: bool,
    pub listen_backlog: usize,
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq, Eq)]
pub enum Variable {
    TcpPort,
    Choice(Vec<String>),
}

#[derive(RustcDecodable)]
pub struct ContainerConfig {
    pub kind: ContainerKind,
    pub variables: BTreeMap<String, Variable>,
    pub volumes: BTreeMap<String, Volume>,
    pub user_id: u32,
    pub group_id: u32,
    pub restart_timeout: f32,
    pub kill_timeout: f32,
    pub memory_limit: u64,
    pub fileno_limit: u64,
    pub cpu_shares: usize,
    pub executable: String,
    pub arguments: Vec<String>,
    pub environ: BTreeMap<String, String>,
    pub workdir: PathBuf,
    pub resolv_conf: ResolvConf,
    pub hosts_file: HostsFile,
    pub uid_map: Vec<IdMap>,
    pub gid_map: Vec<IdMap>,
    pub stdout_stderr_file: Option<PathBuf>,
    pub interactive: bool,
    pub restart_process_only: bool,
    pub tcp_ports: HashMap<String, TcpPort>,
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct InstantiatedConfig {
    pub kind: ContainerKind,
    pub volumes: BTreeMap<String, Volume>,
    pub user_id: u32,
    pub group_id: u32,
    pub restart_timeout: f32,
    pub kill_timeout: f32,
    pub memory_limit: u64,
    pub fileno_limit: u64,
    pub cpu_shares: usize,
    pub executable: String,
    pub arguments: Vec<String>,
    pub environ: BTreeMap<String, String>,
    pub workdir: PathBuf,
    pub resolv_conf: ResolvConf,
    pub hosts_file: HostsFile,
    pub uid_map: Vec<IdMap>,
    pub gid_map: Vec<IdMap>,
    pub stdout_stderr_file: Option<PathBuf>,
    pub interactive: bool,
    pub restart_process_only: bool,
    pub tcp_ports: HashMap<u16, TcpPort>,
}

pub struct Variables<'a> {
    pub user_vars: &'a HashMap<String, String>,
    pub lithos_name: &'a str,
    pub lithos_config_filename: &'a str,
}

impl InstantiatedConfig {
    pub fn map_uid(&self, internal_uid: u32) -> Option<u32> {
        self.uid_map.map_id(internal_uid)
    }
    pub fn map_gid(&self, internal_gid: u32) -> Option<u32> {
        self.gid_map.map_id(internal_gid)
    }
}

impl ContainerConfig {
    pub fn validator<'x>() -> Structure<'x> {
        Structure::new()
        .member("kind", Scalar::new().default("Daemon"))
        .member("variables", Mapping::new(
            Scalar::new(),
            Enum::new()
                .option("TcpPort", Nothing)
        ))
        .member("metadata", Anything)
        .member("volumes", Mapping::new(
                Scalar::new(),
                volume_validator()))
        .member("user_id", Numeric::new())
        .member("group_id", Numeric::new().default(0))
        .member("memory_limit", Numeric::new().default(0x7fffffffffffffffi64))
        .member("fileno_limit", Numeric::new().default(1024))
        .member("cpu_shares", Numeric::new().default(1024))
        .member("restart_timeout", Numeric::new().min(0).max(86400).default(1))
        .member("kill_timeout",
            Numeric::new().min(0).max(86400)
                .default(DEFAULT_KILL_TIMEOUT as i64))
        .member("executable", Scalar::new())
        .member("arguments", Sequence::new(Scalar::new()))
        .member("environ", Mapping::new(
                Scalar::new(),
                Scalar::new()))
        .member("workdir", Scalar::new().default("/"))
        .member("resolv_conf", Structure::new()
            .member("copy_from_host", Scalar::new().default(true)))
        .member("hosts_file", Structure::new()
            .member("copy_from_host", Scalar::new().default(false))
            .member("localhost", Scalar::new().optional())
            .member("public_hostname", Scalar::new().optional()))
        .member("uid_map", mapping_validator())
        .member("gid_map", mapping_validator())
        .member("stdout_stderr_file", Scalar::new().optional())
        .member("interactive", Scalar::new().default(false))
        .member("restart_process_only", Scalar::new().default(false))
        .member("tcp_ports", Mapping::new(
            Scalar::new(),
            Structure::new()
                .member("host", Scalar::new().default("0.0.0.0"))
                .member("fd", Numeric::new().min(0).optional())
                .member("reuse_addr", Scalar::new().default(true))
                .member("reuse_port", Scalar::new().default(false))
                .member("listen_backlog", Scalar::new().default(128))
            ))
    }
    pub fn instantiate(&self, variables: &Variables)
        -> Result<InstantiatedConfig, Vec<String>>
    {
        let mut errors1 = HashSet::new();
        let mut errors2 = HashSet::new();
        let result = {
            let mut replacer = |capt: &Captures| {
                let varname = capt.get(1).unwrap().as_str();
                let val = variables.user_vars.get(varname).map(|x| x.clone())
                    .or_else(|| match varname {
                        "lithos:name"
                        => Some(variables.lithos_name.to_string()),
                        "lithos:config_filename"
                        => Some(variables.lithos_config_filename.to_string()),
                        _ => None,
                    });
                match val {
                    Some(x) => x,
                    None => {
                        errors1.insert(format!("unknown variable {:?}", varname));
                        return format!("<<no var {:?}>>", varname);
                    }
                }
            };
            InstantiatedConfig {
                kind: self.kind.clone(),
                volumes: self.volumes.clone(),
                user_id: self.user_id.clone(),
                group_id: self.group_id.clone(),
                restart_timeout: self.restart_timeout.clone(),
                kill_timeout: self.kill_timeout.clone(),
                memory_limit: self.memory_limit.clone(),
                fileno_limit: self.fileno_limit.clone(),
                cpu_shares: self.cpu_shares.clone(),
                executable: self.executable.clone(),
                arguments: self.arguments.iter()
                    .map(|x| VARIABLE_REGEX.replace(&x, &mut replacer).into())
                    .collect(),
                environ: self.environ.iter()
                    .map(|(key, val)| {
                        (key.clone(),
                         VARIABLE_REGEX.replace(&val, &mut replacer).into())
                    })
                    .collect(),
                workdir: self.workdir.clone(),
                resolv_conf: self.resolv_conf.clone(),
                hosts_file: self.hosts_file.clone(),
                uid_map: self.uid_map.clone(),
                gid_map: self.gid_map.clone(),
                stdout_stderr_file: self.stdout_stderr_file.clone(),
                interactive: self.interactive.clone(),
                restart_process_only: self.restart_process_only.clone(),
                tcp_ports: self.tcp_ports.iter()
                    .map(|(key, val)| {
                        let s = VARIABLE_REGEX.replace(&key, &mut replacer);
                        let port = match s.parse::<u16>() {
                            Ok(x) => x,
                            Err(e) => {
                                errors2.insert(format!("Bad port {:?}: {}",
                                    key, e));
                                return (0, val.clone());
                            }
                        };
                        (port, val.clone())
                    })
                    .collect(),
            }
        };
        if errors1.len() > 0 || errors2.len() > 0 {
            return Err(errors1.into_iter().chain(errors2.into_iter())
                       .collect());
        } else {
            return Ok(result);
        }
    }
}

pub fn volume_validator<'x>() -> Enum<'x> {
    Enum::new()
    .option("Persistent",  Structure::new()
        .member("path",  Scalar::new().default("/"))
        .member("mkdir",  Scalar::new().default(false))
        .member("mode",  Numeric::new().min(0).max(0o1777).default(0o777))
        .member("user",  Numeric::new().default(0))
        .member("group",  Numeric::new().default(0)))
    .option("Readonly", Scalar::new())
    .option("Tmpfs", Structure::new()
        .member("size", Numeric::new().min(0).default(100*1024*1024))
        .member("mode", Numeric::new().min(0).max(0o1777).default(0o777)))
    .option("Statedir", Structure::new()
        .member("path", Scalar::new().default("/"))
        .member("mode", Numeric::new().min(0).max(0o1777).default(0o777))
        .member("user", Numeric::new().default(0))
        .member("group", Numeric::new().default(0)))
}

impl Decodable for Host {
    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
        try!(d.read_str()).parse().map(Host)
            .map_err(|x| d.error(&format!("{}", x)))
    }
}

impl Encodable for Host {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        format!("{}", self.0).encode(s)
    }
}

impl Variable {
    pub fn validate(&self, value: &str, sandbox: &SandboxConfig)
        -> Result<(), String>
    {
        match *self {
            Variable::TcpPort => {
                let port = value.parse::<u16>()
                    .map_err(|e| format!(
                        "invalid TcpPort {:?}: {}", value, e))?;
                if !in_range(&sandbox.allow_tcp_ports, port as u32) {
                    return Err(format!(
                        "TcpPort {:?} is not in allowed range", port));
                }
            }
            Variable::Choice(ref choices) => {
                if !choices.iter().any(|x| x == value) {
                    return Err(format!("variable value {:?} \
                        is not one of {:?}", value, choices));
                }
            }
        }
        Ok(())
    }
}
<commit_msg>Fixes validator for `Choice`<commit_after>use std::net::IpAddr;
use std::path::PathBuf;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::os::unix::io::RawFd;

use regex::{Regex, Captures};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use quire::validate::{Structure, Sequence, Scalar, Numeric, Enum};
use quire::validate::{Mapping, Nothing, Anything};
use id_map::{IdMap, IdMapExt, mapping_validator};

use sandbox_config::SandboxConfig;
use utils::{in_range};

pub const DEFAULT_KILL_TIMEOUT: f32 = 5.;

lazy_static! {
    static ref VARIABLE_REGEX: Regex = Regex::new(r#"@\{([^}]*)\}"#).unwrap();
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq, Eq)]
pub struct TmpfsInfo {
    pub size: usize,
    pub mode: u32,
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq, Eq)]
pub struct PersistentInfo {
    pub path: PathBuf,
    pub mkdir: bool,
    pub mode: u32,
    pub user: u32,
    pub group: u32,
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq, Eq)]
pub struct StatedirInfo {
    pub path: PathBuf,
    pub mode: u32,
    pub user: u32,
    pub group: u32,
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq, Eq)]
pub enum Volume {
    Readonly(PathBuf),
    Persistent(PersistentInfo),
    Tmpfs(TmpfsInfo),
    Statedir(StatedirInfo),
}

#[derive(RustcDecodable, RustcEncodable, Serialize, Debug, PartialEq, Eq)]
#[derive(Clone, Copy)]
pub enum ContainerKind {
    Daemon,
    Command,
}

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct ResolvConf {
    pub copy_from_host: bool,
}

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct HostsFile {
    pub copy_from_host: bool,
    pub localhost: Option<bool>,
    pub public_hostname: Option<bool>,
}

#[derive(Clone, Debug)]
pub struct Host(pub IpAddr);

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct TcpPort {
    pub host: Host,
    pub fd: RawFd,
    pub reuse_addr: bool,
    pub reuse_port: bool,
    pub listen_backlog: usize,
}

#[derive(RustcDecodable, RustcEncodable, Clone, PartialEq, Eq)]
pub enum Variable {
    TcpPort,
    Choice(Vec<String>),
}

#[derive(RustcDecodable)]
pub struct ContainerConfig {
    pub kind: ContainerKind,
    pub variables: BTreeMap<String, Variable>,
    pub volumes: BTreeMap<String, Volume>,
    pub user_id: u32,
    pub group_id: u32,
    pub restart_timeout: f32,
    pub kill_timeout: f32,
    pub memory_limit: u64,
    pub fileno_limit: u64,
    pub cpu_shares: usize,
    pub executable: String,
    pub arguments: Vec<String>,
    pub environ: BTreeMap<String, String>,
    pub workdir: PathBuf,
    pub resolv_conf: ResolvConf,
    pub hosts_file: HostsFile,
    pub uid_map: Vec<IdMap>,
    pub gid_map: Vec<IdMap>,
    pub stdout_stderr_file: Option<PathBuf>,
    pub interactive: bool,
    pub restart_process_only: bool,
    pub tcp_ports: HashMap<String, TcpPort>,
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct InstantiatedConfig {
    pub kind: ContainerKind,
    pub volumes: BTreeMap<String, Volume>,
    pub user_id: u32,
    pub group_id: u32,
    pub restart_timeout: f32,
    pub kill_timeout: f32,
    pub memory_limit: u64,
    pub fileno_limit: u64,
    pub cpu_shares: usize,
    pub executable: String,
    pub arguments: Vec<String>,
    pub environ: BTreeMap<String, String>,
    pub workdir: PathBuf,
    pub resolv_conf: ResolvConf,
    pub hosts_file: HostsFile,
    pub uid_map: Vec<IdMap>,
    pub gid_map: Vec<IdMap>,
    pub stdout_stderr_file: Option<PathBuf>,
    pub interactive: bool,
    pub restart_process_only: bool,
    pub tcp_ports: HashMap<u16, TcpPort>,
}

pub struct Variables<'a> {
    pub user_vars: &'a HashMap<String, String>,
    pub lithos_name: &'a str,
    pub lithos_config_filename: &'a str,
}

impl InstantiatedConfig {
    pub fn map_uid(&self, internal_uid: u32) -> Option<u32> {
        self.uid_map.map_id(internal_uid)
    }
    pub fn map_gid(&self, internal_gid: u32) -> Option<u32> {
        self.gid_map.map_id(internal_gid)
    }
}

impl ContainerConfig {
    pub fn validator<'x>() -> Structure<'x> {
        Structure::new()
        .member("kind", Scalar::new().default("Daemon"))
        .member("variables", Mapping::new(
            Scalar::new(),
            Enum::new()
                .option("TcpPort", Nothing)
                .option("Choice", Sequence::new(Scalar::new()))
        ))
        .member("metadata", Anything)
        .member("volumes", Mapping::new(
                Scalar::new(),
                volume_validator()))
        .member("user_id", Numeric::new())
        .member("group_id", Numeric::new().default(0))
        .member("memory_limit", Numeric::new().default(0x7fffffffffffffffi64))
        .member("fileno_limit", Numeric::new().default(1024))
        .member("cpu_shares", Numeric::new().default(1024))
        .member("restart_timeout", Numeric::new().min(0).max(86400).default(1))
        .member("kill_timeout",
            Numeric::new().min(0).max(86400)
                .default(DEFAULT_KILL_TIMEOUT as i64))
        .member("executable", Scalar::new())
        .member("arguments", Sequence::new(Scalar::new()))
        .member("environ", Mapping::new(
                Scalar::new(),
                Scalar::new()))
        .member("workdir", Scalar::new().default("/"))
        .member("resolv_conf", Structure::new()
            .member("copy_from_host", Scalar::new().default(true)))
        .member("hosts_file", Structure::new()
            .member("copy_from_host", Scalar::new().default(false))
            .member("localhost", Scalar::new().optional())
            .member("public_hostname", Scalar::new().optional()))
        .member("uid_map", mapping_validator())
        .member("gid_map", mapping_validator())
        .member("stdout_stderr_file", Scalar::new().optional())
        .member("interactive", Scalar::new().default(false))
        .member("restart_process_only", Scalar::new().default(false))
        .member("tcp_ports", Mapping::new(
            Scalar::new(),
            Structure::new()
                .member("host", Scalar::new().default("0.0.0.0"))
                .member("fd", Numeric::new().min(0).optional())
                .member("reuse_addr", Scalar::new().default(true))
                .member("reuse_port", Scalar::new().default(false))
                .member("listen_backlog", Scalar::new().default(128))
            ))
    }
    pub fn instantiate(&self, variables: &Variables)
        -> Result<InstantiatedConfig, Vec<String>>
    {
        let mut errors1 = HashSet::new();
        let mut errors2 = HashSet::new();
        let result = {
            let mut replacer = |capt: &Captures| {
                let varname = capt.get(1).unwrap().as_str();
                let val = variables.user_vars.get(varname).map(|x| x.clone())
                    .or_else(|| match varname {
                        "lithos:name"
                        => Some(variables.lithos_name.to_string()),
                        "lithos:config_filename"
                        => Some(variables.lithos_config_filename.to_string()),
                        _ => None,
                    });
                match val {
                    Some(x) => x,
                    None => {
                        errors1.insert(format!("unknown variable {:?}", varname));
                        return format!("<<no var {:?}>>", varname);
                    }
                }
            };
            InstantiatedConfig {
                kind: self.kind.clone(),
                volumes: self.volumes.clone(),
                user_id: self.user_id.clone(),
                group_id: self.group_id.clone(),
                restart_timeout: self.restart_timeout.clone(),
                kill_timeout: self.kill_timeout.clone(),
                memory_limit: self.memory_limit.clone(),
                fileno_limit: self.fileno_limit.clone(),
                cpu_shares: self.cpu_shares.clone(),
                executable: self.executable.clone(),
                arguments: self.arguments.iter()
                    .map(|x| VARIABLE_REGEX.replace(&x, &mut replacer).into())
                    .collect(),
                environ: self.environ.iter()
                    .map(|(key, val)| {
                        (key.clone(),
                         VARIABLE_REGEX.replace(&val, &mut replacer).into())
                    })
                    .collect(),
                workdir: self.workdir.clone(),
                resolv_conf: self.resolv_conf.clone(),
                hosts_file: self.hosts_file.clone(),
                uid_map: self.uid_map.clone(),
                gid_map: self.gid_map.clone(),
                stdout_stderr_file: self.stdout_stderr_file.clone(),
                interactive: self.interactive.clone(),
                restart_process_only: self.restart_process_only.clone(),
                tcp_ports: self.tcp_ports.iter()
                    .map(|(key, val)| {
                        let s = VARIABLE_REGEX.replace(&key, &mut replacer);
                        let port = match s.parse::<u16>() {
                            Ok(x) => x,
                            Err(e) => {
                                errors2.insert(format!("Bad port {:?}: {}",
                                    key, e));
                                return (0, val.clone());
                            }
                        };
                        (port, val.clone())
                    })
                    .collect(),
            }
        };
        if errors1.len() > 0 || errors2.len() > 0 {
            return Err(errors1.into_iter().chain(errors2.into_iter())
                       .collect());
        } else {
            return Ok(result);
        }
    }
}

pub fn volume_validator<'x>() -> Enum<'x> {
    Enum::new()
    .option("Persistent",  Structure::new()
        .member("path",  Scalar::new().default("/"))
        .member("mkdir",  Scalar::new().default(false))
        .member("mode",  Numeric::new().min(0).max(0o1777).default(0o777))
        .member("user",  Numeric::new().default(0))
        .member("group",  Numeric::new().default(0)))
    .option("Readonly", Scalar::new())
    .option("Tmpfs", Structure::new()
        .member("size", Numeric::new().min(0).default(100*1024*1024))
        .member("mode", Numeric::new().min(0).max(0o1777).default(0o777)))
    .option("Statedir", Structure::new()
        .member("path", Scalar::new().default("/"))
        .member("mode", Numeric::new().min(0).max(0o1777).default(0o777))
        .member("user", Numeric::new().default(0))
        .member("group", Numeric::new().default(0)))
}

impl Decodable for Host {
    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
        try!(d.read_str()).parse().map(Host)
            .map_err(|x| d.error(&format!("{}", x)))
    }
}

impl Encodable for Host {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        format!("{}", self.0).encode(s)
    }
}

impl Variable {
    pub fn validate(&self, value: &str, sandbox: &SandboxConfig)
        -> Result<(), String>
    {
        match *self {
            Variable::TcpPort => {
                let port = value.parse::<u16>()
                    .map_err(|e| format!(
                        "invalid TcpPort {:?}: {}", value, e))?;
                if !in_range(&sandbox.allow_tcp_ports, port as u32) {
                    return Err(format!(
                        "TcpPort {:?} is not in allowed range", port));
                }
            }
            Variable::Choice(ref choices) => {
                if !choices.iter().any(|x| x == value) {
                    return Err(format!("variable value {:?} \
                        is not one of {:?}", value, choices));
                }
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags: --test

//! Test that makes sure wrongly-typed bench functions are rejected

#[bench]
fn bar(x: isize) { }
//~^ ERROR mismatched types
//~| expected type `for<'r> fn(&'r mut __test::test::Bencher)`
//~| found type `fn(isize) {bar}`
//~| expected mutable reference, found isize
<commit_msg>update test -- we now give a slightly different error<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags: --test

//! Test that makes sure wrongly-typed bench functions are rejected

#[bench]
fn bar(x: isize) { }
//~^ ERROR mismatched types
<|endoftext|>


<commit_before>use core::codepointinfo::CodepointInfo;

// a line is composed of codepoints
#[derive(Debug, Clone)]
pub struct Line {
    pub chars: Vec<CodepointInfo>,
    pub nb_chars: usize,
    pub width: usize,
    pub read_only: bool,
}

impl Line {
    pub fn new(width: usize) -> Line {

        assert_eq!(width > 0, true);

        let mut chars = Vec::with_capacity(width);
        for _ in 0..width {
            chars.push(CodepointInfo::new());
        }

        Line {
            chars,
            nb_chars: 0,
            width,
            read_only: false,
        }
    }

    pub fn resize(&mut self, width: usize) {
        self.chars.resize(width, CodepointInfo::new());
        self.nb_chars = 0;
        self.width = width;
        self.read_only = false;
    }

    pub fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {

        if self.nb_chars < self.width && self.read_only == false {
            self.chars[self.nb_chars] = cpi;
            self.nb_chars += 1;
            (true, self.nb_chars)
        } else {
            self.read_only = true;
            (false, self.nb_chars)
        }
    }

    pub fn clear(&mut self) {
        for w in 0..self.width {
            self.chars[w] = CodepointInfo::new();
        }
        self.nb_chars = 0;
        self.read_only = false;
    }

    pub fn get_cpi(&self, index: usize) -> Option<&CodepointInfo> {
        if index < self.width {
            Some(&self.chars[index])
        } else {
            None
        }
    }

    pub fn get_first_cpi(&self) -> Option<&CodepointInfo> {
        if 0 < self.nb_chars {
            Some(&self.chars[0])
        } else {
            None
        }
    }

    pub fn get_mut_cpi(&mut self, index: usize) -> Option<&mut CodepointInfo> {
        if index < self.width {
            Some(&mut self.chars[index])
        } else {
            None
        }
    }

    pub fn get_used_cpi(&self, index: usize) -> Option<&CodepointInfo> {
        if index < self.nb_chars {
            Some(&self.chars[index])
        } else {
            None
        }
    }

    pub fn get_mut_used_cpi(&mut self, index: usize) -> Option<&mut CodepointInfo> {
        if index < self.nb_chars {
            Some(&mut self.chars[index])
        } else {
            None
        }
    }
}
<commit_msg>Line: add fn get_last_cpi<commit_after>use core::codepointinfo::CodepointInfo;

// a line is composed of codepoints
#[derive(Debug, Clone)]
pub struct Line {
    pub chars: Vec<CodepointInfo>,
    pub nb_chars: usize,
    pub width: usize,
    pub read_only: bool,
}

impl Line {
    pub fn new(width: usize) -> Line {

        assert_eq!(width > 0, true);

        let mut chars = Vec::with_capacity(width);
        for _ in 0..width {
            chars.push(CodepointInfo::new());
        }

        Line {
            chars,
            nb_chars: 0,
            width,
            read_only: false,
        }
    }

    pub fn resize(&mut self, width: usize) {
        self.chars.resize(width, CodepointInfo::new());
        self.nb_chars = 0;
        self.width = width;
        self.read_only = false;
    }

    pub fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {

        if self.nb_chars < self.width && self.read_only == false {
            self.chars[self.nb_chars] = cpi;
            self.nb_chars += 1;
            (true, self.nb_chars)
        } else {
            self.read_only = true;
            (false, self.nb_chars)
        }
    }

    pub fn clear(&mut self) {
        for w in 0..self.width {
            self.chars[w] = CodepointInfo::new();
        }
        self.nb_chars = 0;
        self.read_only = false;
    }

    pub fn get_cpi(&self, index: usize) -> Option<&CodepointInfo> {
        if index < self.width {
            Some(&self.chars[index])
        } else {
            None
        }
    }

    pub fn get_first_cpi(&self) -> Option<&CodepointInfo> {
        if 0 < self.nb_chars {
            Some(&self.chars[0])
        } else {
            None
        }
    }

    pub fn get_last_cpi(&self) -> Option<&CodepointInfo> {
        if self.nb_chars > 0 {
            Some(&self.chars[self.nb_chars - 1])
        } else {
            None
        }
    }

    pub fn get_mut_cpi(&mut self, index: usize) -> Option<&mut CodepointInfo> {
        if index < self.width {
            Some(&mut self.chars[index])
        } else {
            None
        }
    }

    pub fn get_used_cpi(&self, index: usize) -> Option<&CodepointInfo> {
        if index < self.nb_chars {
            Some(&self.chars[index])
        } else {
            None
        }
    }

    pub fn get_mut_used_cpi(&mut self, index: usize) -> Option<&mut CodepointInfo> {
        if index < self.nb_chars {
            Some(&mut self.chars[index])
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use super::{layout, callbacks, types, ids, development};

pub trait UiApplication {
    fn new_window(&mut self, title: &str, size: types::WindowStartSize, has_menu: bool) -> Box<UiWindow>;
    fn name(&self) -> &str;
    fn start(&mut self);
    fn find_member_by_id_mut(&mut self, id: ids::Id) -> Option<&mut UiMember>;
    fn find_member_by_id(&self, id: ids::Id) -> Option<&UiMember>;
}

pub trait UiMember {
    fn size(&self) -> (u16, u16);
    fn on_resize(&mut self, Option<callbacks::Resize>);

    fn set_visibility(&mut self, visibility: types::Visibility);
    fn visibility(&self) -> types::Visibility;

    fn as_base(&self) -> &types::UiMemberBase;
    fn as_base_mut(&mut self) -> &mut types::UiMemberBase;

	fn is_control(&self) -> Option<&UiControl>;
    fn is_control_mut(&mut self) -> Option<&mut UiControl>;

    unsafe fn native_id(&self) -> usize;
}

pub trait UiLayable: UiMember {
	fn layout_width(&self) -> layout::Size;
	fn layout_height(&self) -> layout::Size;
	fn layout_gravity(&self) -> layout::Gravity;
	fn layout_orientation(&self) -> layout::Orientation;
	fn layout_alignment(&self) -> layout::Alignment;

	fn set_layout_width(&mut self, layout::Size);
	fn set_layout_height(&mut self, layout::Size);
	fn set_layout_gravity(&mut self, layout::Gravity);
	fn set_layout_orientation(&mut self, layout::Orientation);
	fn set_layout_alignment(&mut self, layout::Alignment);

	fn as_member(&self) -> &UiMember;
	fn as_member_mut(&mut self) -> &mut UiMember;
}

pub trait UiControl: UiLayable + development::UiDrawable {
    fn is_container_mut(&mut self) -> Option<&mut UiContainer>;
    fn is_container(&self) -> Option<&UiContainer>;

	fn on_added_to_container(&mut self, &UiContainer, x: u16, y: u16);
    fn on_removed_from_container(&mut self, &UiContainer);

    fn parent(&self) -> Option<&types::UiMemberBase>;
    fn parent_mut(&mut self) -> Option<&mut types::UiMemberBase>;
    fn root(&self) -> Option<&types::UiMemberBase>;
    fn root_mut(&mut self) -> Option<&mut types::UiMemberBase>;

	fn as_layable(&self) -> &UiLayable;
	fn as_layable_mut(&mut self) -> &mut UiLayable;

    #[cfg(feature = "markup")]
    fn fill_from_markup(&mut self, &super::markup::Markup, &mut super::markup::MarkupRegistry);
}

pub trait UiContainer: UiMember {
    fn find_control_by_id_mut(&mut self, id: ids::Id) -> Option<&mut UiControl>;
    fn find_control_by_id(&self, id: ids::Id) -> Option<&UiControl>;

    fn is_multi_mut(&mut self) -> Option<&mut UiMultiContainer> { None }
    fn is_multi(&self) -> Option<&UiMultiContainer> { None }
    fn is_single_mut(&mut self) -> Option<&mut UiSingleContainer> { None }
    fn is_single(&self) -> Option<&UiSingleContainer> { None }

	fn as_member(&self) -> &UiMember;
	fn as_member_mut(&mut self) -> &mut UiMember;
}

pub trait UiSingleContainer: UiContainer {
	fn set_child(&mut self, Option<Box<UiControl>>) -> Option<Box<UiControl>>;
    fn child(&self) -> Option<&UiControl>;
    fn child_mut(&mut self) -> Option<&mut UiControl>;

	fn as_container(&self) -> &UiContainer;
	fn as_container_mut(&mut self) -> &mut UiContainer;
}

pub trait UiMultiContainer: UiContainer {
    fn len(&self) -> usize;
    fn set_child_to(&mut self, index: usize, Box<UiControl>) -> Option<Box<UiControl>>;
    fn remove_child_from(&mut self, index: usize) -> Option<Box<UiControl>>;
    fn child_at(&self, index: usize) -> Option<&Box<UiControl>>;
    fn child_at_mut(&mut self, index: usize) -> Option<&mut Box<UiControl>>;

	fn as_container(&self) -> &UiContainer;
	fn as_container_mut(&mut self) -> &mut UiContainer;

    fn clear(&mut self) {
        let len = self.len();
        for index in (0..len).rev() {
            self.remove_child_from(index);
        }
    }
    fn push_child(&mut self, child: Box<UiControl>) {
        let len = self.len();
        self.set_child_to(len, child);
    }
    fn pop_child(&mut self) -> Option<Box<UiControl>> {
        let len = self.len();
        if len > 0 {
        	self.remove_child_from(len - 1)
        } else {
        	None
        }
    }
}

pub trait UiWindow: UiSingleContainer {
	fn as_single_container(&self) -> &UiSingleContainer;
	fn as_single_container_mut(&mut self) -> &mut UiSingleContainer;
}

pub trait UiButton: UiControl {
    //fn new(label: &str) -> Box<Self>;
    fn label(&self) -> &str;
    fn set_label(&mut self, &str);
    fn on_left_click(&mut self, Option<callbacks::Click>);

	fn as_control(&self) -> &UiControl;
	fn as_control_mut(&mut self) -> &mut UiControl;
}

pub trait UiLinearLayout: UiMultiContainer + UiControl {
    fn orientation(&self) -> layout::Orientation;
    fn set_orientation(&mut self, layout::Orientation);

	fn as_control(&self) -> &UiControl;
	fn as_control_mut(&mut self) -> &mut UiControl;
	fn as_multi_container(&self) -> &UiMultiContainer;
	fn as_multi_container_mut(&mut self) -> &mut UiMultiContainer;
}

pub trait UiRelativeLayout: UiMultiContainer + UiControl {}<commit_msg>Cow<str> application name<commit_after>use super::{layout, callbacks, types, ids, development};

pub trait UiApplication {
    fn new_window(&mut self, title: &str, size: types::WindowStartSize, has_menu: bool) -> Box<UiWindow>;
    fn name<'a>(&'a self) -> ::std::borrow::Cow<'a, str>;
    fn start(&mut self);
    fn find_member_by_id_mut(&mut self, id: ids::Id) -> Option<&mut UiMember>;
    fn find_member_by_id(&self, id: ids::Id) -> Option<&UiMember>;
}

pub trait UiMember {
    fn size(&self) -> (u16, u16);
    fn on_resize(&mut self, Option<callbacks::Resize>);

    fn set_visibility(&mut self, visibility: types::Visibility);
    fn visibility(&self) -> types::Visibility;

    fn as_base(&self) -> &types::UiMemberBase;
    fn as_base_mut(&mut self) -> &mut types::UiMemberBase;

	fn is_control(&self) -> Option<&UiControl>;
    fn is_control_mut(&mut self) -> Option<&mut UiControl>;

    unsafe fn native_id(&self) -> usize;
}

pub trait UiLayable: UiMember {
	fn layout_width(&self) -> layout::Size;
	fn layout_height(&self) -> layout::Size;
	fn layout_gravity(&self) -> layout::Gravity;
	fn layout_orientation(&self) -> layout::Orientation;
	fn layout_alignment(&self) -> layout::Alignment;

	fn set_layout_width(&mut self, layout::Size);
	fn set_layout_height(&mut self, layout::Size);
	fn set_layout_gravity(&mut self, layout::Gravity);
	fn set_layout_orientation(&mut self, layout::Orientation);
	fn set_layout_alignment(&mut self, layout::Alignment);

	fn as_member(&self) -> &UiMember;
	fn as_member_mut(&mut self) -> &mut UiMember;
}

pub trait UiControl: UiLayable + development::UiDrawable {
    fn is_container_mut(&mut self) -> Option<&mut UiContainer>;
    fn is_container(&self) -> Option<&UiContainer>;

	fn on_added_to_container(&mut self, &UiContainer, x: u16, y: u16);
    fn on_removed_from_container(&mut self, &UiContainer);

    fn parent(&self) -> Option<&types::UiMemberBase>;
    fn parent_mut(&mut self) -> Option<&mut types::UiMemberBase>;
    fn root(&self) -> Option<&types::UiMemberBase>;
    fn root_mut(&mut self) -> Option<&mut types::UiMemberBase>;

	fn as_layable(&self) -> &UiLayable;
	fn as_layable_mut(&mut self) -> &mut UiLayable;

    #[cfg(feature = "markup")]
    fn fill_from_markup(&mut self, &super::markup::Markup, &mut super::markup::MarkupRegistry);
}

pub trait UiContainer: UiMember {
    fn find_control_by_id_mut(&mut self, id: ids::Id) -> Option<&mut UiControl>;
    fn find_control_by_id(&self, id: ids::Id) -> Option<&UiControl>;

    fn is_multi_mut(&mut self) -> Option<&mut UiMultiContainer> { None }
    fn is_multi(&self) -> Option<&UiMultiContainer> { None }
    fn is_single_mut(&mut self) -> Option<&mut UiSingleContainer> { None }
    fn is_single(&self) -> Option<&UiSingleContainer> { None }

	fn as_member(&self) -> &UiMember;
	fn as_member_mut(&mut self) -> &mut UiMember;
}

pub trait UiSingleContainer: UiContainer {
	fn set_child(&mut self, Option<Box<UiControl>>) -> Option<Box<UiControl>>;
    fn child(&self) -> Option<&UiControl>;
    fn child_mut(&mut self) -> Option<&mut UiControl>;

	fn as_container(&self) -> &UiContainer;
	fn as_container_mut(&mut self) -> &mut UiContainer;
}

pub trait UiMultiContainer: UiContainer {
    fn len(&self) -> usize;
    fn set_child_to(&mut self, index: usize, Box<UiControl>) -> Option<Box<UiControl>>;
    fn remove_child_from(&mut self, index: usize) -> Option<Box<UiControl>>;
    fn child_at(&self, index: usize) -> Option<&Box<UiControl>>;
    fn child_at_mut(&mut self, index: usize) -> Option<&mut Box<UiControl>>;

	fn as_container(&self) -> &UiContainer;
	fn as_container_mut(&mut self) -> &mut UiContainer;

    fn clear(&mut self) {
        let len = self.len();
        for index in (0..len).rev() {
            self.remove_child_from(index);
        }
    }
    fn push_child(&mut self, child: Box<UiControl>) {
        let len = self.len();
        self.set_child_to(len, child);
    }
    fn pop_child(&mut self) -> Option<Box<UiControl>> {
        let len = self.len();
        if len > 0 {
        	self.remove_child_from(len - 1)
        } else {
        	None
        }
    }
}

pub trait UiWindow: UiSingleContainer {
	fn as_single_container(&self) -> &UiSingleContainer;
	fn as_single_container_mut(&mut self) -> &mut UiSingleContainer;
}

pub trait UiButton: UiControl {
    //fn new(label: &str) -> Box<Self>;
    fn label(&self) -> &str;
    fn set_label(&mut self, &str);
    fn on_left_click(&mut self, Option<callbacks::Click>);

	fn as_control(&self) -> &UiControl;
	fn as_control_mut(&mut self) -> &mut UiControl;
}

pub trait UiLinearLayout: UiMultiContainer + UiControl {
    fn orientation(&self) -> layout::Orientation;
    fn set_orientation(&mut self, layout::Orientation);

	fn as_control(&self) -> &UiControl;
	fn as_control_mut(&mut self) -> &mut UiControl;
	fn as_multi_container(&self) -> &UiMultiContainer;
	fn as_multi_container_mut(&mut self) -> &mut UiMultiContainer;
}

pub trait UiRelativeLayout: UiMultiContainer + UiControl {}<|endoftext|>


<commit_before>//! Defines common interfaces for interacting with statistical distributions and provides
//! concrete implementations for a variety of distributions.

use rand::Rng;
use super::result::Result;

pub use self::bernoulli::Bernoulli;
pub use self::binomial::Binomial;
pub use self::chi::Chi;
pub use self::chi_squared::ChiSquared;
pub use self::discrete_uniform::DiscreteUniform;
pub use self::exponential::Exponential;
pub use self::gamma::Gamma;
pub use self::log_normal::LogNormal;
pub use self::normal::Normal;
pub use self::poisson::Poisson;
pub use self::student_t::StudentT;
pub use self::triangular::Triangular;
pub use self::uniform::Uniform;
pub use self::weibull::Weibull;

mod bernoulli;
mod binomial;
mod chi;
mod chi_squared;
mod discrete_uniform;
mod exponential;
mod gamma;
mod log_normal;
mod normal;
mod poisson;
mod student_t;
mod triangular;
mod uniform;
mod weibull;

/// The `Distribution` trait is used to specify an interface
/// for sampling distributions
///
/// # Examples
///
/// A trivial implementation that just samples from the supplied
/// random number generator
///
/// ```
/// use rand::StdRng;
///
/// struct Foo;
///
/// impl Distribution for Foo {
///     fn sample<R: Rng>(&self, r: &mut R) -> f64 {
///         r.next_f64()
///     }
/// }
/// ```
pub trait Distribution {
    /// Draws a random sample using the supplied random number generator
    fn sample<R: Rng>(&self, r: &mut R) -> f64;
}

/// The `Univariate` trait extends the `Distribution`
/// trait provides an interface for interacting with
/// univariate statistical distributions.
///
/// # Remarks
///
/// All methods provided by the `Univariate` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution. The `CheckedUnivariate`
/// trait provides a panic-safe interface for univariate distributions
pub trait Univariate : Distribution {
    /// Returns the mean for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.5, n.mean());
    /// ```
    fn mean(&self) -> f64;

    /// Returns the variance for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(1.0 / 12.0, n.variance());
    /// ```
    fn variance(&self) -> f64;

    /// Returns the standard deviation for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!((1f64 / 12f64).sqrt(), n.std_dev());
    /// ```
    fn std_dev(&self) -> f64;

    /// Returns the entropy for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.0, n.entropy());
    /// ```
    fn entropy(&self) -> f64;

    /// Returns the skewness for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.0, n.skewness());
    /// ```
    fn skewness(&self) -> f64;

    /// Returns the median for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.5, n.median());
    /// ```
    fn median(&self) -> f64;

    /// Returns the cumulative distribution function calculated
    /// at `x` for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.5, n.cdf(0.5));
    /// ```
    fn cdf(&self, x: f64) -> f64;
}

/// The `CheckedUnivariate` trait extends the `Distribution` trait and
/// provides a checked interface for interacting with univariate statistical
/// distributions. This means implementors should return an `Err` instead of
/// panicking on an invalid state or input.
pub trait CheckedUnivariate : Distribution {
    fn mean(&self) -> Result<f64>;
    fn variance(&self) -> Result<f64>;
    fn std_dev(&self) -> Result<f64>;
    fn entropy(&self) -> Result<f64>;
    fn skewness(&self) -> Result<f64>;
    fn median(&self) -> Result<f64>;
    fn cdf(&self) -> Result<f64>;
}

/// The `Continuous` trait extends the `Univariate`
/// trait and provides an interface for interacting with continuous
/// univariate statistical distributions
///
/// # Remarks
///
/// All methods provided by the `Continuous` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution. The `CheckedContinuous`
/// trait provides a panic-safe interface for continuous distributions
pub trait Continuous : Univariate {
    fn mode(&self) -> f64;
    fn min(&self) -> f64;
    fn max(&self) -> f64;
    fn pdf(&self, x: f64) -> f64;
    fn ln_pdf(&self, x: f64) -> f64;
}

/// The `CheckedContinous` trait extends the `CheckedUnivariate`
/// trait and provides a checked interface for interacting with
/// continous univariate statistical distributions. This means
/// implementors should return an `Err` instead of panicking on
/// an invalid state or input.
pub trait CheckedContinuous : CheckedUnivariate {
    fn mode(&self) -> Result<f64>;
    fn min(&self) -> Result<f64>;
    fn max(&self) -> Result<f64>;
    fn pdf(&self, x: f64) -> Result<f64>;
    fn ln_pdf(&self, x: f64) -> Result<f64>;
}

/// The `Discrete` trait extends the `Univariate`
/// trait and provides an interface for interacting with discrete
/// univariate statistical distributions
///
/// # Remakrs
///
/// All methods provided by the `Discrete` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution. The `CheckedDiscrete` trait
/// provides a panic-safe interface for discrete distributions
pub trait Discrete : Univariate {
    fn mode(&self) -> i64;
    fn min(&self) -> i64;
    fn max(&self) -> i64;
    fn pmf(&self, x: i64) -> f64;
    fn ln_pmf(&self, x: i64) -> f64;
}

/// The `CheckedDiscrete` trait extends the `CheckedUnivariate` trait
/// and provides a checked interface for interacting with discrete
/// univariate statistical distributions. This means implementors
/// should return an `Err` instead of panicking on an invalid state
/// or input
pub trait CheckedDiscrete : CheckedUnivariate {
    fn mode(&self) -> Result<i64>;
    fn min(&self) -> Result<i64>;
    fn max(&self) -> Result<i64>;
    fn pmf(&self, x: i64) -> Result<f64>;
    fn ln_pmf(&self, x: i64) -> Result<f64>;
}<commit_msg>doc comments for checked univariate trait<commit_after>//! Defines common interfaces for interacting with statistical distributions and provides
//! concrete implementations for a variety of distributions.

use rand::Rng;
use super::result::Result;

pub use self::bernoulli::Bernoulli;
pub use self::binomial::Binomial;
pub use self::chi::Chi;
pub use self::chi_squared::ChiSquared;
pub use self::discrete_uniform::DiscreteUniform;
pub use self::exponential::Exponential;
pub use self::gamma::Gamma;
pub use self::log_normal::LogNormal;
pub use self::normal::Normal;
pub use self::poisson::Poisson;
pub use self::student_t::StudentT;
pub use self::triangular::Triangular;
pub use self::uniform::Uniform;
pub use self::weibull::Weibull;

mod bernoulli;
mod binomial;
mod chi;
mod chi_squared;
mod discrete_uniform;
mod exponential;
mod gamma;
mod log_normal;
mod normal;
mod poisson;
mod student_t;
mod triangular;
mod uniform;
mod weibull;

/// The `Distribution` trait is used to specify an interface
/// for sampling distributions
///
/// # Examples
///
/// A trivial implementation that just samples from the supplied
/// random number generator
///
/// ```
/// use rand::StdRng;
///
/// struct Foo;
///
/// impl Distribution for Foo {
///     fn sample<R: Rng>(&self, r: &mut R) -> f64 {
///         r.next_f64()
///     }
/// }
/// ```
pub trait Distribution {
    /// Draws a random sample using the supplied random number generator
    fn sample<R: Rng>(&self, r: &mut R) -> f64;
}

/// The `Univariate` trait extends the `Distribution`
/// trait provides an interface for interacting with
/// univariate statistical distributions.
///
/// # Remarks
///
/// All methods provided by the `Univariate` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution. The `CheckedUnivariate`
/// trait provides a panic-safe interface for univariate distributions
pub trait Univariate : Distribution {
    /// Returns the mean for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.5, n.mean());
    /// ```
    fn mean(&self) -> f64;

    /// Returns the variance for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(1.0 / 12.0, n.variance());
    /// ```
    fn variance(&self) -> f64;

    /// Returns the standard deviation for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!((1f64 / 12f64).sqrt(), n.std_dev());
    /// ```
    fn std_dev(&self) -> f64;

    /// Returns the entropy for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.0, n.entropy());
    /// ```
    fn entropy(&self) -> f64;

    /// Returns the skewness for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.0, n.skewness());
    /// ```
    fn skewness(&self) -> f64;

    /// Returns the median for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.5, n.median());
    /// ```
    fn median(&self) -> f64;

    /// Returns the cumulative distribution function calculated
    /// at `x` for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.5, n.cdf(0.5));
    /// ```
    fn cdf(&self, x: f64) -> f64;
}

/// The `CheckedUnivariate` trait extends the `Distribution` trait and
/// provides a checked interface for interacting with univariate statistical
/// distributions. This means implementors should return an `Err` instead of
/// panicking on an invalid state or input.
pub trait CheckedUnivariate : Distribution {
    /// Returns the mean for a given distribution or a `StatsError`
    /// depending on the implementor. This method should not panic
    /// but return a `StatsError` instead.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.5, n.mean().unwrap());
    /// ```
    fn mean(&self) -> Result<f64>;

    /// Returns the variance for a given distribution or a `StatsError`
    /// depending on the implementor. This method should not panic
    /// but return a `StatsError` instead.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(1.0 / 12.0, n.variance().unwrap());
    /// ```
    fn variance(&self) -> Result<f64>;

    /// Returns the standard deviation for a given distribution or
    /// a `StatsError` depending on the implementor. This method should
    /// not panic but return a `StatsError` instead.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!((1f64 / 12f64).sqrt(), n.std_dev().unwrap());
    /// ```
    fn std_dev(&self) -> Result<f64>;

    /// Returns the entropy for a given distribution or a `StatsError`
    /// depending on the implementor. This method should not panic but
    /// return a `StatsError` instead.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.0, n.entropy().unwrap());
    /// ```
    fn entropy(&self) -> Result<f64>;

    /// Returns the skewness for a given distribution or a `StatsError`
    /// depending on the implementor. This method should not panic but
    /// return a `StatsError` instead.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.0, n.skewness().unwrap());
    /// ```
    fn skewness(&self) -> Result<f64>;

    /// Returns the median for a given distribution or a `StatsError`
    /// depending on the implementor. This method should not panic but
    /// return a `StatsError` instead.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.5, n.median());
    /// ```
    fn median(&self) -> Result<f64>;

    /// Returns the cumulative distribution function calculated
    /// at `x` for a given distribution or a `StatsError` depending
    /// on the implementor. This method should not panic but return a
    /// `StatsError` instead. `StatsError`s should be returned for argument
    /// bound violations.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0, 1).unwrap();
    /// assert_eq!(0.5, n.cdf(0.5));
    /// ```
    fn cdf(&self) -> Result<f64>;
}

/// The `Continuous` trait extends the `Univariate`
/// trait and provides an interface for interacting with continuous
/// univariate statistical distributions
///
/// # Remarks
///
/// All methods provided by the `Continuous` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution. The `CheckedContinuous`
/// trait provides a panic-safe interface for continuous distributions
pub trait Continuous : Univariate {
    fn mode(&self) -> f64;
    fn min(&self) -> f64;
    fn max(&self) -> f64;
    fn pdf(&self, x: f64) -> f64;
    fn ln_pdf(&self, x: f64) -> f64;
}

/// The `CheckedContinous` trait extends the `CheckedUnivariate`
/// trait and provides a checked interface for interacting with
/// continous univariate statistical distributions. This means
/// implementors should return an `Err` instead of panicking on
/// an invalid state or input.
pub trait CheckedContinuous : CheckedUnivariate {
    fn mode(&self) -> Result<f64>;
    fn min(&self) -> Result<f64>;
    fn max(&self) -> Result<f64>;
    fn pdf(&self, x: f64) -> Result<f64>;
    fn ln_pdf(&self, x: f64) -> Result<f64>;
}

/// The `Discrete` trait extends the `Univariate`
/// trait and provides an interface for interacting with discrete
/// univariate statistical distributions
///
/// # Remakrs
///
/// All methods provided by the `Discrete` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution. The `CheckedDiscrete` trait
/// provides a panic-safe interface for discrete distributions
pub trait Discrete : Univariate {
    fn mode(&self) -> i64;
    fn min(&self) -> i64;
    fn max(&self) -> i64;
    fn pmf(&self, x: i64) -> f64;
    fn ln_pmf(&self, x: i64) -> f64;
}

/// The `CheckedDiscrete` trait extends the `CheckedUnivariate` trait
/// and provides a checked interface for interacting with discrete
/// univariate statistical distributions. This means implementors
/// should return an `Err` instead of panicking on an invalid state
/// or input
pub trait CheckedDiscrete : CheckedUnivariate {
    fn mode(&self) -> Result<i64>;
    fn min(&self) -> Result<i64>;
    fn max(&self) -> Result<i64>;
    fn pmf(&self, x: i64) -> Result<f64>;
    fn ln_pmf(&self, x: i64) -> Result<f64>;
}<|endoftext|>


<commit_before>//! Defines common interfaces for interacting with statistical distributions
//! and provides
//! concrete implementations for a variety of distributions.
use super::statistics::{Max, Min};
use ::num_traits::{float::Float, Bounded, Num};

pub use self::bernoulli::Bernoulli;
pub use self::beta::Beta;
pub use self::binomial::Binomial;
pub use self::categorical::Categorical;
pub use self::cauchy::Cauchy;
pub use self::chi::Chi;
pub use self::chi_squared::ChiSquared;
pub use self::dirac::Dirac;
pub use self::dirichlet::Dirichlet;
pub use self::discrete_uniform::DiscreteUniform;
pub use self::empirical::Empirical;
pub use self::erlang::Erlang;
pub use self::exponential::Exp;
pub use self::fisher_snedecor::FisherSnedecor;
pub use self::gamma::Gamma;
pub use self::geometric::Geometric;
pub use self::hypergeometric::Hypergeometric;
pub use self::inverse_gamma::InverseGamma;
pub use self::laplace::Laplace;
pub use self::log_normal::LogNormal;
pub use self::multinomial::Multinomial;
pub use self::multivariate_normal::MultivariateNormal;
pub use self::negative_binomial::NegativeBinomial;
pub use self::normal::Normal;
pub use self::pareto::Pareto;
pub use self::poisson::Poisson;
pub use self::students_t::StudentsT;
pub use self::triangular::Triangular;
pub use self::uniform::Uniform;
pub use self::weibull::Weibull;

mod bernoulli;
mod beta;
mod binomial;
mod categorical;
mod cauchy;
mod chi;
mod chi_squared;
mod dirac;
mod dirichlet;
mod discrete_uniform;
mod empirical;
mod erlang;
mod exponential;
mod fisher_snedecor;
mod gamma;
mod geometric;
mod hypergeometric;
mod internal;
mod inverse_gamma;
mod laplace;
mod log_normal;
mod multinomial;
mod multivariate_normal;
mod negative_binomial;
mod normal;
mod pareto;
mod poisson;
mod students_t;
mod triangular;
mod uniform;
mod weibull;
mod ziggurat;
mod ziggurat_tables;
mod laplace;

use crate::Result;

/// The `ContinuousCDF` trait is used to specify an interface for univariate
/// distributions for which cdf float arguments are sensible.
pub trait ContinuousCDF<K: Float, T: Float>: Min<K> + Max<K> {
    /// Returns the cumulative distribution function calculated
    /// at `x` for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{ContinuousCDF, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.cdf(0.5));
    /// ```
    fn cdf(&self, x: K) -> T;
    /// Due to issues with rounding and floating-point accuracy the default
    /// implementation may be ill-behaved.
    /// Specialized inverse cdfs should be used whenever possible.
    /// Performs a binary search on the domain of `cdf` to obtain an approximation
    /// of `F^-1(p) := inf { x | F(x) >= p }`. Needless to say, performance may
    /// may be lacking.
    fn inverse_cdf(&self, p: T) -> K {
        if p == T::zero() {
            return self.min();
        };
        if p == T::one() {
            return self.max();
        };
        let two = K::one() + K::one();
        let mut high = two;
        let mut low = -high;
        while self.cdf(low) > p {
            low = low + low;
        }
        while self.cdf(high) < p {
            high = high + high;
        }
        let mut i = 16;
        while i != 0 {
            let mid = (high + low) / two;
            if self.cdf(mid) >= p {
                high = mid;
            } else {
                low = mid;
            }
            i -= 1;
        }
        (high + low) / two
    }
}

/// The `DiscreteCDF` trait is used to specify an interface for univariate
/// discrete distributions.
pub trait DiscreteCDF<K: Bounded + Clone + Num, T: Float>: Min<K> + Max<K> {
    /// Returns the cumulative distribution function calculated
    /// at `x` for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{ContinuousCDF, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.cdf(0.5));
    /// ```
    fn cdf(&self, x: K) -> T;
    /// Due to issues with rounding and floating-point accuracy the default implementation may be ill-behaved
    /// Specialized inverse cdfs should be used whenever possible.
    fn inverse_cdf(&self, p: T) -> K {
        // TODO: fix integer implementation
        if p == T::zero() {
            return self.min();
        };
        if p == T::one() {
            return self.max();
        };
        let two = K::one() + K::one();
        let mut high = two.clone();
        let mut low = K::min_value();
        while self.cdf(high.clone()) < p {
            high = high.clone() + high.clone();
        }
        while high != low {
            let mid = (high.clone() + low.clone()) / two.clone();
            if self.cdf(mid.clone()) >= p {
                high = mid;
            } else {
                low = mid;
            }
        }
        high
    }
}

/// The `Continuous` trait  provides an interface for interacting with
/// continuous statistical distributions
///
/// # Remarks
///
/// All methods provided by the `Continuous` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution.
pub trait Continuous<K, T> {
    /// Returns the probability density function calculated at `x` for a given
    /// distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0, n.pdf(0.5));
    /// ```
    fn pdf(&self, x: K) -> T;

    /// Returns the log of the probability density function calculated at `x`
    /// for a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.ln_pdf(0.5));
    /// ```
    fn ln_pdf(&self, x: K) -> T;
}

/// The `Discrete` trait provides an interface for interacting with discrete
/// statistical distributions
///
/// # Remarks
///
/// All methods provided by the `Discrete` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution.
pub trait Discrete<K, T> {
    /// Returns the probability mass function calculated at `x` for a given
    /// distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    /// use statrs::prec;
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert!(prec::almost_eq(n.pmf(5), 0.24609375, 1e-15));
    /// ```
    fn pmf(&self, x: K) -> T;

    /// Returns the log of the probability mass function calculated at `x` for
    /// a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    /// use statrs::prec;
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert!(prec::almost_eq(n.ln_pmf(5), (0.24609375f64).ln(), 1e-15));
    /// ```
    fn ln_pmf(&self, x: K) -> T;
}
<commit_msg>fix: remove second statrs::distribution::laplace<commit_after>//! Defines common interfaces for interacting with statistical distributions
//! and provides
//! concrete implementations for a variety of distributions.
use super::statistics::{Max, Min};
use ::num_traits::{float::Float, Bounded, Num};

pub use self::bernoulli::Bernoulli;
pub use self::beta::Beta;
pub use self::binomial::Binomial;
pub use self::categorical::Categorical;
pub use self::cauchy::Cauchy;
pub use self::chi::Chi;
pub use self::chi_squared::ChiSquared;
pub use self::dirac::Dirac;
pub use self::dirichlet::Dirichlet;
pub use self::discrete_uniform::DiscreteUniform;
pub use self::empirical::Empirical;
pub use self::erlang::Erlang;
pub use self::exponential::Exp;
pub use self::fisher_snedecor::FisherSnedecor;
pub use self::gamma::Gamma;
pub use self::geometric::Geometric;
pub use self::hypergeometric::Hypergeometric;
pub use self::inverse_gamma::InverseGamma;
pub use self::laplace::Laplace;
pub use self::log_normal::LogNormal;
pub use self::multinomial::Multinomial;
pub use self::multivariate_normal::MultivariateNormal;
pub use self::negative_binomial::NegativeBinomial;
pub use self::normal::Normal;
pub use self::pareto::Pareto;
pub use self::poisson::Poisson;
pub use self::students_t::StudentsT;
pub use self::triangular::Triangular;
pub use self::uniform::Uniform;
pub use self::weibull::Weibull;

mod bernoulli;
mod beta;
mod binomial;
mod categorical;
mod cauchy;
mod chi;
mod chi_squared;
mod dirac;
mod dirichlet;
mod discrete_uniform;
mod empirical;
mod erlang;
mod exponential;
mod fisher_snedecor;
mod gamma;
mod geometric;
mod hypergeometric;
mod internal;
mod inverse_gamma;
mod laplace;
mod log_normal;
mod multinomial;
mod multivariate_normal;
mod negative_binomial;
mod normal;
mod pareto;
mod poisson;
mod students_t;
mod triangular;
mod uniform;
mod weibull;
mod ziggurat;
mod ziggurat_tables;

use crate::Result;

/// The `ContinuousCDF` trait is used to specify an interface for univariate
/// distributions for which cdf float arguments are sensible.
pub trait ContinuousCDF<K: Float, T: Float>: Min<K> + Max<K> {
    /// Returns the cumulative distribution function calculated
    /// at `x` for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{ContinuousCDF, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.cdf(0.5));
    /// ```
    fn cdf(&self, x: K) -> T;
    /// Due to issues with rounding and floating-point accuracy the default
    /// implementation may be ill-behaved.
    /// Specialized inverse cdfs should be used whenever possible.
    /// Performs a binary search on the domain of `cdf` to obtain an approximation
    /// of `F^-1(p) := inf { x | F(x) >= p }`. Needless to say, performance may
    /// may be lacking.
    fn inverse_cdf(&self, p: T) -> K {
        if p == T::zero() {
            return self.min();
        };
        if p == T::one() {
            return self.max();
        };
        let two = K::one() + K::one();
        let mut high = two;
        let mut low = -high;
        while self.cdf(low) > p {
            low = low + low;
        }
        while self.cdf(high) < p {
            high = high + high;
        }
        let mut i = 16;
        while i != 0 {
            let mid = (high + low) / two;
            if self.cdf(mid) >= p {
                high = mid;
            } else {
                low = mid;
            }
            i -= 1;
        }
        (high + low) / two
    }
}

/// The `DiscreteCDF` trait is used to specify an interface for univariate
/// discrete distributions.
pub trait DiscreteCDF<K: Bounded + Clone + Num, T: Float>: Min<K> + Max<K> {
    /// Returns the cumulative distribution function calculated
    /// at `x` for a given distribution. May panic depending
    /// on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{ContinuousCDF, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.cdf(0.5));
    /// ```
    fn cdf(&self, x: K) -> T;
    /// Due to issues with rounding and floating-point accuracy the default implementation may be ill-behaved
    /// Specialized inverse cdfs should be used whenever possible.
    fn inverse_cdf(&self, p: T) -> K {
        // TODO: fix integer implementation
        if p == T::zero() {
            return self.min();
        };
        if p == T::one() {
            return self.max();
        };
        let two = K::one() + K::one();
        let mut high = two.clone();
        let mut low = K::min_value();
        while self.cdf(high.clone()) < p {
            high = high.clone() + high.clone();
        }
        while high != low {
            let mid = (high.clone() + low.clone()) / two.clone();
            if self.cdf(mid.clone()) >= p {
                high = mid;
            } else {
                low = mid;
            }
        }
        high
    }
}

/// The `Continuous` trait  provides an interface for interacting with
/// continuous statistical distributions
///
/// # Remarks
///
/// All methods provided by the `Continuous` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution.
pub trait Continuous<K, T> {
    /// Returns the probability density function calculated at `x` for a given
    /// distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0, n.pdf(0.5));
    /// ```
    fn pdf(&self, x: K) -> T;

    /// Returns the log of the probability density function calculated at `x`
    /// for a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Continuous, Uniform};
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.ln_pdf(0.5));
    /// ```
    fn ln_pdf(&self, x: K) -> T;
}

/// The `Discrete` trait provides an interface for interacting with discrete
/// statistical distributions
///
/// # Remarks
///
/// All methods provided by the `Discrete` trait are unchecked, meaning
/// they can panic if in an invalid state or encountering invalid input
/// depending on the implementing distribution.
pub trait Discrete<K, T> {
    /// Returns the probability mass function calculated at `x` for a given
    /// distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    /// use statrs::prec;
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert!(prec::almost_eq(n.pmf(5), 0.24609375, 1e-15));
    /// ```
    fn pmf(&self, x: K) -> T;

    /// Returns the log of the probability mass function calculated at `x` for
    /// a given distribution.
    /// May panic depending on the implementor.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::{Discrete, Binomial};
    /// use statrs::prec;
    ///
    /// let n = Binomial::new(0.5, 10).unwrap();
    /// assert!(prec::almost_eq(n.ln_pmf(5), (0.24609375f64).ln(), 1e-15));
    /// ```
    fn ln_pmf(&self, x: K) -> T;
}
<|endoftext|>