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

//! Thread-local random number generator

use std::cell::UnsafeCell;
use std::rc::Rc;

use {RngCore, CryptoRng, SeedableRng, EntropyRng};
use prng::hc128::Hc128Core;
use {Distribution, Standard, Rng, Error};
use reseeding::ReseedingRng;

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
// Previously we used a `RefCell`, with an overhead of ~15%. There will only
// ever be one mutable reference to the interior of the `UnsafeCell`, because
// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
// single thread (which is the definition of `ThreadRng`), there will only ever
// be one of these methods active at a time.
//
// A possible scenario where there could be multiple mutable references is if
// `ThreadRng` is used inside `next_u32` and co. But the implementation is
// completely under our control. We just have to ensure none of them use
// `ThreadRng` internally, which is nonsensical anyway. We should also never run
// `ThreadRng` in destructors of its implementation, which is also nonsensical.
//
// The additional `Rc` is not strictly neccesary, and could be removed. For now
// it ensures `ThreadRng` stays `!Send` and `!Sync`, and implements `Clone`.

// Number of generated bytes after which to reseed `TreadRng`.
//
// The time it takes to reseed HC-128 is roughly equivalent to generating 7 KiB.
// We pick a treshold here that is large enough to not reduce the average
// performance too much, but also small enough to not make reseeding something
// that basically never happens.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB

/// The type returned by [`thread_rng`], essentially just a reference to the
/// PRNG in thread-local memory.
///
/// Cloning this handle just produces a new reference to the same thread-local
/// generator.
///
/// [`thread_rng`]: fn.thread_rng.html
#[derive(Clone, Debug)]
pub struct ThreadRng {
    rng: Rc<UnsafeCell<ReseedingRng<Hc128Core, EntropyRng>>>,
}

thread_local!(
    static THREAD_RNG_KEY: Rc<UnsafeCell<ReseedingRng<Hc128Core, EntropyRng>>> = {
        let mut entropy_source = EntropyRng::new();
        let r = Hc128Core::from_rng(&mut entropy_source).unwrap_or_else(|err|
                panic!("could not initialize thread_rng: {}", err));
        let rng = ReseedingRng::new(r,
                                    THREAD_RNG_RESEED_THRESHOLD,
                                    entropy_source);
        Rc::new(UnsafeCell::new(rng))
    }
);

/// Retrieve the lazily-initialized thread-local random number
/// generator, seeded by the system. Intended to be used in method
/// chaining style, e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
/// `let mut rng = thread_rng();`.
///
/// `ThreadRng` uses [`ReseedingRng`] wrapping the same PRNG as [`StdRng`],
/// which is reseeded after generating 32 MiB of random data. A single instance
/// is cached per thread and the returned `ThreadRng` is a reference to this
/// instance — hence `ThreadRng` is neither `Send` nor `Sync` but is safe to use
/// within a single thread. This RNG is seeded and reseeded via [`EntropyRng`]
/// as required.
///
/// Note that the reseeding is done as an extra precaution against entropy
/// leaks and is in theory unnecessary — to predict `thread_rng`'s output, an
/// attacker would have to either determine most of the RNG's seed or internal
/// state, or crack the algorithm used.
///
/// Like [`StdRng`], `ThreadRng` is a cryptographically secure PRNG. The current
/// algorithm used is [HC-128], which is an array-based PRNG that trades memory
/// usage for better performance. This makes it similar to ISAAC, the algorithm
/// used in `ThreadRng` before rand 0.5.
///
/// [`ReseedingRng`]: reseeding/struct.ReseedingRng.html
/// [`StdRng`]: struct.StdRng.html
/// [`EntropyRng`]: struct.EntropyRng.html
/// [HC-128]: prng/hc128/struct.Hc128Rng.html
pub fn thread_rng() -> ThreadRng {
    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
}

impl RngCore for ThreadRng {
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        unsafe { (*self.rng.get()).next_u32() }
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        unsafe { (*self.rng.get()).next_u64() }
    }

    fn fill_bytes(&mut self, bytes: &mut [u8]) {
        unsafe { (*self.rng.get()).fill_bytes(bytes) }
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        unsafe { (*self.rng.get()).try_fill_bytes(dest) }
    }
}

impl CryptoRng for ThreadRng {}

/// DEPRECATED: use `thread_rng().gen()` instead.
///
/// Generates a random value using the thread-local random number generator.
///
/// This is simply a shortcut for `thread_rng().gen()`. See [`thread_rng`] for
/// documentation of the entropy source and [`Rand`] for documentation of
/// distributions and type-specific generation.
///
/// # Examples
///
/// ```
/// # #![allow(deprecated)]
/// let x = rand::random::<u8>();
/// println!("{}", x);
///
/// let y = rand::random::<f64>();
/// println!("{}", y);
///
/// if rand::random() { // generates a boolean
///     println!("Better lucky than good!");
/// }
/// ```
///
/// If you're calling `random()` in a loop, caching the generator as in the
/// following example can increase performance.
///
/// ```
/// # #![allow(deprecated)]
/// use rand::Rng;
///
/// let mut v = vec![1, 2, 3];
///
/// for x in v.iter_mut() {
///     *x = rand::random()
/// }
///
/// // can be made faster by caching thread_rng
///
/// let mut rng = rand::thread_rng();
///
/// for x in v.iter_mut() {
///     *x = rng.gen();
/// }
/// ```
///
/// [`thread_rng`]: fn.thread_rng.html
/// [`Rand`]: trait.Rand.html
#[deprecated(since="0.5.0", note="removed in favor of thread_rng().gen()")]
#[inline]
pub fn random<T>() -> T where Standard: Distribution<T> {
    thread_rng().gen()
}

#[cfg(test)]
mod test {
    #[test]
    #[cfg(not(feature="stdweb"))]
    fn test_thread_rng() {
        use Rng;
        let mut r = ::thread_rng();
        r.gen::<i32>();
        let mut v = [1, 1, 1];
        r.shuffle(&mut v);
        let b: &[_] = &[1, 1, 1];
        assert_eq!(v, b);
        assert_eq!(r.gen_range(0, 1), 0);
    }

    #[test]
    #[allow(deprecated)]
    fn test_random() {
        use super::random;
        // not sure how to test this aside from just getting some values
        let _n : usize = random();
        let _f : f32 = random();
        let _o : Option<Option<i8>> = random();
        let _many : ((),
                     (usize,
                      isize,
                      Option<(u32, (bool,))>),
                     (u8, i8, u16, i16, u32, i32, u64, i64),
                     (f32, (f64, (f64,)))) = random();
    }
}
<commit_msg>Un-deprecate random()<commit_after>// Copyright 2017-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Thread-local random number generator

use std::cell::UnsafeCell;
use std::rc::Rc;

use {RngCore, CryptoRng, SeedableRng, EntropyRng};
use prng::hc128::Hc128Core;
use {Distribution, Standard, Rng, Error};
use reseeding::ReseedingRng;

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
// Previously we used a `RefCell`, with an overhead of ~15%. There will only
// ever be one mutable reference to the interior of the `UnsafeCell`, because
// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
// single thread (which is the definition of `ThreadRng`), there will only ever
// be one of these methods active at a time.
//
// A possible scenario where there could be multiple mutable references is if
// `ThreadRng` is used inside `next_u32` and co. But the implementation is
// completely under our control. We just have to ensure none of them use
// `ThreadRng` internally, which is nonsensical anyway. We should also never run
// `ThreadRng` in destructors of its implementation, which is also nonsensical.
//
// The additional `Rc` is not strictly neccesary, and could be removed. For now
// it ensures `ThreadRng` stays `!Send` and `!Sync`, and implements `Clone`.

// Number of generated bytes after which to reseed `TreadRng`.
//
// The time it takes to reseed HC-128 is roughly equivalent to generating 7 KiB.
// We pick a treshold here that is large enough to not reduce the average
// performance too much, but also small enough to not make reseeding something
// that basically never happens.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB

/// The type returned by [`thread_rng`], essentially just a reference to the
/// PRNG in thread-local memory.
///
/// Cloning this handle just produces a new reference to the same thread-local
/// generator.
///
/// [`thread_rng`]: fn.thread_rng.html
#[derive(Clone, Debug)]
pub struct ThreadRng {
    rng: Rc<UnsafeCell<ReseedingRng<Hc128Core, EntropyRng>>>,
}

thread_local!(
    static THREAD_RNG_KEY: Rc<UnsafeCell<ReseedingRng<Hc128Core, EntropyRng>>> = {
        let mut entropy_source = EntropyRng::new();
        let r = Hc128Core::from_rng(&mut entropy_source).unwrap_or_else(|err|
                panic!("could not initialize thread_rng: {}", err));
        let rng = ReseedingRng::new(r,
                                    THREAD_RNG_RESEED_THRESHOLD,
                                    entropy_source);
        Rc::new(UnsafeCell::new(rng))
    }
);

/// Retrieve the lazily-initialized thread-local random number
/// generator, seeded by the system. Intended to be used in method
/// chaining style, e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
/// `let mut rng = thread_rng();`.
///
/// `ThreadRng` uses [`ReseedingRng`] wrapping the same PRNG as [`StdRng`],
/// which is reseeded after generating 32 MiB of random data. A single instance
/// is cached per thread and the returned `ThreadRng` is a reference to this
/// instance — hence `ThreadRng` is neither `Send` nor `Sync` but is safe to use
/// within a single thread. This RNG is seeded and reseeded via [`EntropyRng`]
/// as required.
///
/// Note that the reseeding is done as an extra precaution against entropy
/// leaks and is in theory unnecessary — to predict `thread_rng`'s output, an
/// attacker would have to either determine most of the RNG's seed or internal
/// state, or crack the algorithm used.
///
/// Like [`StdRng`], `ThreadRng` is a cryptographically secure PRNG. The current
/// algorithm used is [HC-128], which is an array-based PRNG that trades memory
/// usage for better performance. This makes it similar to ISAAC, the algorithm
/// used in `ThreadRng` before rand 0.5.
///
/// [`ReseedingRng`]: reseeding/struct.ReseedingRng.html
/// [`StdRng`]: struct.StdRng.html
/// [`EntropyRng`]: struct.EntropyRng.html
/// [HC-128]: prng/hc128/struct.Hc128Rng.html
pub fn thread_rng() -> ThreadRng {
    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
}

impl RngCore for ThreadRng {
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        unsafe { (*self.rng.get()).next_u32() }
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        unsafe { (*self.rng.get()).next_u64() }
    }

    fn fill_bytes(&mut self, bytes: &mut [u8]) {
        unsafe { (*self.rng.get()).fill_bytes(bytes) }
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        unsafe { (*self.rng.get()).try_fill_bytes(dest) }
    }
}

impl CryptoRng for ThreadRng {}

/// Generates a random value using the thread-local random number generator.
///
/// This is simply a shortcut for `thread_rng().gen()`. See [`thread_rng`] for
/// documentation of the entropy source and [`Standard`] for documentation of
/// distributions and type-specific generation.
///
/// # Examples
///
/// ```rust
/// let x = rand::random::<u8>();
/// println!("{}", x);
///
/// let y = rand::random::<f64>();
/// println!("{}", y);
///
/// if rand::random() { // generates a boolean
///     println!("Better lucky than good!");
/// }
/// ```
///
/// If you're calling `random()` in a loop, caching the generator as in the
/// following example can increase performance.
///
/// ```rust
/// # #![allow(deprecated)]
/// use rand::Rng;
///
/// let mut v = vec![1, 2, 3];
///
/// for x in v.iter_mut() {
///     *x = rand::random()
/// }
///
/// // can be made faster by caching thread_rng
///
/// let mut rng = rand::thread_rng();
///
/// for x in v.iter_mut() {
///     *x = rng.gen();
/// }
/// ```
///
/// [`thread_rng`]: fn.thread_rng.html
/// [`Standard`]: distributions/struct.Standard.html
#[inline]
pub fn random<T>() -> T where Standard: Distribution<T> {
    thread_rng().gen()
}

#[cfg(test)]
mod test {
    #[test]
    #[cfg(not(feature="stdweb"))]
    fn test_thread_rng() {
        use Rng;
        let mut r = ::thread_rng();
        r.gen::<i32>();
        let mut v = [1, 1, 1];
        r.shuffle(&mut v);
        let b: &[_] = &[1, 1, 1];
        assert_eq!(v, b);
        assert_eq!(r.gen_range(0, 1), 0);
    }

    #[test]
    #[allow(deprecated)]
    fn test_random() {
        use super::random;
        // not sure how to test this aside from just getting some values
        let _n : usize = random();
        let _f : f32 = random();
        let _o : Option<Option<i8>> = random();
        let _many : ((),
                     (usize,
                      isize,
                      Option<(u32, (bool,))>),
                     (u8, i8, u16, i16, u32, i32, u64, i64),
                     (f32, (f64, (f64,)))) = random();
    }
}
<|endoftext|>


<commit_before>//! Topic name

use std::io::{Read, Write};
use std::convert::Into;
use std::ops::Deref;
use std::fmt;
use std::error::Error;
use std::mem;

use regex::Regex;

use encodable::StringEncodeError;
use {Encodable, Decodable};

const TOPIC_NAME_VALIDATE_REGEX: &'static str = r"^[^#+]+$";

lazy_static! {
    static ref TOPIC_NAME_VALIDATOR: Regex = Regex::new(TOPIC_NAME_VALIDATE_REGEX).unwrap();
}

#[inline]
fn is_invalid_topic_name(topic_name: &str) -> bool {
    topic_name.is_empty() || topic_name.as_bytes().len() > 65535 || !TOPIC_NAME_VALIDATOR.is_match(&topic_name)
}

/// Topic name
///
/// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718106
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct TopicName(String);

impl TopicName {
    /// Creates a new topic name from string
    /// Return error if the string is not a valid topic name
    pub fn new<S: Into<String>>(topic_name: S) -> Result<TopicName, TopicNameError> {
        let topic_name = topic_name.into();
        if is_invalid_topic_name(&topic_name) {
            Err(TopicNameError::InvalidTopicName(topic_name))
        } else {
            Ok(TopicName(topic_name))
        }
    }

    /// Creates a new topic name from string without validation
    pub unsafe fn new_unchecked(topic_name: String) -> TopicName {
        TopicName(topic_name)
    }
}

impl Into<String> for TopicName {
    fn into(self) -> String {
        self.0
    }
}

impl Deref for TopicName {
    type Target = TopicNameRef;

    fn deref(&self) -> &TopicNameRef {
        unsafe { TopicNameRef::new_unchecked(&self.0) }
    }
}

impl<'a> Encodable<'a> for TopicName {
    type Err = TopicNameError;

    fn encode<W: Write>(&self, writer: &mut W) -> Result<(), TopicNameError> {
        (&self.0[..])
            .encode(writer)
            .map_err(TopicNameError::StringEncodeError)
    }

    fn encoded_length(&self) -> u32 {
        (&self.0[..]).encoded_length()
    }
}

impl<'a> Decodable<'a> for TopicName {
    type Err = TopicNameError;
    type Cond = ();

    fn decode_with<R: Read>(reader: &mut R, _rest: Option<()>) -> Result<TopicName, TopicNameError> {
        let topic_name: String = try!(Decodable::decode(reader).map_err(TopicNameError::StringEncodeError));
        TopicName::new(topic_name)
    }
}

/// Errors while parsing topic names
#[derive(Debug)]
pub enum TopicNameError {
    StringEncodeError(StringEncodeError),
    InvalidTopicName(String),
}

impl fmt::Display for TopicNameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &TopicNameError::StringEncodeError(ref err) => err.fmt(f),
            &TopicNameError::InvalidTopicName(ref topic) => write!(f, "Invalid topic filter ({})", topic),
        }
    }
}

impl Error for TopicNameError {
    fn description(&self) -> &str {
        match self {
            &TopicNameError::StringEncodeError(ref err) => err.description(),
            &TopicNameError::InvalidTopicName(..) => "Invalid topic filter",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &TopicNameError::StringEncodeError(ref err) => Some(err),
            &TopicNameError::InvalidTopicName(..) => None,
        }
    }
}

/// Reference to a topic name
#[derive(Debug, Eq, PartialEq)]
pub struct TopicNameRef(str);

impl TopicNameRef {
    /// Creates a new topic name from string
    /// Return error if the string is not a valid topic name
    pub fn new<S: AsRef<str> + ?Sized>(topic_name: &S) -> Result<&TopicNameRef, TopicNameError> {
        let topic_name = topic_name.as_ref();
        if is_invalid_topic_name(&topic_name) {
            Err(TopicNameError::InvalidTopicName(topic_name.to_owned()))
        } else {
            Ok(unsafe { mem::transmute(topic_name) })
        }
    }

    /// Creates a new topic name from string without validation
    pub unsafe fn new_unchecked<S: AsRef<str> + ?Sized>(topic_name: &S) -> &TopicNameRef {
        mem::transmute(topic_name.as_ref())
    }

    /// Check if this topic name is only for server.
    ///
    /// Topic names that beginning with a '$' character are reserved for servers
    pub fn is_server_specific(&self) -> bool {
        self.0.starts_with('$')
    }
}

impl Deref for TopicNameRef {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

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

    #[test]
    fn topic_name_sys() {
        let topic_name = "$SYS".to_owned();
        TopicName::new(topic_name).unwrap();

        let topic_name = "$SYS/broker/connection/test.cosm-energy/state".to_owned();
        TopicName::new(topic_name).unwrap();
    }

    #[test]
    fn topic_name_slash() {
        TopicName::new("/").unwrap();
    }

    #[test]
    fn topic_name_basic() {
        TopicName::new("/finance").unwrap();
        TopicName::new("/finance//def").unwrap();
    }
}
<commit_msg>Added Hash for TopicName<commit_after>//! Topic name

use std::io::{Read, Write};
use std::convert::Into;
use std::ops::Deref;
use std::fmt;
use std::error::Error;
use std::mem;

use regex::Regex;

use encodable::StringEncodeError;
use {Encodable, Decodable};

const TOPIC_NAME_VALIDATE_REGEX: &'static str = r"^[^#+]+$";

lazy_static! {
    static ref TOPIC_NAME_VALIDATOR: Regex = Regex::new(TOPIC_NAME_VALIDATE_REGEX).unwrap();
}

#[inline]
fn is_invalid_topic_name(topic_name: &str) -> bool {
    topic_name.is_empty() || topic_name.as_bytes().len() > 65535 || !TOPIC_NAME_VALIDATOR.is_match(&topic_name)
}

/// Topic name
///
/// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718106
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct TopicName(String);

impl TopicName {
    /// Creates a new topic name from string
    /// Return error if the string is not a valid topic name
    pub fn new<S: Into<String>>(topic_name: S) -> Result<TopicName, TopicNameError> {
        let topic_name = topic_name.into();
        if is_invalid_topic_name(&topic_name) {
            Err(TopicNameError::InvalidTopicName(topic_name))
        } else {
            Ok(TopicName(topic_name))
        }
    }

    /// Creates a new topic name from string without validation
    pub unsafe fn new_unchecked(topic_name: String) -> TopicName {
        TopicName(topic_name)
    }
}

impl Into<String> for TopicName {
    fn into(self) -> String {
        self.0
    }
}

impl Deref for TopicName {
    type Target = TopicNameRef;

    fn deref(&self) -> &TopicNameRef {
        unsafe { TopicNameRef::new_unchecked(&self.0) }
    }
}

impl<'a> Encodable<'a> for TopicName {
    type Err = TopicNameError;

    fn encode<W: Write>(&self, writer: &mut W) -> Result<(), TopicNameError> {
        (&self.0[..])
            .encode(writer)
            .map_err(TopicNameError::StringEncodeError)
    }

    fn encoded_length(&self) -> u32 {
        (&self.0[..]).encoded_length()
    }
}

impl<'a> Decodable<'a> for TopicName {
    type Err = TopicNameError;
    type Cond = ();

    fn decode_with<R: Read>(reader: &mut R, _rest: Option<()>) -> Result<TopicName, TopicNameError> {
        let topic_name: String = try!(Decodable::decode(reader).map_err(TopicNameError::StringEncodeError));
        TopicName::new(topic_name)
    }
}

/// Errors while parsing topic names
#[derive(Debug)]
pub enum TopicNameError {
    StringEncodeError(StringEncodeError),
    InvalidTopicName(String),
}

impl fmt::Display for TopicNameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &TopicNameError::StringEncodeError(ref err) => err.fmt(f),
            &TopicNameError::InvalidTopicName(ref topic) => write!(f, "Invalid topic filter ({})", topic),
        }
    }
}

impl Error for TopicNameError {
    fn description(&self) -> &str {
        match self {
            &TopicNameError::StringEncodeError(ref err) => err.description(),
            &TopicNameError::InvalidTopicName(..) => "Invalid topic filter",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &TopicNameError::StringEncodeError(ref err) => Some(err),
            &TopicNameError::InvalidTopicName(..) => None,
        }
    }
}

/// Reference to a topic name
#[derive(Debug, Eq, PartialEq)]
pub struct TopicNameRef(str);

impl TopicNameRef {
    /// Creates a new topic name from string
    /// Return error if the string is not a valid topic name
    pub fn new<S: AsRef<str> + ?Sized>(topic_name: &S) -> Result<&TopicNameRef, TopicNameError> {
        let topic_name = topic_name.as_ref();
        if is_invalid_topic_name(&topic_name) {
            Err(TopicNameError::InvalidTopicName(topic_name.to_owned()))
        } else {
            Ok(unsafe { mem::transmute(topic_name) })
        }
    }

    /// Creates a new topic name from string without validation
    pub unsafe fn new_unchecked<S: AsRef<str> + ?Sized>(topic_name: &S) -> &TopicNameRef {
        mem::transmute(topic_name.as_ref())
    }

    /// Check if this topic name is only for server.
    ///
    /// Topic names that beginning with a '$' character are reserved for servers
    pub fn is_server_specific(&self) -> bool {
        self.0.starts_with('$')
    }
}

impl Deref for TopicNameRef {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

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

    #[test]
    fn topic_name_sys() {
        let topic_name = "$SYS".to_owned();
        TopicName::new(topic_name).unwrap();

        let topic_name = "$SYS/broker/connection/test.cosm-energy/state".to_owned();
        TopicName::new(topic_name).unwrap();
    }

    #[test]
    fn topic_name_slash() {
        TopicName::new("/").unwrap();
    }

    #[test]
    fn topic_name_basic() {
        TopicName::new("/finance").unwrap();
        TopicName::new("/finance//def").unwrap();
    }
}
<|endoftext|>


<commit_before>use core::cellbuffer::{CellAccessor, Cell};
use ui::layout::{HorizontalAlign, VerticalAlign};

#[derive(Clone, Copy)]
pub enum Orientation {
    Horizontal,
    Vertical,
}

pub trait Painter: CellAccessor {
    /// Prints a string at the specified position.
    ///
    /// This is a shorthand for setting each cell individually. `cell`'s style is going to be
    /// copied to each destination cell.
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::{Terminal, Cell, Color, Attr};
    /// use rustty::ui::Painter;
    ///
    /// let mut term = Terminal::new().unwrap();
    /// let cell = Cell::with_style(Color::Default, Color::Red, Attr::Default);
    /// term.printline_with_cell(0, 0, "foobar", cell);
    /// ```
    fn printline_with_cell(&mut self, x: usize, y: usize, line: &str, cell: Cell) {
        let (cols, _) = self.size();
        for (index, ch) in line.chars().enumerate() {
            let current_x = x + index;
            if current_x >= cols {
                break;
            }
            match self.get_mut(current_x, y) {
                Some(c) => { c.set_fg(cell.fg()); c.set_bg(cell.bg()); c.set_ch(ch); },
                None => {},
            }
        }
    }

    /// Prints a string at the specified position.
    ///
    /// Shorthand for `printline_with_cell(x, y, line, Cell::default())`.
    fn printline(&mut self, x: usize, y: usize, line: &str) {
        self.printline_with_cell(x, y, line, Cell::default());
    }

    /// Returns the proper x coord to align `line` in the specified `halign` alignment.
    ///
    /// `margin` is the number of characters we want to leave near the borders.
    fn halign_line(&self, line: &str, halign: HorizontalAlign, margin: usize) -> usize {
        let (cols, _) = self.size();
        match halign {
            HorizontalAlign::Left => margin,
            HorizontalAlign::Right => cols - line.chars().count() - margin - 1,
            HorizontalAlign::Middle => (cols - line.chars().count()) / 2,
        }
    }

    /// Returns the proper y coord to align `line` in the specified `valign` alignment.
    ///
    /// `margin` is the number of characters we want to leave near the borders.
    ///
    /// For now, the contents of line has no incidence whatsoever on the result, but when we
    /// support multi-line strings, it will, so we might as well stay consistent with
    /// `halign_line()`.
    #[allow(unused_variables)]
    fn valign_line(&self, line: &str, valign: VerticalAlign, margin: usize) -> usize {
        let (_, rows) = self.size();
        match valign {
            VerticalAlign::Top => margin,
            VerticalAlign::Bottom => rows - margin - 1,
            VerticalAlign::Middle => rows / 2,
        }
    }

    fn repeat_cell(&mut self, x: usize, y: usize, orientation: Orientation, count: usize, cell: Cell) {
        for i in 0..count {
            let (ix, iy) = match orientation {
                Orientation::Horizontal => (x + i, y),
                Orientation::Vertical => (x, y + i),
            };
            match self.get_mut(ix, iy) {
                Some(c) => { *c = cell; },
                None => (),
            };
        }
    }

    fn draw_box(&mut self) {
        let (cols, rows) = self.size();
        let corners = [
            (0, 0, '┌'),
            (cols-1, 0, '┐'),
            (cols-1, rows-1, '┘'),
            (0, rows-1, '└'),
        ];
        for &(x, y, ch) in corners.iter() {
            self.get_mut(x, y).unwrap().set_ch(ch);
        }
        let lines = [
            (1, 0, cols-2, Orientation::Horizontal, '─'),
            (1, rows-1, cols-2, Orientation::Horizontal, '─'),
            (0, 1, rows-2, Orientation::Vertical, '│'),
            (cols-1, 1, rows-2, Orientation::Vertical, '│'),
        ];
        for &(x, y, count, orientation, ch) in lines.iter() {
            let cell = Cell::with_char(ch);
            self.repeat_cell(x, y, orientation, count, cell);
        }
    }
}

impl<T: CellAccessor> Painter for T {}

<commit_msg>Fix bug where printline_with_cell() ignored the cell's attrs<commit_after>use core::cellbuffer::{CellAccessor, Cell};
use ui::layout::{HorizontalAlign, VerticalAlign};

#[derive(Clone, Copy)]
pub enum Orientation {
    Horizontal,
    Vertical,
}

pub trait Painter: CellAccessor {
    /// Prints a string at the specified position.
    ///
    /// This is a shorthand for setting each cell individually. `cell`'s style is going to be
    /// copied to each destination cell.
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::{Terminal, Cell, Color, Attr};
    /// use rustty::ui::Painter;
    ///
    /// let mut term = Terminal::new().unwrap();
    /// let cell = Cell::with_style(Color::Default, Color::Red, Attr::Default);
    /// term.printline_with_cell(0, 0, "foobar", cell);
    /// ```
    fn printline_with_cell(&mut self, x: usize, y: usize, line: &str, cell: Cell) {
        let (cols, _) = self.size();
        for (index, ch) in line.chars().enumerate() {
            let current_x = x + index;
            if current_x >= cols {
                break;
            }
            match self.get_mut(current_x, y) {
                Some(c) => { c.set_fg(cell.fg()); c.set_bg(cell.bg()); c.set_attrs(cell.attrs()); c.set_ch(ch); },
                None => {},
            }
        }
    }

    /// Prints a string at the specified position.
    ///
    /// Shorthand for `printline_with_cell(x, y, line, Cell::default())`.
    fn printline(&mut self, x: usize, y: usize, line: &str) {
        self.printline_with_cell(x, y, line, Cell::default());
    }

    /// Returns the proper x coord to align `line` in the specified `halign` alignment.
    ///
    /// `margin` is the number of characters we want to leave near the borders.
    fn halign_line(&self, line: &str, halign: HorizontalAlign, margin: usize) -> usize {
        let (cols, _) = self.size();
        match halign {
            HorizontalAlign::Left => margin,
            HorizontalAlign::Right => cols - line.chars().count() - margin - 1,
            HorizontalAlign::Middle => (cols - line.chars().count()) / 2,
        }
    }

    /// Returns the proper y coord to align `line` in the specified `valign` alignment.
    ///
    /// `margin` is the number of characters we want to leave near the borders.
    ///
    /// For now, the contents of line has no incidence whatsoever on the result, but when we
    /// support multi-line strings, it will, so we might as well stay consistent with
    /// `halign_line()`.
    #[allow(unused_variables)]
    fn valign_line(&self, line: &str, valign: VerticalAlign, margin: usize) -> usize {
        let (_, rows) = self.size();
        match valign {
            VerticalAlign::Top => margin,
            VerticalAlign::Bottom => rows - margin - 1,
            VerticalAlign::Middle => rows / 2,
        }
    }

    fn repeat_cell(&mut self, x: usize, y: usize, orientation: Orientation, count: usize, cell: Cell) {
        for i in 0..count {
            let (ix, iy) = match orientation {
                Orientation::Horizontal => (x + i, y),
                Orientation::Vertical => (x, y + i),
            };
            match self.get_mut(ix, iy) {
                Some(c) => { *c = cell; },
                None => (),
            };
        }
    }

    fn draw_box(&mut self) {
        let (cols, rows) = self.size();
        let corners = [
            (0, 0, '┌'),
            (cols-1, 0, '┐'),
            (cols-1, rows-1, '┘'),
            (0, rows-1, '└'),
        ];
        for &(x, y, ch) in corners.iter() {
            self.get_mut(x, y).unwrap().set_ch(ch);
        }
        let lines = [
            (1, 0, cols-2, Orientation::Horizontal, '─'),
            (1, rows-1, cols-2, Orientation::Horizontal, '─'),
            (0, 1, rows-2, Orientation::Vertical, '│'),
            (cols-1, 1, rows-2, Orientation::Vertical, '│'),
        ];
        for &(x, y, count, orientation, ch) in lines.iter() {
            let cell = Cell::with_char(ch);
            self.repeat_cell(x, y, orientation, count, cell);
        }
    }
}

impl<T: CellAccessor> Painter for T {}

<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

//! Vector operations.
use libc::c_int;
use num::traits::NumCast;
use num::complex::{Complex32, Complex64};
use vector::ops::{Copy, Axpy, Scal, Dot, Nrm2, Asum, Iamax};

pub mod ll;
pub mod ops;

/// Methods that allow a type to be used in BLAS functions as a vector.
pub trait Vector<T> {
    /// The stride within the vector. For example, if `inc` returns 7, every
    /// 7th element is used. Defaults to 1.
    fn inc(&self) -> c_int { 1 }
    /// The number of elements in the vector.
    fn len(&self) -> c_int;
    /// An unsafe pointer to a contiguous block of memory.
    unsafe fn as_ptr(&self) -> *const T;
    /// An unsafe mutable pointer to a contiguous block of memory.
    unsafe fn as_mut_ptr(&mut self) -> *mut T;
}

impl<'a, T> Into<Vec<T>> for &'a Vector<T>
    where T: Copy {

    fn into(self) -> Vec<T> {
        let n = self.len() as usize;

        let mut x = Vec::with_capacity(n);
        unsafe { x.set_len(n); }
        Copy::copy(self, &mut x);

        x
    }
}

pub trait VectorOperations<T>: Sized + Vector<T>
    where T: Copy + Axpy + Scal + Dot + Nrm2 + Asum + Iamax {

    #[inline]
    fn update(&mut self, alpha: &T, x: &Vector<T>) -> &mut Self {
        Axpy::axpy(alpha, x, self);
        self
    }

    #[inline]
    fn scale(&mut self, alpha: &T) -> &mut Self {
        Scal::scal(alpha, self);
        self
    }

    #[inline]
    fn dot(&self, x: &Vector<T>) -> T {
        Dot::dot(self, x)
    }

    #[inline]
    fn abs_sum(&self) -> T {
        Asum::asum(self)
    }

    #[inline]
    fn norm(&self) -> T {
        Nrm2::nrm2(self)
    }

    #[inline]
    fn max_index(&self) -> usize {
        Iamax::iamax(self)
    }
}

impl<T> Vector<T> for Vec<T> {

    #[inline]
    fn len(&self) -> c_int {
        let l: Option<c_int> = NumCast::from(Vec::len(self));
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    unsafe fn as_ptr(&self) -> *const T { self[..].as_ptr() }

    #[inline]
    unsafe fn as_mut_ptr(&mut self) -> *mut T { (&mut self[..]).as_mut_ptr() }
}

impl<T> Vector<T> for [T] {

    #[inline]
    fn len(&self) -> c_int {
        let l: Option<c_int> = NumCast::from(<[T]>::len(self));
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    unsafe fn as_ptr(&self) -> *const T { <[T]>::as_ptr(self) }

    #[inline]
    unsafe fn as_mut_ptr(&mut self) -> *mut T { <[T]>::as_mut_ptr(self) }
}

macro_rules! operations_impl(
    ($v: ident, $($t: ty), +) => (
        $( impl VectorOperations<$t> for $v<$t> {} )+
    )
);

operations_impl!(Vec, f32, f64, Complex32, Complex64);
//impl<'a> VectorOperations<f32> for &'a [f32] {}
//impl<'a> VectorOperations<f64> for &'a [f64] {}
//impl<'a> VectorOperations<Complex32> for &'a [Complex32] {}
//impl<'a> VectorOperations<Complex64> for &'a [Complex64] {}
<commit_msg>Actually make ptr methods safe. Closes #14<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

//! Vector operations.
use libc::c_int;
use num::traits::NumCast;
use num::complex::{Complex32, Complex64};
use vector::ops::{Copy, Axpy, Scal, Dot, Nrm2, Asum, Iamax};

pub mod ll;
pub mod ops;

/// Methods that allow a type to be used in BLAS functions as a vector.
pub trait Vector<T> {
    /// The stride within the vector. For example, if `inc` returns 7, every
    /// 7th element is used. Defaults to 1.
    fn inc(&self) -> c_int { 1 }
    /// The number of elements in the vector.
    fn len(&self) -> c_int;
    /// An unsafe pointer to a contiguous block of memory.
    fn as_ptr(&self) -> *const T;
    /// An unsafe mutable pointer to a contiguous block of memory.
    fn as_mut_ptr(&mut self) -> *mut T;
}

impl<'a, T> Into<Vec<T>> for &'a Vector<T>
    where T: Copy {

    fn into(self) -> Vec<T> {
        let n = self.len() as usize;

        let mut x = Vec::with_capacity(n);
        unsafe { x.set_len(n); }
        Copy::copy(self, &mut x);

        x
    }
}

pub trait VectorOperations<T>: Sized + Vector<T>
    where T: Copy + Axpy + Scal + Dot + Nrm2 + Asum + Iamax {

    #[inline]
    fn update(&mut self, alpha: &T, x: &Vector<T>) -> &mut Self {
        Axpy::axpy(alpha, x, self);
        self
    }

    #[inline]
    fn scale(&mut self, alpha: &T) -> &mut Self {
        Scal::scal(alpha, self);
        self
    }

    #[inline]
    fn dot(&self, x: &Vector<T>) -> T {
        Dot::dot(self, x)
    }

    #[inline]
    fn abs_sum(&self) -> T {
        Asum::asum(self)
    }

    #[inline]
    fn norm(&self) -> T {
        Nrm2::nrm2(self)
    }

    #[inline]
    fn max_index(&self) -> usize {
        Iamax::iamax(self)
    }
}

impl<T> Vector<T> for Vec<T> {

    #[inline]
    fn len(&self) -> c_int {
        let l: Option<c_int> = NumCast::from(Vec::len(self));
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn as_ptr(&self) -> *const T { self[..].as_ptr() }

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

impl<T> Vector<T> for [T] {

    #[inline]
    fn len(&self) -> c_int {
        let l: Option<c_int> = NumCast::from(<[T]>::len(self));
        match l {
            Some(l) => l,
            None => panic!(),
        }
    }

    #[inline]
    fn as_ptr(&self) -> *const T { <[T]>::as_ptr(self) }

    #[inline]
    fn as_mut_ptr(&mut self) -> *mut T { <[T]>::as_mut_ptr(self) }
}

macro_rules! operations_impl(
    ($v: ident, $($t: ty), +) => (
        $( impl VectorOperations<$t> for $v<$t> {} )+
    )
);

operations_impl!(Vec, f32, f64, Complex32, Complex64);
//impl<'a> VectorOperations<f32> for &'a [f32] {}
//impl<'a> VectorOperations<f64> for &'a [f64] {}
//impl<'a> VectorOperations<Complex32> for &'a [Complex32] {}
//impl<'a> VectorOperations<Complex64> for &'a [Complex64] {}
<|endoftext|>


<commit_before>
use std::sync::Arc;
use std::collections::HashMap;
use std::borrow::Cow;
use parking_lot::RwLock;
use elements::{Internal, ValueType};
use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
	CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance;
use interpreter::value::RuntimeValue;
use interpreter::variable::{VariableInstance, VariableType};

/// Min index of native function.
pub const NATIVE_INDEX_FUNC_MIN: u32 = 10001;
/// Min index of native global.
pub const NATIVE_INDEX_GLOBAL_MIN: u32 = 20001;

/// User functions executor.
pub trait UserFunctionExecutor {
	/// Execute function with given name.
	fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
}

/// User function descriptor
#[derive(Debug, Clone)]
pub enum UserFunctionDescriptor {
	/// Static function definition
	Static(&'static str, &'static [ValueType], Option<ValueType>),
	/// Dynamic heap function definition
	Heap(String, Vec<ValueType>, Option<ValueType>),
}

impl UserFunctionDescriptor {
	/// New function with statically known params
	pub fn statik(name: &'static str, params: &'static [ValueType], result: Option<ValueType>) -> Self {
		UserFunctionDescriptor::Static(name, params, result)
	}

	/// New function with statically unknown params
	pub fn heap(name: String, params: Vec<ValueType>, result: Option<ValueType>) -> Self {
		UserFunctionDescriptor::Heap(name, params, result)
	}

	/// Name of the function
	pub fn name(&self) -> &str {
		match self {
			&UserFunctionDescriptor::Static(name, _, _) => name,
			&UserFunctionDescriptor::Heap(ref name, _, _) => name,
		}
	}

	/// Arguments of the function
	pub fn params(&self) -> &[ValueType] {
		match self {
			&UserFunctionDescriptor::Static(_, params, _) => params,
			&UserFunctionDescriptor::Heap(_, ref params, _) => params,
		}
	}

	/// Return type of the function
	pub fn return_type(&self) -> Option<ValueType> {
		match self {
			&UserFunctionDescriptor::Static(_, _, result) => result,
			&UserFunctionDescriptor::Heap(_, _, result) => result,
		}
	}
}

/// Set of user-defined module elements.
pub struct UserDefinedElements<'a> {
	/// User globals list.
	pub globals: HashMap<String, Arc<VariableInstance>>,
	/// User functions list.
	pub functions: Cow<'static, [UserFunctionDescriptor]>,
	/// Functions executor.
	pub executor: Option<&'a mut UserFunctionExecutor>,
}

/// Native module instance.
pub struct NativeModuleInstance<'a> {
	/// Underlying module reference.
	base: Arc<ModuleInstanceInterface>,
	/// User function executor.
	executor: RwLock<Option<&'a mut UserFunctionExecutor>>,
	/// By-name functions index.
	functions_by_name: HashMap<String, u32>,
	/// User functions list.
	functions: Cow<'static, [UserFunctionDescriptor]>,
	/// By-name functions index.
	globals_by_name: HashMap<String, u32>,
	/// User globals list.
	globals: Vec<Arc<VariableInstance>>,
}

impl<'a> NativeModuleInstance<'a> {
	/// Create new native module
	pub fn new(base: Arc<ModuleInstanceInterface>, elements: UserDefinedElements<'a>) -> Result<Self, Error> {
		if !elements.functions.is_empty() && elements.executor.is_none() {
			return Err(Error::Function("trying to construct native env module with functions, but without executor".into()));
		}

		Ok(NativeModuleInstance {
			base: base,
			executor: RwLock::new(elements.executor),
			functions_by_name: elements.functions.iter().enumerate().map(|(i, f)| (f.name().to_owned(), i as u32)).collect(),
			functions: elements.functions,
			globals_by_name: elements.globals.iter().enumerate().map(|(i, (g_name, _))| (g_name.to_owned(), i as u32)).collect(),
			globals: elements.globals.into_iter().map(|(_, g)| g).collect(),
		})
	}
}

impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
	fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
		self.base.execute_index(index, params)
	}

	fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
		self.base.execute_export(name, params)
	}

	fn export_entry<'b>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
		if let Some(index) = self.functions_by_name.get(name) {
			let composite_index = NATIVE_INDEX_FUNC_MIN + *index;
			match required_type {
				&ExportEntryType::Any => return Ok(Internal::Function(composite_index)),
				&ExportEntryType::Function(ref required_type) => {
					let actual_type = self.function_type(ItemIndex::Internal(composite_index))
						.expect(
							"by_name contains index; function_type succeeds for all functions from by_name; qed",
						);
					return if actual_type == *required_type {
						Ok(Internal::Function(composite_index))
					} else {
						Err(Error::Validation(format!(
							"Export function type {} mismatch. Expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
							index,
							required_type.params(),
							required_type.return_type(),
							actual_type.params(),
							actual_type.return_type()
						)))
					};
				}
				_ => (),
			}
		}
		if let Some(index) = self.globals_by_name.get(name) {
			let composite_index = NATIVE_INDEX_GLOBAL_MIN + *index;
			match required_type {
				&ExportEntryType::Any => {
					return Ok(Internal::Global(composite_index))
				}
				&ExportEntryType::Global(ref required_type) => {
					let actual_type = self.globals
						.get(*index as usize)
						.expect(
							"globals_by_name maps to indexes of globals; index read from globals_by_name; qed",
						)
						.variable_type();
					return if actual_type == *required_type {
						Ok(Internal::Global(composite_index))
					} else {
						Err(Error::Validation(format!(
							"Export global type {} mismatch. Expected type {:?} when got {:?}",
							index,
							required_type,
							actual_type
						)))
					};
				}
				_ => (),
			}
		}

		self.base.export_entry(name, required_type)
	}

	fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
		self.base.table(index)
	}

	fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
		self.base.memory(index)
	}

	fn global<'b>(&self, global_index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<Arc<VariableInstance>, Error> {
		let index = match global_index {
			ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
			ItemIndex::External(_) => unreachable!("trying to get global, exported by native env module"),
		};

		if index < NATIVE_INDEX_GLOBAL_MIN {
			return self.base.global(global_index, variable_type, externals);
		}

		self.globals
			.get((index - NATIVE_INDEX_GLOBAL_MIN) as usize)
			.cloned()
			.ok_or(Error::Native(format!("trying to get native global with index {}", index)))
	}

	fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error> {
		let index = match function_index {
			ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
			ItemIndex::External(_) => unreachable!("trying to call function, exported by native env module"),
		};

		if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
			return self.base.function_type(function_index);
		}

		Ok(FunctionSignature::User(self.functions
			.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
			.ok_or(Error::Native(format!("missing native env function with index {}", index)))?))
	}

	fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error> {
		self.function_type(ItemIndex::Internal(type_index))
	}

	fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
		self.base.function_reference(index, externals)
	}

	fn function_reference_indirect<'b>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
		self.base.function_reference_indirect(table_idx, type_idx, func_idx, externals)
	}

	fn function_body<'b>(&'b self, _internal_index: u32) -> Result<Option<InternalFunction<'b>>, Error> {
		Ok(None)
	}

	fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
		if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
			return self.base.call_internal_function(outer, index);
		}

		self.functions
			.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
			.ok_or(Error::Native(format!("trying to call native function with index {}", index)).into())
			.and_then(|f| self.executor.write()
				.as_mut()
				.expect("function existss; if function exists, executor must also exists [checked in constructor]; qed")
				.execute(&f.name(), outer))
	}
}

/// Create wrapper for a module with given native user functions .
///
/// # Examples
///
/// ```rust
/// use parity_wasm::interpreter::{CallerContext, Error, ExecutionParams, ExportEntryType,
///                                FunctionSignature, ItemIndex, ModuleInstance,
///                                ModuleInstanceInterface, ProgramInstance, RuntimeValue,
///                                UserDefinedElements, UserError, UserFunctionDescriptor,
///                                UserFunctionExecutor};
///
/// struct MyExecutor;
///
/// impl UserFunctionExecutor for MyExecutor {
///     fn execute(
///         &mut self,
///         name: &str,
///         context: CallerContext,
///     ) -> Result<Option<RuntimeValue>, Error> {
///         match name {
///             "add" => {
///                 // fn add(a: u32, b: u32) -> u32
///                 let b = context.value_stack.pop_as::<u32>()? as u32;
///                 let a = context.value_stack.pop_as::<u32>()? as u32;
///                 let sum = a + b;
///                 Ok(Some(RuntimeValue::I32(sum as i32)))
///             }
///             _ => Err(Error::Trap("not implemented".into()).into()),
///         }
///     }
/// }
/// ```
pub fn native_module<'a>(base: Arc<ModuleInstanceInterface>, user_elements: UserDefinedElements<'a>) -> Result<NativeModuleInstance, Error> {
	NativeModuleInstance::new(base, user_elements)
}

impl<'a> PartialEq for UserFunctionDescriptor {
	fn eq(&self, other: &Self) -> bool {
		self.params() == other.params()
			&& self.return_type() == other.return_type()
	}
}
<commit_msg>Fixes in error strings<commit_after>
use std::sync::Arc;
use std::collections::HashMap;
use std::borrow::Cow;
use parking_lot::RwLock;
use elements::{Internal, ValueType};
use interpreter::Error;
use interpreter::module::{ModuleInstanceInterface, ExecutionParams, ItemIndex,
	CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
use interpreter::memory::MemoryInstance;
use interpreter::table::TableInstance;
use interpreter::value::RuntimeValue;
use interpreter::variable::{VariableInstance, VariableType};

/// Min index of native function.
pub const NATIVE_INDEX_FUNC_MIN: u32 = 10001;
/// Min index of native global.
pub const NATIVE_INDEX_GLOBAL_MIN: u32 = 20001;

/// User functions executor.
pub trait UserFunctionExecutor {
	/// Execute function with given name.
	fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
}

/// User function descriptor
#[derive(Debug, Clone)]
pub enum UserFunctionDescriptor {
	/// Static function definition
	Static(&'static str, &'static [ValueType], Option<ValueType>),
	/// Dynamic heap function definition
	Heap(String, Vec<ValueType>, Option<ValueType>),
}

impl UserFunctionDescriptor {
	/// New function with statically known params
	pub fn statik(name: &'static str, params: &'static [ValueType], result: Option<ValueType>) -> Self {
		UserFunctionDescriptor::Static(name, params, result)
	}

	/// New function with statically unknown params
	pub fn heap(name: String, params: Vec<ValueType>, result: Option<ValueType>) -> Self {
		UserFunctionDescriptor::Heap(name, params, result)
	}

	/// Name of the function
	pub fn name(&self) -> &str {
		match self {
			&UserFunctionDescriptor::Static(name, _, _) => name,
			&UserFunctionDescriptor::Heap(ref name, _, _) => name,
		}
	}

	/// Arguments of the function
	pub fn params(&self) -> &[ValueType] {
		match self {
			&UserFunctionDescriptor::Static(_, params, _) => params,
			&UserFunctionDescriptor::Heap(_, ref params, _) => params,
		}
	}

	/// Return type of the function
	pub fn return_type(&self) -> Option<ValueType> {
		match self {
			&UserFunctionDescriptor::Static(_, _, result) => result,
			&UserFunctionDescriptor::Heap(_, _, result) => result,
		}
	}
}

/// Set of user-defined module elements.
pub struct UserDefinedElements<'a> {
	/// User globals list.
	pub globals: HashMap<String, Arc<VariableInstance>>,
	/// User functions list.
	pub functions: Cow<'static, [UserFunctionDescriptor]>,
	/// Functions executor.
	pub executor: Option<&'a mut UserFunctionExecutor>,
}

/// Native module instance.
pub struct NativeModuleInstance<'a> {
	/// Underlying module reference.
	base: Arc<ModuleInstanceInterface>,
	/// User function executor.
	executor: RwLock<Option<&'a mut UserFunctionExecutor>>,
	/// By-name functions index.
	functions_by_name: HashMap<String, u32>,
	/// User functions list.
	functions: Cow<'static, [UserFunctionDescriptor]>,
	/// By-name functions index.
	globals_by_name: HashMap<String, u32>,
	/// User globals list.
	globals: Vec<Arc<VariableInstance>>,
}

impl<'a> NativeModuleInstance<'a> {
	/// Create new native module
	pub fn new(base: Arc<ModuleInstanceInterface>, elements: UserDefinedElements<'a>) -> Result<Self, Error> {
		if !elements.functions.is_empty() && elements.executor.is_none() {
			return Err(Error::Function("trying to construct native module with functions, but without executor".into()));
		}

		Ok(NativeModuleInstance {
			base: base,
			executor: RwLock::new(elements.executor),
			functions_by_name: elements.functions.iter().enumerate().map(|(i, f)| (f.name().to_owned(), i as u32)).collect(),
			functions: elements.functions,
			globals_by_name: elements.globals.iter().enumerate().map(|(i, (g_name, _))| (g_name.to_owned(), i as u32)).collect(),
			globals: elements.globals.into_iter().map(|(_, g)| g).collect(),
		})
	}
}

impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
	fn execute_index(&self, index: u32, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
		self.base.execute_index(index, params)
	}

	fn execute_export(&self, name: &str, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
		self.base.execute_export(name, params)
	}

	fn export_entry<'b>(&self, name: &str, required_type: &ExportEntryType) -> Result<Internal, Error> {
		if let Some(index) = self.functions_by_name.get(name) {
			let composite_index = NATIVE_INDEX_FUNC_MIN + *index;
			match required_type {
				&ExportEntryType::Any => return Ok(Internal::Function(composite_index)),
				&ExportEntryType::Function(ref required_type) => {
					let actual_type = self.function_type(ItemIndex::Internal(composite_index))
						.expect(
							"by_name contains index; function_type succeeds for all functions from by_name; qed",
						);
					return if actual_type == *required_type {
						Ok(Internal::Function(composite_index))
					} else {
						Err(Error::Validation(format!(
							"Export function type {} mismatch. Expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}",
							index,
							required_type.params(),
							required_type.return_type(),
							actual_type.params(),
							actual_type.return_type()
						)))
					};
				}
				_ => (),
			}
		}
		if let Some(index) = self.globals_by_name.get(name) {
			let composite_index = NATIVE_INDEX_GLOBAL_MIN + *index;
			match required_type {
				&ExportEntryType::Any => {
					return Ok(Internal::Global(composite_index))
				}
				&ExportEntryType::Global(ref required_type) => {
					let actual_type = self.globals
						.get(*index as usize)
						.expect(
							"globals_by_name maps to indexes of globals; index read from globals_by_name; qed",
						)
						.variable_type();
					return if actual_type == *required_type {
						Ok(Internal::Global(composite_index))
					} else {
						Err(Error::Validation(format!(
							"Export global type {} mismatch. Expected type {:?} when got {:?}",
							index,
							required_type,
							actual_type
						)))
					};
				}
				_ => (),
			}
		}

		self.base.export_entry(name, required_type)
	}

	fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
		self.base.table(index)
	}

	fn memory(&self, index: ItemIndex) -> Result<Arc<MemoryInstance>, Error> {
		self.base.memory(index)
	}

	fn global<'b>(&self, global_index: ItemIndex, variable_type: Option<VariableType>, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<Arc<VariableInstance>, Error> {
		let index = match global_index {
			ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
			ItemIndex::External(_) => unreachable!("trying to get global, exported by native module"),
		};

		if index < NATIVE_INDEX_GLOBAL_MIN {
			return self.base.global(global_index, variable_type, externals);
		}

		self.globals
			.get((index - NATIVE_INDEX_GLOBAL_MIN) as usize)
			.cloned()
			.ok_or(Error::Native(format!("trying to get native global with index {}", index)))
	}

	fn function_type(&self, function_index: ItemIndex) -> Result<FunctionSignature, Error> {
		let index = match function_index {
			ItemIndex::IndexSpace(index) | ItemIndex::Internal(index) => index,
			ItemIndex::External(_) => unreachable!("trying to call function, exported by native module"),
		};

		if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
			return self.base.function_type(function_index);
		}

		Ok(FunctionSignature::User(self.functions
			.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
			.ok_or(Error::Native(format!("missing native function with index {}", index)))?))
	}

	fn function_type_by_index(&self, type_index: u32) -> Result<FunctionSignature, Error> {
		self.function_type(ItemIndex::Internal(type_index))
	}

	fn function_reference<'b>(&self, index: ItemIndex, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
		self.base.function_reference(index, externals)
	}

	fn function_reference_indirect<'b>(&self, table_idx: u32, type_idx: u32, func_idx: u32, externals: Option<&'b HashMap<String, Arc<ModuleInstanceInterface + 'b>>>) -> Result<InternalFunctionReference<'b>, Error> {
		self.base.function_reference_indirect(table_idx, type_idx, func_idx, externals)
	}

	fn function_body<'b>(&'b self, _internal_index: u32) -> Result<Option<InternalFunction<'b>>, Error> {
		Ok(None)
	}

	fn call_internal_function(&self, outer: CallerContext, index: u32) -> Result<Option<RuntimeValue>, Error> {
		if index < NATIVE_INDEX_FUNC_MIN || index >= NATIVE_INDEX_GLOBAL_MIN {
			return self.base.call_internal_function(outer, index);
		}

		self.functions
			.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
			.ok_or(Error::Native(format!("trying to call native function with index {}", index)).into())
			.and_then(|f| self.executor.write()
				.as_mut()
				.expect("function exists; if function exists, executor must also exists [checked in constructor]; qed")
				.execute(&f.name(), outer))
	}
}

/// Create wrapper for a module with given native user functions .
///
/// # Examples
///
/// ```rust
/// use parity_wasm::interpreter::{CallerContext, Error, ExecutionParams, ExportEntryType,
///                                FunctionSignature, ItemIndex, ModuleInstance,
///                                ModuleInstanceInterface, ProgramInstance, RuntimeValue,
///                                UserDefinedElements, UserError, UserFunctionDescriptor,
///                                UserFunctionExecutor};
///
/// struct MyExecutor;
///
/// impl UserFunctionExecutor for MyExecutor {
///     fn execute(
///         &mut self,
///         name: &str,
///         context: CallerContext,
///     ) -> Result<Option<RuntimeValue>, Error> {
///         match name {
///             "add" => {
///                 // fn add(a: u32, b: u32) -> u32
///                 let b = context.value_stack.pop_as::<u32>()? as u32;
///                 let a = context.value_stack.pop_as::<u32>()? as u32;
///                 let sum = a + b;
///                 Ok(Some(RuntimeValue::I32(sum as i32)))
///             }
///             _ => Err(Error::Trap("not implemented".into()).into()),
///         }
///     }
/// }
/// ```
pub fn native_module<'a>(base: Arc<ModuleInstanceInterface>, user_elements: UserDefinedElements<'a>) -> Result<NativeModuleInstance, Error> {
	NativeModuleInstance::new(base, user_elements)
}

impl<'a> PartialEq for UserFunctionDescriptor {
	fn eq(&self, other: &Self) -> bool {
		self.params() == other.params()
			&& self.return_type() == other.return_type()
	}
}
<|endoftext|>


<commit_before>#![warn(unused)]
extern crate cairo;
extern crate gio;
extern crate glib;
extern crate rsvg_internals;
extern crate url;

use std::io::Read;
use std::path::Path;

use gio::FileExt;
use glib::object::Cast;

use rsvg_internals::{Dpi, Handle, LoadFlags};
use url::Url;

pub use rsvg_internals::{LoadingError, RenderingError};

/// Full configuration for loading an [`SvgHandle`][SvgHandle]
///
/// This struct implements a builder pattern for configuring an
/// [`SvgHandle`][SvgHandle]'s options, and then loading the SVG data.
/// You can call the methods of `LoadOptions` in sequence to configure
/// how SVG data should be loaded, and finally use one of the loading
/// functions to load an [`SvgHandle`][SvgHandle].
///
/// # Example:
///
/// ```ignore
/// extern crate librsvg;
///
/// use librsvg::LoadOptions;
///
/// let svg_handle = LoadOptions::new()
///     .unlimited_size()
///     .read_path("example.svg")
///     .unwrap();
/// ```
///
/// [SvgHandle]: struct.SvgHandle.html
pub struct LoadOptions {
    unlimited_size: bool,
    keep_image_data: bool,
    base_url: Option<Url>,
}

impl LoadOptions {
    pub fn new() -> Self {
        LoadOptions {
            unlimited_size: false,
            keep_image_data: false,
            base_url: None,
        }
    }

    pub fn base_url(mut self, url: Option<&Url>) -> Self {
        self.base_url = url.map(|u| u.clone());
        self
    }

    pub fn unlimited_size(mut self, unlimited: bool) -> Self {
        self.unlimited_size = unlimited;
        self
    }

    pub fn keep_image_data(mut self, keep: bool) -> Self {
        self.keep_image_data = keep;
        self
    }

    fn load_flags(&self) -> LoadFlags {
        LoadFlags {
            unlimited_size: self.unlimited_size,
            keep_image_data: self.keep_image_data,
        }
    }

    pub fn read_path<P: AsRef<Path>>(self, path: P) -> Result<SvgHandle, LoadingError> {
        let file = gio::File::new_for_path(path);

        let stream = file.read(None)?;

        let mut handle = Handle::new_with_flags(self.load_flags());
        handle.construct_read_stream_sync(&stream.upcast(), Some(&file), None)?;

        Ok(SvgHandle(handle))
    }

    pub fn read(self, _r: &dyn Read, _base_url: Option<&Url>) -> Result<SvgHandle, LoadingError> {
        // This requires wrapping a Read with a GInputStream
        unimplemented!();
    }
}

pub struct SvgHandle(Handle);

pub struct CairoRenderer<'a> {
    handle: &'a SvgHandle,
    dpi: Dpi,
}

// Note that these are different than the C API's default, which is 90.
const DEFAULT_DPI_X: f64 = 96.0;
const DEFAULT_DPI_Y: f64 = 96.0;

impl SvgHandle {
    pub fn get_cairo_renderer(&self) -> CairoRenderer {
        CairoRenderer {
            handle: self,
            dpi: Dpi::new(DEFAULT_DPI_X, DEFAULT_DPI_Y),
        }
    }
}

impl<'a> CairoRenderer<'a> {
    pub fn set_dpi(&mut self, dpi_x: f64, dpi_y: f64) {
        assert!(dpi_x > 0.0);
        assert!(dpi_y > 0.0);

        self.dpi = Dpi::new(dpi_x, dpi_y);
    }

    pub fn get_dimensions(&self) -> Result<(i32, i32), RenderingError> {
        self.handle
            .0
            .get_dimensions()
            .map(|dimensions| (dimensions.width, dimensions.height))
    }

    pub fn render(&self, cr: &cairo::Context) -> Result<(), RenderingError> {
        self.handle.0.render_cairo_sub(cr, None)
    }
}
<commit_msg>LoadOptions: add a read_file() method<commit_after>#![warn(unused)]
extern crate cairo;
extern crate gio;
extern crate glib;
extern crate rsvg_internals;
extern crate url;

use std::io::Read;
use std::path::Path;

use gio::{Cancellable, FileExt};
use glib::object::Cast;

use rsvg_internals::{Dpi, Handle, LoadFlags};
use url::Url;

pub use rsvg_internals::{LoadingError, RenderingError};

/// Full configuration for loading an [`SvgHandle`][SvgHandle]
///
/// This struct implements a builder pattern for configuring an
/// [`SvgHandle`][SvgHandle]'s options, and then loading the SVG data.
/// You can call the methods of `LoadOptions` in sequence to configure
/// how SVG data should be loaded, and finally use one of the loading
/// functions to load an [`SvgHandle`][SvgHandle].
///
/// # Example:
///
/// ```ignore
/// extern crate librsvg;
///
/// use librsvg::LoadOptions;
///
/// let svg_handle = LoadOptions::new()
///     .unlimited_size()
///     .read_path("example.svg")
///     .unwrap();
/// ```
///
/// [SvgHandle]: struct.SvgHandle.html
pub struct LoadOptions {
    unlimited_size: bool,
    keep_image_data: bool,
    base_url: Option<Url>,
}

impl LoadOptions {
    pub fn new() -> Self {
        LoadOptions {
            unlimited_size: false,
            keep_image_data: false,
            base_url: None,
        }
    }

    pub fn base_url(mut self, url: Option<&Url>) -> Self {
        self.base_url = url.map(|u| u.clone());
        self
    }

    pub fn unlimited_size(mut self, unlimited: bool) -> Self {
        self.unlimited_size = unlimited;
        self
    }

    pub fn keep_image_data(mut self, keep: bool) -> Self {
        self.keep_image_data = keep;
        self
    }

    fn load_flags(&self) -> LoadFlags {
        LoadFlags {
            unlimited_size: self.unlimited_size,
            keep_image_data: self.keep_image_data,
        }
    }

    pub fn read_path<P: AsRef<Path>>(self, path: P) -> Result<SvgHandle, LoadingError> {
        let file = gio::File::new_for_path(path);
        self.read_file(&file, None)
    }

    pub fn read(self, _r: &dyn Read, _base_url: Option<&Url>) -> Result<SvgHandle, LoadingError> {
        // This requires wrapping a Read with a GInputStream
        unimplemented!();
    }

    pub fn read_file<'a, P: Into<Option<&'a Cancellable>>>(
        self,
        file: &gio::File,
        cancellable: P,
    ) -> Result<SvgHandle, LoadingError> {
        let stream = file.read(None)?;

        let mut handle = Handle::new_with_flags(self.load_flags());
        handle.construct_read_stream_sync(&stream.upcast(), Some(&file), cancellable.into())?;

        Ok(SvgHandle(handle))
    }
}

pub struct SvgHandle(Handle);

pub struct CairoRenderer<'a> {
    handle: &'a SvgHandle,
    dpi: Dpi,
}

// Note that these are different than the C API's default, which is 90.
const DEFAULT_DPI_X: f64 = 96.0;
const DEFAULT_DPI_Y: f64 = 96.0;

impl SvgHandle {
    pub fn get_cairo_renderer(&self) -> CairoRenderer {
        CairoRenderer {
            handle: self,
            dpi: Dpi::new(DEFAULT_DPI_X, DEFAULT_DPI_Y),
        }
    }
}

impl<'a> CairoRenderer<'a> {
    pub fn set_dpi(&mut self, dpi_x: f64, dpi_y: f64) {
        assert!(dpi_x > 0.0);
        assert!(dpi_y > 0.0);

        self.dpi = Dpi::new(dpi_x, dpi_y);
    }

    pub fn get_dimensions(&self) -> Result<(i32, i32), RenderingError> {
        self.handle
            .0
            .get_dimensions()
            .map(|dimensions| (dimensions.width, dimensions.height))
    }

    pub fn render(&self, cr: &cairo::Context) -> Result<(), RenderingError> {
        self.handle.0.render_cairo_sub(cr, None)
    }
}
<|endoftext|>


<commit_before>use std::result::Result;

use serde_json::*;

use super::script::*;
use super::bound_script::*;
use super::bind_expression::*;
use super::binding_environment::*;
use super::script_interpreter::*;

///
/// Creates an execution error relating to an script statement
///
fn generate_statement_error(error: ScriptEvaluationError, script: &Script) -> Value {
    json![{
        "error":            error,
        "failed-statement": script
    }]
}

///
/// Binds a sequnce in a script
///
fn bind_sequence(sequence: &Vec<Script>, binding_environment: &mut BindingEnvironment) -> Result<Vec<BoundScript>, Value> {
    let mut result = vec![];

    for statement in sequence {
        result.push(bind_statement(statement, binding_environment)?);
    }

    Ok(result)
}

///
/// Binds a new variable name
///
fn bind_variable_name(name: &ScriptToken, script: &Script, binding_environment: &mut BindingEnvironment) -> Result<u32, Value> {
    let binding = binding_environment.allocate_variable(&name.matched);

    match binding {
        Ok(value)                       => Ok(value),
        Err(BindingError::AlreadyInUse) => Err(generate_statement_error(ScriptEvaluationError::VariableNameAlreadyInUse, script))
    }
}

///
/// Binds a statement to an environment
///
pub fn bind_statement(script: &Script, binding_environment: &mut BindingEnvironment) -> Result<BoundScript, Value> {
    use self::BoundScript::*;

    match *script {
        Script::RunCommand(ref expr)    => Ok(RunCommand(bind_expression(expr, binding_environment)?)),
        Script::Sequence(ref parts)     => Ok(Sequence(bind_sequence(parts, binding_environment)?)),
        Script::Var(ref name, ref expr) => Ok(Var(bind_variable_name(name, script, binding_environment)?, bind_expression(expr, binding_environment)?, name.clone())),

        _ => unimplemented!()
    }
}

#[cfg(test)]
mod test {
    use gossyp_base::basic::*;
    use super::*;

    #[test]
    fn can_bind_simple_statement() {
        let string_statement    = Script::RunCommand(Expression::string("\"Foo\""));
        let empty_environment   = EmptyEnvironment::new();
        let mut env             = BindingEnvironment::new(&empty_environment);

        let bound               = bind_statement(&string_statement, &mut *env);

        assert!(match bound { Ok(BoundScript::RunCommand(BoundExpression::Value(Value::String(s), _))) => s == "Foo", _ => false });
    }

    #[test]
    fn can_bind_simple_sequence() {
        let sequence_statement  = Script::Sequence(vec![Script::RunCommand(Expression::string("\"Foo\""))]);
        let empty_environment   = EmptyEnvironment::new();
        let mut env             = BindingEnvironment::new(&empty_environment);

        let bound               = bind_statement(&sequence_statement, &mut *env);

        assert!(match bound { Ok(BoundScript::Sequence(_)) => true, _ => false });
    }

    #[test]
    fn can_bind_var_expression() {
        let var_statement       = Script::Var(ScriptToken::identifier("test"), Expression::number("42"));
        let empty_environment   = EmptyEnvironment::new();
        let mut env             = BindingEnvironment::new(&empty_environment);

        let bound               = bind_statement(&var_statement, &mut *env);

        assert!(match bound { Ok(BoundScript::Var(0, BoundExpression::Value(_, _), _)) => true, _ => false });
    }
}
<commit_msg>Add variable allocation to the start of a bound script<commit_after>use std::result::Result;

use serde_json::*;

use super::script::*;
use super::bound_script::*;
use super::bind_expression::*;
use super::binding_environment::*;
use super::script_interpreter::*;

///
/// Creates an execution error relating to an script statement
///
fn generate_statement_error(error: ScriptEvaluationError, script: &Script) -> Value {
    json![{
        "error":            error,
        "failed-statement": script
    }]
}

///
/// Binds a sequnce in a script
///
fn bind_sequence(sequence: &Vec<Script>, binding_environment: &mut BindingEnvironment) -> Result<Vec<BoundScript>, Value> {
    let mut result = vec![];

    for statement in sequence {
        result.push(bind_statement_without_allocation(statement, binding_environment)?);
    }

    Ok(result)
}

///
/// Binds a new variable name
///
fn bind_variable_name(name: &ScriptToken, script: &Script, binding_environment: &mut BindingEnvironment) -> Result<u32, Value> {
    let binding = binding_environment.allocate_variable(&name.matched);

    match binding {
        Ok(value)                       => Ok(value),
        Err(BindingError::AlreadyInUse) => Err(generate_statement_error(ScriptEvaluationError::VariableNameAlreadyInUse, script))
    }
}

///
/// Binds a statement to an environment (does not allocate space for variables)
///
fn bind_statement_without_allocation(script: &Script, binding_environment: &mut BindingEnvironment) -> Result<BoundScript, Value> {
    use self::BoundScript::*;

    match *script {
        Script::RunCommand(ref expr)    => Ok(RunCommand(bind_expression(expr, binding_environment)?)),
        Script::Sequence(ref parts)     => Ok(Sequence(bind_sequence(parts, binding_environment)?)),
        Script::Var(ref name, ref expr) => Ok(Var(bind_variable_name(name, script, binding_environment)?, bind_expression(expr, binding_environment)?, name.clone())),

        _ => unimplemented!()
    }
}

///
/// Binds a statement to an environment
///
pub fn bind_statement(script: &Script, binding_environment: &mut BindingEnvironment) -> Result<BoundScript, Value> {
    use self::BoundScript::*;

    // We store the initial number of variables so we can see if any allocation is required
    let initial_variable_count  = binding_environment.get_number_of_variables();

    // Then bind the statements with no further allocation
    let bound_script            = bind_statement_without_allocation(script, binding_environment)?;

    // Transform to an allocation script if required
    let final_variable_count = binding_environment.get_number_of_variables();
    if initial_variable_count < final_variable_count {
        Ok(AllocateVariables(final_variable_count, Box::new(bound_script)))
    } else {
        Ok(bound_script)
    }
}

#[cfg(test)]
mod test {
    use gossyp_base::basic::*;
    use super::*;

    #[test]
    fn can_bind_simple_statement() {
        let string_statement    = Script::RunCommand(Expression::string("\"Foo\""));
        let empty_environment   = EmptyEnvironment::new();
        let mut env             = BindingEnvironment::new(&empty_environment);

        let bound               = bind_statement(&string_statement, &mut *env);

        assert!(match bound { Ok(BoundScript::RunCommand(BoundExpression::Value(Value::String(s), _))) => s == "Foo", _ => false });
    }

    #[test]
    fn can_bind_simple_sequence() {
        let sequence_statement  = Script::Sequence(vec![Script::RunCommand(Expression::string("\"Foo\""))]);
        let empty_environment   = EmptyEnvironment::new();
        let mut env             = BindingEnvironment::new(&empty_environment);

        let bound               = bind_statement(&sequence_statement, &mut *env);

        assert!(match bound { Ok(BoundScript::Sequence(_)) => true, _ => false });
    }

    #[test]
    fn can_bind_var_expression() {
        let var_statement       = Script::Var(ScriptToken::identifier("test"), Expression::number("42"));
        let empty_environment   = EmptyEnvironment::new();
        let mut env             = BindingEnvironment::new(&empty_environment);

        let bound               = bind_statement(&var_statement, &mut *env);

        assert!(match bound { Ok(BoundScript::AllocateVariables(1, _)) => true, _ => false });

        if let Ok(BoundScript::AllocateVariables(_, boundvar)) = bound {
            assert!(match *boundvar { BoundScript::Var(0, BoundExpression::Value(_, _), _) => true, _ => false });
        } else {
            assert!(false);
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use measurement::Measurement;

pub fn get_equable_ranges(sensors: u64, threads: u64) -> Vec<(u64, u64)>{
	if threads > sensors{
		panic!("threads {} must be <= sensors {}", threads, sensors);
	}
	if sensors % threads != 0{
		panic!("sensors {} must divide evenly into threads {}", sensors, threads);
	}
	let mut result = Vec::<(u64, u64)>::new();
	let range_size = sensors / threads;
	let mut begin = 0;
	for i in 1..threads{
		result.push((begin, range_size * i - 1));
		begin = range_size * i;
	}
	result.push((begin, sensors-1));
	return result;
}
pub fn get_slice_index_which_is_greater_or_equal<T: Ord + Debug>(values: &[T], s: T) -> Option<usize>{
	let len = values.len();
	if len == 0 { return None; }
	if len == 1{
		if values[0] == s{ return Some(0); }
		else { return None; }
	}
	let mut low = 0;
	let mut high = len - 1;
	let mut mid = 0;
	let mut prev_mid = 0;
	loop{
		mid = low + (high - low) / 2;
		// let ref v = values[mid];
		// println!("[{}, {}]. mid = {}. v = {:?}", low, high, mid, v);
		if values[mid] < s { low = mid; }
		else { high = mid; }
		if prev_mid == mid { break; }
		prev_mid = mid;
	}
	if mid < len - 1{
		if values[mid] < s { mid = mid + 1; }
	}
	if mid == len - 1 && values[mid] < s { return None;	}
	else { return Some(mid); }
}
pub fn get_slice_index_which_is_greater_or_equal2(values: &[Measurement], s: u64) -> Option<usize>{
	let len = values.len();
	if len == 0 { return None; }
	if len == 1{
		if values[0].time == s{ return Some(0); }
		else { return None; }
	}
	let mut low = 0;
	let mut high = len - 1;
	let mut mid = 0;
	let mut prev_mid = 0;
	loop{
		mid = low + (high - low) / 2;
		// let ref v = values[mid];
		// println!("[{}, {}]. mid = {}. v = {:?}", low, high, mid, v);
		if values[mid].time < s{ low = mid; }
		else { high = mid; }
		if prev_mid == mid { break; }
		prev_mid = mid;
	}
	if mid < len - 1{
		if values[mid].time < s { mid = mid + 1;}
	}
	if mid == len - 1 && values[mid].time < s { return None;}
	else { return Some(mid); }
}
#[cfg(test)]
mod tests{
	use super::*;

	#[test]
	fn get_equable_ranges_odd_sensors_odd_threads(){
		let ranges = get_equable_ranges(33, 11);
		assert_eq!(11, ranges.len());
		assert_eq!((0, 2), ranges[0]);
		assert_eq!((3, 5), ranges[1]);
		assert_eq!((6, 8), ranges[2]);
		assert_eq!((9, 11), ranges[3]);
		assert_eq!((12, 14), ranges[4]);
		assert_eq!((15, 17), ranges[5]);
		assert_eq!((18, 20), ranges[6]);
		assert_eq!((21, 23), ranges[7]);
		assert_eq!((24, 26), ranges[8]);
		assert_eq!((27, 29), ranges[9]);
		assert_eq!((30, 32), ranges[10]);
	}
	#[test]
	fn get_equable_ranges_even_sensors_even_threads(){
		let ranges = get_equable_ranges(10, 2);
		assert_eq!(2, ranges.len());
		assert_eq!((0, 4), ranges[0]);
		assert_eq!((5, 9), ranges[1]);

		let ranges = get_equable_ranges(8, 4);
		assert_eq!(4, ranges.len());
		assert_eq!((0, 1), ranges[0]);
		assert_eq!((2, 3), ranges[1]);
		assert_eq!((4, 5), ranges[2]);
		assert_eq!((6, 7), ranges[3]);
	}
	#[test]
	fn get_righter_less_or_equal_empty_slice(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[], 0));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_1_without_searching_element(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1], 0));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_1_with_searching_element(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1], 1));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_2_without_searching_element(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2], 3));
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2], 4));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_2_with_searching_element(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 2], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2], 2));
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 2], 0));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_2_with_searching_element_many_matches(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 1], 1));
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[2, 2], 2));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_3_without_searching_element(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2, 3], 4));
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 1, 1], 2));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_3_with_searching_element(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 2, 3], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2, 3], 2));
		assert_eq!(Some(2), get_slice_index_which_is_greater_or_equal(&[1, 2, 3], 3));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_3_with_searching_element_many_matches(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 1, 1], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2, 2], 2));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_4_without_searching_element(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4], 5));
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[4, 4, 4, 4], 5));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_4_with_searching_element(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4], 2));
		assert_eq!(Some(2), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4], 3));
		assert_eq!(Some(3), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4], 4));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_4_with_searching_element_many_matches(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 1, 1, 1], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2, 2, 4], 2));
		assert_eq!(Some(2), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 3], 3));
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[4, 4, 4, 4], 3));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_searching_element_many_matches(){
		assert_eq!(Some(2), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 3, 3, 3, 3, 3, 3], 3));
		assert_eq!(Some(7), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 8], 8));
		assert_eq!(Some(3), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 4, 6, 7, 8, 8], 4));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_searching_element(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 2));
		assert_eq!(Some(2), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 3));
		assert_eq!(Some(3), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 4));
		assert_eq!(Some(4), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 5));
		assert_eq!(Some(5), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 6));
		assert_eq!(Some(6), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 7));
		assert_eq!(Some(7), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 8));
		assert_eq!(Some(8), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 9));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_test(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 10));
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 11));
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 12));
		assert_eq!(Some(8), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 7, 8, 9, 11], 10));
		assert_eq!(Some(5), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 7, 8, 9, 11], 6));
		assert_eq!(Some(8), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 4, 4, 4, 4, 6], 5));
		assert_eq!(Some(3), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 4, 4, 4, 4, 6], 4));
	}
}<commit_msg>Fixed bug in get_slice_index_which_is_greater_or_equal. Now when collection's length is 1 and searching element is less or equal to the collection element it will return Some(0). Example: ([1], 0) => Some(0). But ([0], 1) => None<commit_after>use std::fmt::Debug;
use measurement::Measurement;

pub fn get_equable_ranges(sensors: u64, threads: u64) -> Vec<(u64, u64)>{
	if threads > sensors{
		panic!("threads {} must be <= sensors {}", threads, sensors);
	}
	if sensors % threads != 0{
		panic!("sensors {} must divide evenly into threads {}", sensors, threads);
	}
	let mut result = Vec::<(u64, u64)>::new();
	let range_size = sensors / threads;
	let mut begin = 0;
	for i in 1..threads{
		result.push((begin, range_size * i - 1));
		begin = range_size * i;
	}
	result.push((begin, sensors-1));
	return result;
}
pub fn get_slice_index_which_is_greater_or_equal<T: Ord + Debug>(values: &[T], s: T) -> Option<usize>{
	let len = values.len();
	if len == 0 { return None; }
	if len == 1{
		if values[0] >= s{ return Some(0); }
		else { return None; }
	}
	let mut low = 0;
	let mut high = len - 1;
	let mut mid = 0;
	let mut prev_mid = 0;
	loop{
		mid = low + (high - low) / 2;
		// let ref v = values[mid];
		// println!("[{}, {}]. mid = {}. v = {:?}", low, high, mid, v);
		if values[mid] < s { low = mid; }
		else { high = mid; }
		if prev_mid == mid { break; }
		prev_mid = mid;
	}
	if mid < len - 1{
		if values[mid] < s { mid = mid + 1; }
	}
	if mid == len - 1 && values[mid] < s { return None;	}
	else { return Some(mid); }
}
pub fn get_slice_index_which_is_greater_or_equal2(values: &[Measurement], s: u64) -> Option<usize>{
	let len = values.len();
	if len == 0 { return None; }
	if len == 1{
		if values[0].time >= s{ return Some(0); }
		else { return None; }
	}
	let mut low = 0;
	let mut high = len - 1;
	let mut mid = 0;
	let mut prev_mid = 0;
	loop{
		mid = low + (high - low) / 2;
		// let ref v = values[mid];
		// println!("[{}, {}]. mid = {}. v = {:?}", low, high, mid, v);
		if values[mid].time < s{ low = mid; }
		else { high = mid; }
		if prev_mid == mid { break; }
		prev_mid = mid;
	}
	if mid < len - 1{
		if values[mid].time < s { mid = mid + 1;}
	}
	if mid == len - 1 && values[mid].time < s { return None;}
	else { return Some(mid); }
}
#[cfg(test)]
mod tests{
	use super::*;

	#[test]
	fn get_equable_ranges_odd_sensors_odd_threads(){
		let ranges = get_equable_ranges(33, 11);
		assert_eq!(11, ranges.len());
		assert_eq!((0, 2), ranges[0]);
		assert_eq!((3, 5), ranges[1]);
		assert_eq!((6, 8), ranges[2]);
		assert_eq!((9, 11), ranges[3]);
		assert_eq!((12, 14), ranges[4]);
		assert_eq!((15, 17), ranges[5]);
		assert_eq!((18, 20), ranges[6]);
		assert_eq!((21, 23), ranges[7]);
		assert_eq!((24, 26), ranges[8]);
		assert_eq!((27, 29), ranges[9]);
		assert_eq!((30, 32), ranges[10]);
	}
	#[test]
	fn get_equable_ranges_even_sensors_even_threads(){
		let ranges = get_equable_ranges(10, 2);
		assert_eq!(2, ranges.len());
		assert_eq!((0, 4), ranges[0]);
		assert_eq!((5, 9), ranges[1]);

		let ranges = get_equable_ranges(8, 4);
		assert_eq!(4, ranges.len());
		assert_eq!((0, 1), ranges[0]);
		assert_eq!((2, 3), ranges[1]);
		assert_eq!((4, 5), ranges[2]);
		assert_eq!((6, 7), ranges[3]);
	}
	#[test]
	fn get_righter_less_or_equal_empty_slice(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[], 0));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_1_without_searching_element(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1], 2));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_1_with_searching_element(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1], 1));
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1], 0));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_2_without_searching_element(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2], 3));
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2], 4));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_2_with_searching_element(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 2], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2], 2));
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 2], 0));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_2_with_searching_element_many_matches(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 1], 1));
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[2, 2], 2));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_3_without_searching_element(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2, 3], 4));
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 1, 1], 2));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_3_with_searching_element(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 2, 3], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2, 3], 2));
		assert_eq!(Some(2), get_slice_index_which_is_greater_or_equal(&[1, 2, 3], 3));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_3_with_searching_element_many_matches(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 1, 1], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2, 2], 2));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_4_without_searching_element(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4], 5));
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[4, 4, 4, 4], 5));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_4_with_searching_element(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4], 2));
		assert_eq!(Some(2), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4], 3));
		assert_eq!(Some(3), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4], 4));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_len_4_with_searching_element_many_matches(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 1, 1, 1], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2, 2, 4], 2));
		assert_eq!(Some(2), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 3], 3));
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[4, 4, 4, 4], 3));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_searching_element_many_matches(){
		assert_eq!(Some(2), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 3, 3, 3, 3, 3, 3], 3));
		assert_eq!(Some(7), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 8], 8));
		assert_eq!(Some(3), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 4, 6, 7, 8, 8], 4));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_with_searching_element(){
		assert_eq!(Some(0), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 1));
		assert_eq!(Some(1), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 2));
		assert_eq!(Some(2), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 3));
		assert_eq!(Some(3), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 4));
		assert_eq!(Some(4), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 5));
		assert_eq!(Some(5), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 6));
		assert_eq!(Some(6), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 7));
		assert_eq!(Some(7), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 8));
		assert_eq!(Some(8), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 9));
	}
	#[test]
	fn get_slice_index_which_is_greater_or_equal_test(){
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 10));
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 11));
		assert_eq!(None, get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 6, 7, 8, 9], 12));
		assert_eq!(Some(8), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 7, 8, 9, 11], 10));
		assert_eq!(Some(5), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 5, 7, 8, 9, 11], 6));
		assert_eq!(Some(8), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 4, 4, 4, 4, 6], 5));
		assert_eq!(Some(3), get_slice_index_which_is_greater_or_equal(&[1, 2, 3, 4, 4, 4, 4, 4, 6], 4));
	}
}<|endoftext|>