<commit_before>use std::collections::HashMap;
use std::convert::TryInto;
use std::env;

use crate::error::*;
use crate::source::Source;
use crate::value::{Value, ValueKind};

#[derive(Clone, Debug)]
pub struct Environment {
    /// Optional prefix that will limit access to the environment to only keys that
    /// begin with the defined prefix.
    ///
    /// A prefix with a separator of `_` is tested to be present on each key before its considered
    /// to be part of the source environment.
    ///
    /// For example, the key `CONFIG_DEBUG` would become `DEBUG` with a prefix of `config`.
    prefix: Option<String>,

    /// Optional character sequence that separates each key segment in an environment key pattern.
    /// Consider a nested configuration such as `redis.password`, a separator of `_` would allow
    /// an environment key of `REDIS_PASSWORD` to match.
    separator: Option<String>,

    /// Ignore empty env values (treat as unset).
    ignore_empty: bool,

    /// Parses booleans, integers and floats if they're detected (can be safely parsed).
    try_parsing: bool,
}

impl Environment {
    pub fn new() -> Self {
        Environment::default()
    }

    pub fn with_prefix(s: &str) -> Self {
        Environment {
            prefix: Some(s.into()),
            ..Environment::default()
        }
    }

    pub fn prefix(mut self, s: &str) -> Self {
        self.prefix = Some(s.into());
        self
    }

    pub fn separator(mut self, s: &str) -> Self {
        self.separator = Some(s.into());
        self
    }

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

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

impl Default for Environment {
    fn default() -> Environment {
        Environment {
            prefix: None,
            separator: None,
            ignore_empty: false,
            try_parsing: false,
        }
    }
}

impl Source for Environment {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<HashMap<String, Value>> {
        let mut m = HashMap::new();
        let uri: String = "the environment".into();

        let separator = match self.separator {
            Some(ref separator) => separator,
            _ => "",
        };

        let group_separator = match self.separator {
            Some(ref separator) => separator,
            _ => "_",
        };

        // Define a prefix pattern to test and exclude from keys
        let prefix_pattern = self
            .prefix
            .as_ref()
            .map(|prefix| format!("{}{}", prefix.clone(), group_separator));

        for (key, value) in env::vars() {
            // Treat empty environment variables as unset
            if self.ignore_empty && value.is_empty() {
                continue;
            }

            let mut key = key.to_string();

            // Check for prefix
            if let Some(ref prefix_pattern) = prefix_pattern {
                if key
                    .to_lowercase()
                    .starts_with(&prefix_pattern.to_lowercase())
                {
                    // Remove this prefix from the key
                    key = key[prefix_pattern.len()..].to_string();
                } else {
                    // Skip this key
                    continue;
                }
            }

            // If separator is given replace with `.`
            if !separator.is_empty() {
                key = key.replace(separator, ".");
            }

            let value = if self.try_parsing {
                let string_value = Value::new(Some(&uri), ValueKind::String(value.clone()));

                if let Ok(parsed) = string_value.clone().into_int() {
                    ValueKind::Integer(parsed)
                } else if let Ok(parsed) = string_value.clone().into_float() {
                    ValueKind::Float(parsed)
                } else if let Ok(parsed) = string_value.clone().into_bool() {
                    ValueKind::Boolean(parsed)
                } else {
                    ValueKind::String(value)
                }
            } else {
                ValueKind::String(value)
            };

            m.insert(key.to_lowercase(), Value::new(Some(&uri), value));
        }

        Ok(m)
    }
}
<commit_msg>If env value is true or false parse as bool<commit_after>use std::collections::HashMap;
use std::convert::TryInto;
use std::env;

use crate::error::*;
use crate::source::Source;
use crate::value::{Value, ValueKind};

#[derive(Clone, Debug)]
pub struct Environment {
    /// Optional prefix that will limit access to the environment to only keys that
    /// begin with the defined prefix.
    ///
    /// A prefix with a separator of `_` is tested to be present on each key before its considered
    /// to be part of the source environment.
    ///
    /// For example, the key `CONFIG_DEBUG` would become `DEBUG` with a prefix of `config`.
    prefix: Option<String>,

    /// Optional character sequence that separates each key segment in an environment key pattern.
    /// Consider a nested configuration such as `redis.password`, a separator of `_` would allow
    /// an environment key of `REDIS_PASSWORD` to match.
    separator: Option<String>,

    /// Ignore empty env values (treat as unset).
    ignore_empty: bool,

    /// Parses booleans, integers and floats if they're detected (can be safely parsed).
    try_parsing: bool,
}

impl Environment {
    pub fn new() -> Self {
        Environment::default()
    }

    pub fn with_prefix(s: &str) -> Self {
        Environment {
            prefix: Some(s.into()),
            ..Environment::default()
        }
    }

    pub fn prefix(mut self, s: &str) -> Self {
        self.prefix = Some(s.into());
        self
    }

    pub fn separator(mut self, s: &str) -> Self {
        self.separator = Some(s.into());
        self
    }

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

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

impl Default for Environment {
    fn default() -> Environment {
        Environment {
            prefix: None,
            separator: None,
            ignore_empty: false,
            try_parsing: false,
        }
    }
}

impl Source for Environment {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<HashMap<String, Value>> {
        let mut m = HashMap::new();
        let uri: String = "the environment".into();

        let separator = match self.separator {
            Some(ref separator) => separator,
            _ => "",
        };

        let group_separator = match self.separator {
            Some(ref separator) => separator,
            _ => "_",
        };

        // Define a prefix pattern to test and exclude from keys
        let prefix_pattern = self
            .prefix
            .as_ref()
            .map(|prefix| format!("{}{}", prefix.clone(), group_separator));

        for (key, value) in env::vars() {
            // Treat empty environment variables as unset
            if self.ignore_empty && value.is_empty() {
                continue;
            }

            let mut key = key.to_string();

            // Check for prefix
            if let Some(ref prefix_pattern) = prefix_pattern {
                if key
                    .to_lowercase()
                    .starts_with(&prefix_pattern.to_lowercase())
                {
                    // Remove this prefix from the key
                    key = key[prefix_pattern.len()..].to_string();
                } else {
                    // Skip this key
                    continue;
                }
            }

            // If separator is given replace with `.`
            if !separator.is_empty() {
                key = key.replace(separator, ".");
            }

            let value = if self.try_parsing {
                let string_value = Value::new(Some(&uri), ValueKind::String(value.clone()));

                // if the value is "true" or "false" it should be parsed as a bool
                if let (true, Ok(parsed)) = (
                    value.to_lowercase() == "true" || value.to_lowercase() == "false",
                    string_value.clone().into_bool(),
                ) {
                    ValueKind::Boolean(parsed)
                } else if let Ok(parsed) = string_value.clone().into_int() {
                    ValueKind::Integer(parsed)
                } else if let Ok(parsed) = string_value.clone().into_float() {
                    ValueKind::Float(parsed)
                } else if let Ok(parsed) = string_value.clone().into_bool() {
                    ValueKind::Boolean(parsed)
                } else {
                    ValueKind::String(value)
                }
            } else {
                ValueKind::String(value)
            };

            m.insert(key.to_lowercase(), Value::new(Some(&uri), value));
        }

        Ok(m)
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(docopt_macros)]
#![plugin(regex_macros)]

extern crate rustc_serialize;
extern crate docopt;
extern crate glob;
extern crate littletest;
extern crate regex;

mod tests;

docopt!(pub Args derive Debug, "
Usage: sassaurs_spec [options] [<spec-dir>]
       sassaurs_spec --help

Options:
  -c COMMAND, --command COMMAND
                     Sets a specific binary to run
                     [default: sassc]
  -s, --skip         Skip tests that fail to exit successfully.
  -t, --tap          Output TAP compatible report.
  -v, --verbose      Run verbosely.
  --limit NUMBER     Limit the number of tests run to this positive integer.
  --filter PATTERN   Run tests that match the pattern you provide
  --ignore-todo      Skip any folder named 'todo'.
  --silent           Don't show any logs.
  --nuke             Write a new expected_output for every test.
  --unexpected-pass  When running the todo tests, flag as an error when a test
                     passes which is marked as todo.
",
flag_limit: Option<usize>,
flag_filter: Option<String>,
arg_spec_dir: Option<String>);

fn main() {
    let args: Args = Args::docopt()
        .decode()
        .unwrap_or_else(|e| e.exit());

    let directory = match args.arg_spec_dir {
        None => "sass-spec/spec",
        Some(ref dir) => dir.as_ref()
    };

    if !args.flag_silent && !args.flag_tap {
        println!("Recursively searching under directory '{}' \
            for test files to test '{}' with.",
            directory,
            args.flag_command);
        println!("{}", version(&args.flag_command));
    }

    let path = std::path::Path::new(directory);
    let opts = tests::RunOptions {
        ignore_todo: args.flag_ignore_todo,
        command: args.flag_command
    };

    let runnables = tests::load(path, &opts);

    let runner = littletest::TestRunner::new(littletest::TestOptions {
        parallelism: Some(4)
    });
    runner.run(&runnables);
}

fn version(command: &str) -> String {
    let executable = command.split(' ').next().unwrap();
    match exec(executable, &["-v"]) {
        Some(output) => output,
        None => match exec(executable, &["-V"]) {
            Some(output) => output,
            None => panic!("Could not get version of {}", executable)
        }
    }
}

fn exec(command: &str, args: &[&str]) -> Option<String> {
    use std::process::Command;
    let mut wrapper = Command::new(command);
    match wrapper.args(args).output() {
        Ok(output) => match output.status.success() {
            true => Some(String::from_utf8(output.stdout).unwrap().to_string()),
            _ => None
        },
        Err(e) => panic!("failed to execute process: '{:?}' error: '{}'", wrapper, e)
    }
}
<commit_msg>Limit the number of tests run.<commit_after>#![feature(plugin)]
#![plugin(docopt_macros)]
#![plugin(regex_macros)]

extern crate rustc_serialize;
extern crate docopt;
extern crate glob;
extern crate littletest;
extern crate regex;

mod tests;

docopt!(pub Args derive Debug, "
Usage: sassaurs_spec [options] [<spec-dir>]
       sassaurs_spec --help

Options:
  -c COMMAND, --command COMMAND
                     Sets a specific binary to run
                     [default: sassc]
  -s, --skip         Skip tests that fail to exit successfully.
  -t, --tap          Output TAP compatible report.
  -v, --verbose      Run verbosely.
  --limit NUMBER     Limit the number of tests run to this positive integer.
  --filter PATTERN   Run tests that match the pattern you provide
  --ignore-todo      Skip any folder named 'todo'.
  --silent           Don't show any logs.
  --nuke             Write a new expected_output for every test.
  --unexpected-pass  When running the todo tests, flag as an error when a test
                     passes which is marked as todo.
",
flag_limit: Option<usize>,
flag_filter: Option<String>,
arg_spec_dir: Option<String>);

fn main() {
    let args: Args = Args::docopt()
        .decode()
        .unwrap_or_else(|e| e.exit());

    let directory = match args.arg_spec_dir {
        None => "sass-spec/spec",
        Some(ref dir) => dir.as_ref()
    };

    if !args.flag_silent && !args.flag_tap {
        println!("Recursively searching under directory '{}' \
            for test files to test '{}' with.",
            directory,
            args.flag_command);
        println!("{}", version(&args.flag_command));
    }

    let path = std::path::Path::new(directory);
    let opts = tests::RunOptions {
        ignore_todo: args.flag_ignore_todo,
        command: args.flag_command
    };

    let runnables = tests::load(path, &opts);
    let limited = match args.flag_limit {
        Some(count) => runnables.into_iter().take(count).collect(),
        _ => runnables
    };

    let runner = littletest::TestRunner::new(littletest::TestOptions {
        parallelism: Some(4)
    });
    runner.run(&limited);
}

fn version(command: &str) -> String {
    let executable = command.split(' ').next().unwrap();
    match exec(executable, &["-v"]) {
        Some(output) => output,
        None => match exec(executable, &["-V"]) {
            Some(output) => output,
            None => panic!("Could not get version of {}", executable)
        }
    }
}

fn exec(command: &str, args: &[&str]) -> Option<String> {
    use std::process::Command;
    let mut wrapper = Command::new(command);
    match wrapper.args(args).output() {
        Ok(output) => match output.status.success() {
            true => Some(String::from_utf8(output.stdout).unwrap().to_string()),
            _ => None
        },
        Err(e) => panic!("failed to execute process: '{:?}' error: '{}'", wrapper, e)
    }
}
<|endoftext|>


<commit_before>use libc;
use std::mem::transmute;
use std::raw;
use fn_box::FnBox;

use stack::Stack;
use arch::{mod, Registers};

pub struct Context {
  regs: Registers,
  stack: Stack
}

pub type BoxedFn<Args, Result> = Box<FnBox<Args, Result> + Send + 'static>;
pub type StartFn<T, Args, Result> = fn(data: *mut T, f: BoxedFn<Args, Result>) -> !;

impl Context {
  pub fn new<T, Args, Result>(init: StartFn<T, Args, Result>, data: *mut T,
                              f: BoxedFn<Args, Result>) -> Context {
    let mut stack = Stack::new(4 << 20);
    let f: raw::TraitObject = unsafe { transmute(f) };

    Context {
      regs: arch::initialise_call_frame(&mut stack,
        init_ctx::<T, Args, Result> as libc::uintptr_t,
        &[init as libc::uintptr_t,
          data as libc::uintptr_t,
          f.data as libc::uintptr_t,
          f.vtable as libc::uintptr_t]),
      stack: stack
    }
  }
}

unsafe extern "C" fn init_ctx<T, A, R>(start: StartFn<T, A, R>, data: *mut T,
                                       f_data: *mut (), f_vtable: *mut ()) -> ! {
  let f: BoxedFn<A, R> = transmute(raw::TraitObject {
    data: f_data,
    vtable: f_vtable
  });

  start(data, f)
}

impl Context {
  pub unsafe fn native() -> Context {
    Context {
      regs: Registers::new(),
      stack: Stack::native(arch::get_sp_limit())
    }
  }

  #[inline(always)]
  pub unsafe fn swap(out_context: &mut Context, in_context: &mut Context) {
    arch::set_sp_limit(in_context.stack.limit());
    arch::swapcontext(&mut out_context.regs, &mut in_context.regs);
  }
}
<commit_msg>use arch::uintptr_t instead of libc::uintptr_t<commit_after>use std::mem::transmute;
use std::raw;
use fn_box::FnBox;

use stack::Stack;
use arch::{mod, Registers};

pub struct Context {
  regs: Registers,
  stack: Stack
}

pub type BoxedFn<Args, Result> = Box<FnBox<Args, Result> + Send + 'static>;
pub type StartFn<T, Args, Result> = fn(data: *mut T, f: BoxedFn<Args, Result>) -> !;

impl Context {
  pub fn new<T, Args, Result>(init: StartFn<T, Args, Result>, data: *mut T,
                              f: BoxedFn<Args, Result>) -> Context {
    let mut stack = Stack::new(4 << 20);
    let f: raw::TraitObject = unsafe { transmute(f) };

    Context {
      regs: arch::initialise_call_frame(&mut stack,
        init_ctx::<T, Args, Result> as arch::uintptr_t,
        &[init as arch::uintptr_t,
          data as arch::uintptr_t,
          f.data as arch::uintptr_t,
          f.vtable as arch::uintptr_t]),
      stack: stack
    }
  }
}

unsafe extern "C" fn init_ctx<T, A, R>(start: StartFn<T, A, R>, data: *mut T,
                                       f_data: *mut (), f_vtable: *mut ()) -> ! {
  let f: BoxedFn<A, R> = transmute(raw::TraitObject {
    data: f_data,
    vtable: f_vtable
  });

  start(data, f)
}

impl Context {
  pub unsafe fn native() -> Context {
    Context {
      regs: Registers::new(),
      stack: Stack::native(arch::get_sp_limit())
    }
  }

  #[inline(always)]
  pub unsafe fn swap(out_context: &mut Context, in_context: &mut Context) {
    arch::set_sp_limit(in_context.stack.limit());
    arch::swapcontext(&mut out_context.regs, &mut in_context.regs);
  }
}
<|endoftext|>


<commit_before>//! Defines conversion traits between rust types and numpy data types.

use ndarray::{ArrayBase, Data, Dimension, IntoDimension, Ix1, OwnedRepr};
use pyo3::Python;

use std::{mem, os::raw::c_int};

use crate::{
    npyffi::{self, npy_intp},
    Element, PyArray,
};

/// Conversion trait from some rust types to `PyArray`.
///
/// This trait takes `self`, which means **it holds a pointer to Rust heap, until `resize` or other
/// destructive method is called**.
///
/// In addition, if you construct `PyArray` via this method,
/// **you cannot use some destructive methods like `resize`.**
///
/// # Example
/// ```
/// use numpy::{PyArray, IntoPyArray};
/// pyo3::Python::with_gil(|py| {
///     let py_array = vec![1, 2, 3].into_pyarray(py);
///     assert_eq!(py_array.readonly().as_slice().unwrap(), &[1, 2, 3]);
///     assert!(py_array.resize(100).is_err()); // You can't resize owned-by-rust array.
/// });
/// ```
pub trait IntoPyArray {
    type Item: Element;
    type Dim: Dimension;
    fn into_pyarray<'py>(self, _: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim>;
}

impl<T: Element> IntoPyArray for Box<[T]> {
    type Item = T;
    type Dim = Ix1;
    fn into_pyarray<'py>(self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
        let dims = [self.len()];
        let strides = [mem::size_of::<T>() as npy_intp];
        let data_ptr = self.as_ptr();
        unsafe { PyArray::from_raw_parts(py, dims, strides.as_ptr(), data_ptr, self) }
    }
}

impl<T: Element> IntoPyArray for Vec<T> {
    type Item = T;
    type Dim = Ix1;
    fn into_pyarray<'py>(self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
        let dims = [self.len()];
        let strides = [mem::size_of::<T>() as npy_intp];
        let data_ptr = self.as_ptr();
        unsafe { PyArray::from_raw_parts(py, dims, strides.as_ptr(), data_ptr, self) }
    }
}

impl<A, D> IntoPyArray for ArrayBase<OwnedRepr<A>, D>
where
    A: Element,
    D: Dimension,
{
    type Item = A;
    type Dim = D;
    fn into_pyarray<'py>(self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
        PyArray::from_owned_array(py, self)
    }
}

/// Conversion trait from rust types to `PyArray`.
///
/// This trait takes `&self`, which means **it allocates in Python heap and then copies
/// elements there**.
/// # Example
/// ```
/// use numpy::{PyArray, ToPyArray};
/// pyo3::Python::with_gil(|py| {
///     let py_array = vec![1, 2, 3].to_pyarray(py);
///     assert_eq!(py_array.readonly().as_slice().unwrap(), &[1, 2, 3]);
/// });
/// ```
///
/// This method converts a not-contiguous array to C-order contiguous array.
/// # Example
/// ```
/// use numpy::{PyArray, ToPyArray};
/// use ndarray::{arr3, s};
/// pyo3::Python::with_gil(|py| {
///     let a = arr3(&[[[ 1,  2,  3], [ 4,  5,  6]],
///                    [[ 7,  8,  9], [10, 11, 12]]]);
///     let slice = a.slice(s![.., 0..1, ..]);
///     let sliced = arr3(&[[[ 1,  2,  3]],
///                         [[ 7,  8,  9]]]);
///     let py_slice = slice.to_pyarray(py);
///     assert_eq!(py_slice.readonly().as_array(), sliced);
///     pyo3::py_run!(py, py_slice, "assert py_slice.flags['C_CONTIGUOUS']");
/// });
/// ```
pub trait ToPyArray {
    type Item: Element;
    type Dim: Dimension;
    fn to_pyarray<'py>(&self, _: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim>;
}

impl<T: Element> ToPyArray for [T] {
    type Item = T;
    type Dim = Ix1;
    fn to_pyarray<'py>(&self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
        PyArray::from_slice(py, self)
    }
}

impl<S, D, A> ToPyArray for ArrayBase<S, D>
where
    S: Data<Elem = A>,
    D: Dimension,
    A: Element,
{
    type Item = A;
    type Dim = D;
    fn to_pyarray<'py>(&self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
        let len = self.len();
        match self.order() {
            Some(order) if A::IS_COPY => {
                // if the array is contiguous, copy it by `copy_ptr`.
                let strides = self.npy_strides();
                unsafe {
                    let array =
                        PyArray::new_(py, self.raw_dim(), strides.as_ptr(), order.to_flag());
                    array.copy_ptr(self.as_ptr(), len);
                    array
                }
            }
            _ => {
                // if the array is not contiguous, copy all elements by `ArrayBase::iter`.
                let dim = self.raw_dim();
                let strides = NpyStrides::from_dim(&dim, mem::size_of::<A>());
                unsafe {
                    let array = PyArray::<A, _>::new_(py, dim, strides.as_ptr(), 0);
                    let data_ptr = array.data();
                    for (i, item) in self.iter().enumerate() {
                        data_ptr.add(i).write(item.clone());
                    }
                    array
                }
            }
        }
    }
}

pub(crate) enum Order {
    Standard,
    Fortran,
}

impl Order {
    fn to_flag(&self) -> c_int {
        match self {
            Order::Standard => 0,
            Order::Fortran => 1,
        }
    }
}

pub(crate) trait ArrayExt {
    fn npy_strides(&self) -> NpyStrides;
    fn order(&self) -> Option<Order>;
}

impl<A, S, D> ArrayExt for ArrayBase<S, D>
where
    S: Data<Elem = A>,
    D: Dimension,
{
    fn npy_strides(&self) -> NpyStrides {
        NpyStrides::new(
            self.strides().iter().map(|&x| x as npyffi::npy_intp),
            mem::size_of::<A>(),
        )
    }

    fn order(&self) -> Option<Order> {
        if self.is_standard_layout() {
            Some(Order::Standard)
        } else if self.ndim() > 1 && self.raw_view().reversed_axes().is_standard_layout() {
            Some(Order::Fortran)
        } else {
            None
        }
    }
}

/// Numpy strides with short array optimization
pub(crate) enum NpyStrides {
    Short([npyffi::npy_intp; 8]),
    Long(Vec<npyffi::npy_intp>),
}

impl NpyStrides {
    pub(crate) fn as_ptr(&self) -> *const npy_intp {
        match self {
            NpyStrides::Short(inner) => inner.as_ptr(),
            NpyStrides::Long(inner) => inner.as_ptr(),
        }
    }
    fn from_dim<D: Dimension>(dim: &D, type_size: usize) -> Self {
        Self::new(
            dim.default_strides()
                .slice()
                .iter()
                .map(|&x| x as npyffi::npy_intp),
            type_size,
        )
    }
    fn new(strides: impl ExactSizeIterator<Item = npyffi::npy_intp>, type_size: usize) -> Self {
        let len = strides.len();
        let type_size = type_size as npyffi::npy_intp;
        if len <= 8 {
            let mut res = [0; 8];
            for (i, s) in strides.enumerate() {
                res[i] = s * type_size;
            }
            NpyStrides::Short(res)
        } else {
            NpyStrides::Long(strides.map(|n| n as npyffi::npy_intp * type_size).collect())
        }
    }
}

/// Utility trait to specify the dimention of array
pub trait ToNpyDims: Dimension {
    fn ndim_cint(&self) -> c_int {
        self.ndim() as c_int
    }
    fn as_dims_ptr(&self) -> *mut npyffi::npy_intp {
        self.slice().as_ptr() as *mut npyffi::npy_intp
    }
    fn to_npy_dims(&self) -> npyffi::PyArray_Dims {
        npyffi::PyArray_Dims {
            ptr: self.as_dims_ptr(),
            len: self.ndim_cint(),
        }
    }
    fn __private__(&self) -> PrivateMarker;
}

impl<D: Dimension> ToNpyDims for D {
    fn __private__(&self) -> PrivateMarker {
        PrivateMarker
    }
}

/// Types that can be used to index an array.
///
/// See
/// [IntoDimension](https://docs.rs/ndarray/latest/ndarray/dimension/conversion/trait.IntoDimension.html)
/// for what types you can use as `NpyIndex`.
///
/// But basically, you can use
/// - [tuple](https://doc.rust-lang.org/nightly/std/primitive.tuple.html)
/// - [array](https://doc.rust-lang.org/nightly/std/primitive.array.html)
/// - [slice](https://doc.rust-lang.org/nightly/std/primitive.slice.html)
// Since Numpy's strides is byte offset, we can't use ndarray::NdIndex directly here.
pub trait NpyIndex: IntoDimension {
    fn get_checked<T>(self, dims: &[usize], strides: &[isize]) -> Option<isize>;
    fn get_unchecked<T>(self, strides: &[isize]) -> isize;
    fn __private__(self) -> PrivateMarker;
}

impl<D: IntoDimension> NpyIndex for D {
    fn get_checked<T>(self, dims: &[usize], strides: &[isize]) -> Option<isize> {
        let indices_ = self.into_dimension();
        let indices = indices_.slice();
        if indices.len() != dims.len() {
            return None;
        }
        if indices.iter().zip(dims).any(|(i, d)| i >= d) {
            return None;
        }
        Some(get_unchecked_impl(
            indices,
            strides,
            mem::size_of::<T>() as isize,
        ))
    }
    fn get_unchecked<T>(self, strides: &[isize]) -> isize {
        let indices_ = self.into_dimension();
        let indices = indices_.slice();
        get_unchecked_impl(indices, strides, mem::size_of::<T>() as isize)
    }
    fn __private__(self) -> PrivateMarker {
        PrivateMarker
    }
}

fn get_unchecked_impl(indices: &[usize], strides: &[isize], size: isize) -> isize {
    indices
        .iter()
        .zip(strides)
        .map(|(&i, stride)| stride * i as isize / size)
        .sum()
}

#[doc(hidden)]
pub struct PrivateMarker;
<commit_msg>NpyStrides does not require SBO as the upper limit is statically known.<commit_after>//! Defines conversion traits between rust types and numpy data types.

use ndarray::{ArrayBase, Data, Dimension, IntoDimension, Ix1, OwnedRepr};
use pyo3::Python;

use std::{mem, os::raw::c_int};

use crate::{
    npyffi::{self, npy_intp},
    Element, PyArray,
};

/// Conversion trait from some rust types to `PyArray`.
///
/// This trait takes `self`, which means **it holds a pointer to Rust heap, until `resize` or other
/// destructive method is called**.
///
/// In addition, if you construct `PyArray` via this method,
/// **you cannot use some destructive methods like `resize`.**
///
/// # Example
/// ```
/// use numpy::{PyArray, IntoPyArray};
/// pyo3::Python::with_gil(|py| {
///     let py_array = vec![1, 2, 3].into_pyarray(py);
///     assert_eq!(py_array.readonly().as_slice().unwrap(), &[1, 2, 3]);
///     assert!(py_array.resize(100).is_err()); // You can't resize owned-by-rust array.
/// });
/// ```
pub trait IntoPyArray {
    type Item: Element;
    type Dim: Dimension;
    fn into_pyarray<'py>(self, _: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim>;
}

impl<T: Element> IntoPyArray for Box<[T]> {
    type Item = T;
    type Dim = Ix1;
    fn into_pyarray<'py>(self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
        let dims = [self.len()];
        let strides = [mem::size_of::<T>() as npy_intp];
        let data_ptr = self.as_ptr();
        unsafe { PyArray::from_raw_parts(py, dims, strides.as_ptr(), data_ptr, self) }
    }
}

impl<T: Element> IntoPyArray for Vec<T> {
    type Item = T;
    type Dim = Ix1;
    fn into_pyarray<'py>(self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
        let dims = [self.len()];
        let strides = [mem::size_of::<T>() as npy_intp];
        let data_ptr = self.as_ptr();
        unsafe { PyArray::from_raw_parts(py, dims, strides.as_ptr(), data_ptr, self) }
    }
}

impl<A, D> IntoPyArray for ArrayBase<OwnedRepr<A>, D>
where
    A: Element,
    D: Dimension,
{
    type Item = A;
    type Dim = D;
    fn into_pyarray<'py>(self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
        PyArray::from_owned_array(py, self)
    }
}

/// Conversion trait from rust types to `PyArray`.
///
/// This trait takes `&self`, which means **it allocates in Python heap and then copies
/// elements there**.
/// # Example
/// ```
/// use numpy::{PyArray, ToPyArray};
/// pyo3::Python::with_gil(|py| {
///     let py_array = vec![1, 2, 3].to_pyarray(py);
///     assert_eq!(py_array.readonly().as_slice().unwrap(), &[1, 2, 3]);
/// });
/// ```
///
/// This method converts a not-contiguous array to C-order contiguous array.
/// # Example
/// ```
/// use numpy::{PyArray, ToPyArray};
/// use ndarray::{arr3, s};
/// pyo3::Python::with_gil(|py| {
///     let a = arr3(&[[[ 1,  2,  3], [ 4,  5,  6]],
///                    [[ 7,  8,  9], [10, 11, 12]]]);
///     let slice = a.slice(s![.., 0..1, ..]);
///     let sliced = arr3(&[[[ 1,  2,  3]],
///                         [[ 7,  8,  9]]]);
///     let py_slice = slice.to_pyarray(py);
///     assert_eq!(py_slice.readonly().as_array(), sliced);
///     pyo3::py_run!(py, py_slice, "assert py_slice.flags['C_CONTIGUOUS']");
/// });
/// ```
pub trait ToPyArray {
    type Item: Element;
    type Dim: Dimension;
    fn to_pyarray<'py>(&self, _: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim>;
}

impl<T: Element> ToPyArray for [T] {
    type Item = T;
    type Dim = Ix1;
    fn to_pyarray<'py>(&self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
        PyArray::from_slice(py, self)
    }
}

impl<S, D, A> ToPyArray for ArrayBase<S, D>
where
    S: Data<Elem = A>,
    D: Dimension,
    A: Element,
{
    type Item = A;
    type Dim = D;
    fn to_pyarray<'py>(&self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
        let len = self.len();
        match self.order() {
            Some(order) if A::IS_COPY => {
                // if the array is contiguous, copy it by `copy_ptr`.
                let strides = self.npy_strides();
                unsafe {
                    let array =
                        PyArray::new_(py, self.raw_dim(), strides.as_ptr(), order.to_flag());
                    array.copy_ptr(self.as_ptr(), len);
                    array
                }
            }
            _ => {
                // if the array is not contiguous, copy all elements by `ArrayBase::iter`.
                let dim = self.raw_dim();
                let strides = NpyStrides::new::<_, A>(
                    dim.default_strides()
                        .slice()
                        .iter()
                        .map(|&x| x as npyffi::npy_intp),
                );
                unsafe {
                    let array = PyArray::<A, _>::new_(py, dim, strides.as_ptr(), 0);
                    let data_ptr = array.data();
                    for (i, item) in self.iter().enumerate() {
                        data_ptr.add(i).write(item.clone());
                    }
                    array
                }
            }
        }
    }
}

pub(crate) enum Order {
    Standard,
    Fortran,
}

impl Order {
    fn to_flag(&self) -> c_int {
        match self {
            Order::Standard => 0,
            Order::Fortran => 1,
        }
    }
}

pub(crate) trait ArrayExt {
    fn npy_strides(&self) -> NpyStrides;
    fn order(&self) -> Option<Order>;
}

impl<A, S, D> ArrayExt for ArrayBase<S, D>
where
    S: Data<Elem = A>,
    D: Dimension,
{
    fn npy_strides(&self) -> NpyStrides {
        NpyStrides::new::<_, A>(self.strides().iter().map(|&x| x as npyffi::npy_intp))
    }

    fn order(&self) -> Option<Order> {
        if self.is_standard_layout() {
            Some(Order::Standard)
        } else if self.ndim() > 1 && self.raw_view().reversed_axes().is_standard_layout() {
            Some(Order::Fortran)
        } else {
            None
        }
    }
}

/// An array of strides sufficiently large for [any NumPy array][NPY_MAXDIMS]
///
/// [NPY_MAXDIMS]: https://github.com/numpy/numpy/blob/4c60b3263ac50e5e72f6a909e156314fc3c9cba0/numpy/core/include/numpy/ndarraytypes.h#L40
pub(crate) struct NpyStrides([npyffi::npy_intp; 32]);

impl NpyStrides {
    pub(crate) fn as_ptr(&self) -> *const npy_intp {
        self.0.as_ptr()
    }

    fn new<S, A>(strides: S) -> Self
    where
        S: Iterator<Item = npyffi::npy_intp>,
    {
        let type_size = mem::size_of::<A>() as npyffi::npy_intp;
        let mut res = [0; 32];
        for (i, s) in strides.enumerate() {
            *res.get_mut(i)
                .expect("Only dimensionalities of up to 32 are supported") = s * type_size;
        }
        Self(res)
    }
}

/// Utility trait to specify the dimention of array
pub trait ToNpyDims: Dimension {
    fn ndim_cint(&self) -> c_int {
        self.ndim() as c_int
    }
    fn as_dims_ptr(&self) -> *mut npyffi::npy_intp {
        self.slice().as_ptr() as *mut npyffi::npy_intp
    }
    fn to_npy_dims(&self) -> npyffi::PyArray_Dims {
        npyffi::PyArray_Dims {
            ptr: self.as_dims_ptr(),
            len: self.ndim_cint(),
        }
    }
    fn __private__(&self) -> PrivateMarker;
}

impl<D: Dimension> ToNpyDims for D {
    fn __private__(&self) -> PrivateMarker {
        PrivateMarker
    }
}

/// Types that can be used to index an array.
///
/// See
/// [IntoDimension](https://docs.rs/ndarray/latest/ndarray/dimension/conversion/trait.IntoDimension.html)
/// for what types you can use as `NpyIndex`.
///
/// But basically, you can use
/// - [tuple](https://doc.rust-lang.org/nightly/std/primitive.tuple.html)
/// - [array](https://doc.rust-lang.org/nightly/std/primitive.array.html)
/// - [slice](https://doc.rust-lang.org/nightly/std/primitive.slice.html)
// Since Numpy's strides is byte offset, we can't use ndarray::NdIndex directly here.
pub trait NpyIndex: IntoDimension {
    fn get_checked<T>(self, dims: &[usize], strides: &[isize]) -> Option<isize>;
    fn get_unchecked<T>(self, strides: &[isize]) -> isize;
    fn __private__(self) -> PrivateMarker;
}

impl<D: IntoDimension> NpyIndex for D {
    fn get_checked<T>(self, dims: &[usize], strides: &[isize]) -> Option<isize> {
        let indices_ = self.into_dimension();
        let indices = indices_.slice();
        if indices.len() != dims.len() {
            return None;
        }
        if indices.iter().zip(dims).any(|(i, d)| i >= d) {
            return None;
        }
        Some(get_unchecked_impl(
            indices,
            strides,
            mem::size_of::<T>() as isize,
        ))
    }
    fn get_unchecked<T>(self, strides: &[isize]) -> isize {
        let indices_ = self.into_dimension();
        let indices = indices_.slice();
        get_unchecked_impl(indices, strides, mem::size_of::<T>() as isize)
    }
    fn __private__(self) -> PrivateMarker {
        PrivateMarker
    }
}

fn get_unchecked_impl(indices: &[usize], strides: &[isize], size: isize) -> isize {
    indices
        .iter()
        .zip(strides)
        .map(|(&i, stride)| stride * i as isize / size)
        .sum()
}

#[doc(hidden)]
pub struct PrivateMarker;
<|endoftext|>


<commit_before>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::File;
use std::path::posix::Path;
use editor;
use root;

#[cfg(test)] use std::finally::Finally;
#[cfg(test)] use test_helper::{random_name,cleanup_file};

static TEMPLATE: &'static str = include_str!("creator/template.toml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = match root::muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        true  => Path::new(format!("{}/.{}/", root::homedir_string(), &DEFAULT_MUXED_DIR.to_string())),
        false => root::create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}.toml", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path);

        match editor::default_editor_set() {
            true  => editor::open_project_file(path),
            false => println!("Default editor is not set. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

/// Copy and create the new project file from a template.
fn create_project_file(path: &Path) {
    let filename = path.filename().unwrap().to_string();
    match File::create(path).write(modified_template(TEMPLATE, filename.as_slice()).as_bytes()) {
        Ok(())  => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
}

fn modified_template(template: &str, project_name: &str) -> String {
    template.replace("{file_name}", project_name)
}

#[test]
fn populates_template_values() {
    let value = modified_template(TEMPLATE, "muxed project");
    let result = value.as_slice().contains("muxed project");
    assert!(result);
}

#[test]
fn replaces_template_values() {
    let value = modified_template(TEMPLATE, "muxed project");
    let result = !value.as_slice().contains("{file_name}");
    assert!(result);
}

#[test]
fn creates_project_file() {
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), random_name()));
    create_project_file(path);
    assert!(path.exists());

    cleanup_file(path);
}

#[test]
fn errors_when_creating_project_file() {
    //assert!(false);
}

#[test]
fn create_copies_the_template_file() {
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), random_name()));
    create_project_file(path);
    let data = File::open(path).read_to_end().unwrap();
    assert_eq!(data.as_slice(), TEMPLATE.as_bytes());

    cleanup_file(path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());

    cleanup_file(path);
}
<commit_msg>Assert the template is copied with appropriate values.<commit_after>//! The initializer module parses arguments and verfies commands are valid
//! The creator module handles creating the muxed directory and project files.
#![allow(experimental)]

use std::io::File;
use std::path::posix::Path;
use editor;
use root;

#[cfg(test)] use std::finally::Finally;
#[cfg(test)] use test_helper::{random_name,cleanup_file};

static TEMPLATE: &'static str = include_str!("creator/template.toml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = match root::muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
        true  => Path::new(format!("{}/.{}/", root::homedir_string(), &DEFAULT_MUXED_DIR.to_string())),
        false => root::create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}.toml", muxed_dir.display(), name));
    if !path.exists() {
        create_project_file(path);

        match editor::default_editor_set() {
            true  => editor::open_project_file(path),
            false => println!("Default editor is not set. Please define $EDITOR in your ~/.bashrc or similar file.")
        }
    } else {
        println!("Project already exists.");
    }
}

/// Copy and create the new project file from a template.
fn create_project_file(path: &Path) {
    let filename = path.filename().unwrap().to_string();
    match File::create(path).write(modified_template(TEMPLATE, filename.as_slice()).as_bytes()) {
        Ok(())  => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
}

fn modified_template(template: &str, project_name: &str) -> String {
    template.replace("{file_name}", project_name)
}

#[test]
fn populates_template_values() {
    let value = modified_template(TEMPLATE, "muxed project");
    let result = value.as_slice().contains("muxed project");
    assert!(result);
}

#[test]
fn replaces_template_values() {
    let value = modified_template(TEMPLATE, "muxed project");
    let result = !value.as_slice().contains("{file_name}");
    assert!(result);
}

#[test]
fn creates_project_file() {
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), random_name()));
    create_project_file(path);
    assert!(path.exists());

    cleanup_file(path);
}

#[test]
fn errors_when_creating_project_file() {
    //assert!(false);
}

#[test]
fn create_copies_the_template_file() {
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), random_name()));
    let filename = path.filename().unwrap().to_string();
    create_project_file(path);
    let data = File::open(path).read_to_end().unwrap();
    let template_expectation = modified_template(TEMPLATE, filename.as_slice());
    assert_eq!(data.as_slice(), template_expectation.as_bytes());

    cleanup_file(path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}.toml", root::homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());

    cleanup_file(path);
}
<|endoftext|>


<commit_before>use serde_json;
use std::collections::HashMap;

/// Permitted JSON-API values (all JSON Values)
pub type JsonApiValue = serde_json::Value;

/// Vector of `Resource`
pub type Resources = Vec<Resource>;
/// Vector of `ResourceIdentifiers`
pub type ResourceIdentifiers = Vec<ResourceIdentifier>;
pub type Links = HashMap<String, JsonApiValue>;
/// Meta-data object, can contain any data
pub type Meta = HashMap<String, JsonApiValue>;
/// Resource Attributes, can be any JSON value
pub type ResourceAttributes = HashMap<String, JsonApiValue>;
/// Map of relationships with other objects
pub type Relationships = HashMap<String, Relationship>;
/// Side-loaded Resources
pub type Included = Vec<Resource>;
/// Data-related errors
pub type JsonApiErrors = Vec<JsonApiError>;

pub type JsonApiId = String;
pub type JsonApiIds<'a> = Vec<&'a JsonApiId>;

/// Resource Identifier
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ResourceIdentifier {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: JsonApiId,
}

/// JSON-API Resource
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Resource {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: JsonApiId,
    pub attributes: ResourceAttributes,
    pub relationships: Option<Relationships>,
    pub links: Option<Links>,
}

/// Relationship with another object
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Relationship {
    pub data: IdentifierData,
    pub links: Option<Links>,
}

/// Valid data Resource (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum PrimaryData {
    None,
    Single(Resource),
    Multiple(Resources),
}

/// Valid Resource Identifier (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum IdentifierData {
    None,
    Single(ResourceIdentifier),
    Multiple(ResourceIdentifiers),
}

/// The specification refers to this as a top-level `document`
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiDocument {
    pub data: Option<PrimaryData>,
    pub included: Option<Resources>,
    pub links: Option<Links>,
    pub meta: Option<Meta>,
    pub errors: Option<JsonApiErrors>,
    pub jsonapi: Option<JsonApiInfo>,
}

/// Error location
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ErrorSource {
    pub pointer: Option<String>,
    pub parameter: Option<String>,
}

/// JSON-API Error
/// All fields are optional
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiError {
    pub id: Option<String>,
    pub links: Option<Links>,
    pub status: Option<String>,
    pub code: Option<String>,
    pub title: Option<String>,
    pub detail: Option<String>,
    pub source: Option<ErrorSource>,
    pub meta: Option<Meta>,
}

/// Optional `JsonApiDocument` payload identifying the JSON-API version the server implements
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiInfo {
    pub version: Option<String>,
    pub meta: Option<Meta>,
}

/// Pagination links
#[derive(Serialize, Deserialize, Debug)]
pub struct Pagination {
    pub first: Option<String>,
    pub prev: Option<String>,
    pub next: Option<String>,
    pub last: Option<String>,
}

impl Pagination {
    pub fn has_first(&self) -> bool {
        !self.first.is_none()
    }
    pub fn has_prev(&self) -> bool {
        !self.prev.is_none()
    }
    pub fn has_next(&self) -> bool {
        !self.next.is_none()
    }
    pub fn has_last(&self) -> bool {
        !self.last.is_none()
    }
}

/// Top-level JSON-API Document
impl JsonApiDocument {
    fn has_errors(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_meta(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_included(&self) -> bool {
        !self.included.is_none()
    }
    fn has_data(&self) -> bool {
        !self.data.is_none()
    }
    /// This function returns `false` if the `JsonApiDocument` contains any violations of the
    /// specification. See `DocumentValidationError`
    ///
    /// The spec dictates that the document must have least one of `data`, `errors` or `meta`.
    /// Of these, `data` and `errors` must not co-exist.
    /// The optional field `included` may only be present if the `data` field is present too.
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors};
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// assert_eq!(doc.is_valid(), false);
    /// ```
    pub fn is_valid(&self) -> bool {
        match self.validate() {
            Some(_) => false,
            None => true,
        }
    }

    /// This function returns a `Vec` with identified specification violations enumerated in
    /// `DocumentValidationError`
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors, DocumentValidationError};
    ///
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// match doc.validate() {
    ///   Some(errors) => {
    ///     assert!(
    ///       errors.contains(
    ///         &DocumentValidationError::DataWithErrors
    ///       )
    ///     )
    ///   }
    ///   None => assert!(false)
    /// }
    /// ```
    pub fn validate(&self) -> Option<Vec<DocumentValidationError>> {

        let mut errors = Vec::<DocumentValidationError>::new();

        if self.has_data() && self.has_errors() {
            errors.push(DocumentValidationError::DataWithErrors);
        }

        if self.has_included() && !self.has_data() {
            errors.push(DocumentValidationError::IncludedWithoutData);
        }

        if !(self.has_data() || self.has_meta() || self.has_errors()) {
            errors.push(DocumentValidationError::MissingContent);
        }

        match errors.len() {
            0 => None,
            _ => Some(errors),
        }

    }

    /// Instantiate from string
    ///
    /// ```
    /// use jsonapi::api::JsonApiDocument;
    ///
    /// let serialized = r#"{
    ///   "data" : [
    ///     { "id":"1", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"2", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"3", "type":"post", "attributes":{}, "relationships":{}, "links" :{} }
    ///   ]
    /// }"#;
    /// let doc = JsonApiDocument::from_str(&serialized);
    /// assert_eq!(doc.is_ok(), true);
    /// ```
    pub fn from_str(s: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(&s)
    }
}

impl Resource {
    pub fn get_relationship(&self, name: &str) -> Option<&Relationship> {
        match self.relationships {
            None => None,
            Some(ref relationships) => {
                match relationships.get(name) {
                    None => None,
                    Some(rel) => Some(rel),
                }
            }
        }
    }

    pub fn get_attribute_as_string(&self, attr: &str) -> Result<String, JsonApiDataError> {
        match self.attributes.get(attr) {
            None => Err(JsonApiDataError::AttributeNotFound),
            Some(json_attr) => {
                match json_attr.as_str() {
                    None => Err(JsonApiDataError::IncompatibleAttributeType),
                    Some(s) => Ok(s.into()),
                }
            }
        }
    }

    pub fn get_attribute_as_i64(&self, attr: &str) -> Result<i64, JsonApiDataError> {
        match self.attributes.get(attr) {
            None => Err(JsonApiDataError::AttributeNotFound),
            Some(json_attr) => {
                match json_attr.as_i64() {
                    None => Err(JsonApiDataError::IncompatibleAttributeType),
                    Some(s) => Ok(s.into()),
                }
            }
        }

    }
}

impl Relationship {
    pub fn as_id(&self) -> Result<Option<&JsonApiId>, RelationshipAssumptionError> {
        match self.data {
            IdentifierData::None => Ok(None),
            IdentifierData::Multiple(_) => Err(RelationshipAssumptionError::RelationshipIsAList),
            IdentifierData::Single(ref data) => Ok(Some(&data.id)),
        }
    }

    pub fn as_ids(&self) -> Result<Option<JsonApiIds>, RelationshipAssumptionError> {
        match self.data {
            IdentifierData::None => Ok(None),
            IdentifierData::Single(_) => Err(RelationshipAssumptionError::RelationshipIsNotAList),
            IdentifierData::Multiple(ref data) => Ok(Some(data.iter().map(|x| &x.id).collect())),
        }
    }
}

/// Top-level (Document) JSON-API specification violations
#[derive(Debug, PartialEq)]
pub enum DocumentValidationError {
    IncludedWithoutData,
    DataWithErrors,
    MissingContent,
}

#[derive(Debug, PartialEq)]
pub enum JsonApiDataError {
    AttributeNotFound,
    IncompatibleAttributeType,
}

#[derive(Debug, PartialEq)]
pub enum RelationshipAssumptionError {
    RelationshipIsAList,
    RelationshipIsNotAList,
}
<commit_msg>feature: Stub Resource patch/diff functions<commit_after>use serde_json;
use std::collections::HashMap;

/// Permitted JSON-API values (all JSON Values)
pub type JsonApiValue = serde_json::Value;

/// Vector of `Resource`
pub type Resources = Vec<Resource>;
/// Vector of `ResourceIdentifiers`
pub type ResourceIdentifiers = Vec<ResourceIdentifier>;
pub type Links = HashMap<String, JsonApiValue>;
/// Meta-data object, can contain any data
pub type Meta = HashMap<String, JsonApiValue>;
/// Resource Attributes, can be any JSON value
pub type ResourceAttributes = HashMap<String, JsonApiValue>;
/// Map of relationships with other objects
pub type Relationships = HashMap<String, Relationship>;
/// Side-loaded Resources
pub type Included = Vec<Resource>;
/// Data-related errors
pub type JsonApiErrors = Vec<JsonApiError>;

pub type JsonApiId = String;
pub type JsonApiIds<'a> = Vec<&'a JsonApiId>;

/// Resource Identifier
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ResourceIdentifier {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: JsonApiId,
}

/// JSON-API Resource
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Resource {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: JsonApiId,
    pub attributes: ResourceAttributes,
    pub relationships: Option<Relationships>,
    pub links: Option<Links>,
}

/// Relationship with another object
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Relationship {
    pub data: IdentifierData,
    pub links: Option<Links>,
}

/// Valid data Resource (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum PrimaryData {
    None,
    Single(Resource),
    Multiple(Resources),
}

/// Valid Resource Identifier (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum IdentifierData {
    None,
    Single(ResourceIdentifier),
    Multiple(ResourceIdentifiers),
}

/// The specification refers to this as a top-level `document`
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiDocument {
    pub data: Option<PrimaryData>,
    pub included: Option<Resources>,
    pub links: Option<Links>,
    pub meta: Option<Meta>,
    pub errors: Option<JsonApiErrors>,
    pub jsonapi: Option<JsonApiInfo>,
}

/// Error location
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ErrorSource {
    pub pointer: Option<String>,
    pub parameter: Option<String>,
}

/// JSON-API Error
/// All fields are optional
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiError {
    pub id: Option<String>,
    pub links: Option<Links>,
    pub status: Option<String>,
    pub code: Option<String>,
    pub title: Option<String>,
    pub detail: Option<String>,
    pub source: Option<ErrorSource>,
    pub meta: Option<Meta>,
}

/// Optional `JsonApiDocument` payload identifying the JSON-API version the server implements
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiInfo {
    pub version: Option<String>,
    pub meta: Option<Meta>,
}

/// Pagination links
#[derive(Serialize, Deserialize, Debug)]
pub struct Pagination {
    pub first: Option<String>,
    pub prev: Option<String>,
    pub next: Option<String>,
    pub last: Option<String>,
}

#[derive(Debug)]
pub struct Patch {
    pub patch_type: PatchType,
    pub subject: String,
    pub previous: JsonApiValue,
    pub next: JsonApiValue,
}

#[derive(Debug)]
pub struct PatchSet {
    pub resource_type: String,
    pub resource_id: String,
    pub patches: Vec<Patch>,
}

impl Pagination {
    pub fn has_first(&self) -> bool {
        !self.first.is_none()
    }
    pub fn has_prev(&self) -> bool {
        !self.prev.is_none()
    }
    pub fn has_next(&self) -> bool {
        !self.next.is_none()
    }
    pub fn has_last(&self) -> bool {
        !self.last.is_none()
    }
}

/// Top-level JSON-API Document
impl JsonApiDocument {
    fn has_errors(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_meta(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_included(&self) -> bool {
        !self.included.is_none()
    }
    fn has_data(&self) -> bool {
        !self.data.is_none()
    }
    /// This function returns `false` if the `JsonApiDocument` contains any violations of the
    /// specification. See `DocumentValidationError`
    ///
    /// The spec dictates that the document must have least one of `data`, `errors` or `meta`.
    /// Of these, `data` and `errors` must not co-exist.
    /// The optional field `included` may only be present if the `data` field is present too.
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors};
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// assert_eq!(doc.is_valid(), false);
    /// ```
    pub fn is_valid(&self) -> bool {
        match self.validate() {
            Some(_) => false,
            None => true,
        }
    }

    /// This function returns a `Vec` with identified specification violations enumerated in
    /// `DocumentValidationError`
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors, DocumentValidationError};
    ///
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// match doc.validate() {
    ///   Some(errors) => {
    ///     assert!(
    ///       errors.contains(
    ///         &DocumentValidationError::DataWithErrors
    ///       )
    ///     )
    ///   }
    ///   None => assert!(false)
    /// }
    /// ```
    pub fn validate(&self) -> Option<Vec<DocumentValidationError>> {

        let mut errors = Vec::<DocumentValidationError>::new();

        if self.has_data() && self.has_errors() {
            errors.push(DocumentValidationError::DataWithErrors);
        }

        if self.has_included() && !self.has_data() {
            errors.push(DocumentValidationError::IncludedWithoutData);
        }

        if !(self.has_data() || self.has_meta() || self.has_errors()) {
            errors.push(DocumentValidationError::MissingContent);
        }

        match errors.len() {
            0 => None,
            _ => Some(errors),
        }

    }

    /// Instantiate from string
    ///
    /// ```
    /// use jsonapi::api::JsonApiDocument;
    ///
    /// let serialized = r#"{
    ///   "data" : [
    ///     { "id":"1", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"2", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"3", "type":"post", "attributes":{}, "relationships":{}, "links" :{} }
    ///   ]
    /// }"#;
    /// let doc = JsonApiDocument::from_str(&serialized);
    /// assert_eq!(doc.is_ok(), true);
    /// ```
    pub fn from_str(s: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(&s)
    }
}

impl Resource {
    pub fn get_relationship(&self, name: &str) -> Option<&Relationship> {
        match self.relationships {
            None => None,
            Some(ref relationships) => {
                match relationships.get(name) {
                    None => None,
                    Some(rel) => Some(rel),
                }
            }
        }
    }

    pub fn get_attribute_as_string(&self, attr: &str) -> Result<String, JsonApiDataError> {
        match self.attributes.get(attr) {
            None => Err(JsonApiDataError::AttributeNotFound),
            Some(json_attr) => {
                match json_attr.as_str() {
                    None => Err(JsonApiDataError::IncompatibleAttributeType),
                    Some(s) => Ok(s.into()),
                }
            }
        }
    }

    pub fn get_attribute_as_i64(&self, attr: &str) -> Result<i64, JsonApiDataError> {
        match self.attributes.get(attr) {
            None => Err(JsonApiDataError::AttributeNotFound),
            Some(json_attr) => {
                match json_attr.as_i64() {
                    None => Err(JsonApiDataError::IncompatibleAttributeType),
                    Some(s) => Ok(s.into()),
                }
            }
        }
    }

    pub fn diff(&self, alt: Resource) -> Result<PatchSet, DiffPatchError> {
        unimplemented!();
    }

    pub fn patch(&mut self, patchset: PatchSet) -> Result<(), DiffPatchError> {
        unimplemented!();
    }
}

impl Relationship {
    pub fn as_id(&self) -> Result<Option<&JsonApiId>, RelationshipAssumptionError> {
        match self.data {
            IdentifierData::None => Ok(None),
            IdentifierData::Multiple(_) => Err(RelationshipAssumptionError::RelationshipIsAList),
            IdentifierData::Single(ref data) => Ok(Some(&data.id)),
        }
    }

    pub fn as_ids(&self) -> Result<Option<JsonApiIds>, RelationshipAssumptionError> {
        match self.data {
            IdentifierData::None => Ok(None),
            IdentifierData::Single(_) => Err(RelationshipAssumptionError::RelationshipIsNotAList),
            IdentifierData::Multiple(ref data) => Ok(Some(data.iter().map(|x| &x.id).collect())),
        }
    }
}

/// Top-level (Document) JSON-API specification violations
#[derive(Debug, PartialEq)]
pub enum DocumentValidationError {
    IncludedWithoutData,
    DataWithErrors,
    MissingContent,
}

#[derive(Debug, PartialEq)]
pub enum JsonApiDataError {
    AttributeNotFound,
    IncompatibleAttributeType,
}

#[derive(Debug, PartialEq)]
pub enum RelationshipAssumptionError {
    RelationshipIsAList,
    RelationshipIsNotAList,
}

#[derive(Debug, PartialEq)]
pub enum DiffPatchError {
    IncompatibleType(String, String),
    NonExistentProperty(String),
    IncorrectPropertyValue(String),
}

#[derive(Debug, PartialEq)]
pub enum PatchType {
    Relationship,
    Attribute,
}
<|endoftext|>


<commit_before>//! Generic Integer traits.

use std::ops::{Add, Sub, Mul, Div};
use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
use std::cmp::{PartialEq, PartialOrd};
use std::mem::size_of;

/// Integer trait used to parametrize algorithms for all integer types.
pub trait Int
    : Sized
    + Copy
    + Add<Output=Self>
    + Sub<Output=Self>
    + Mul<Output=Self>
    + Div<Output=Self>
    + Not<Output=Self>
    + BitAnd<Output=Self>
    + BitOr<Output=Self>
    + BitXor<Output=Self>
    + Shr<Self, Output=Self>
    + Shl<Self, Output=Self>
    + PartialEq + PartialOrd
{
    type Unsigned: Int;
    type Signed: Int;
    #[inline] fn one() -> Self;
    #[inline] fn zero() -> Self;
    #[inline] fn byte_size() -> Self;
    #[inline] fn bit_size() -> Self;
    #[inline] fn count_ones(self) -> Self;
    #[inline] fn count_zeros(self) -> Self;
    #[inline] fn leading_zeros(self) -> Self;
    #[inline] fn trailing_zeros(self) -> Self;
    #[inline] fn wrapping_neg(self) -> Self;
    #[inline] fn wrapping_add(self, Self) -> Self;
    #[inline] fn wrapping_sub(self, Self) -> Self;
    #[inline] fn wrapping_shl(self, Self) -> Self;
    #[inline] fn wrapping_shr(self, Self) -> Self;
    #[inline] fn to_u8(self) -> u8;
    #[inline] fn to_u16(self) -> u16;
    #[inline] fn to_u32(self) -> u32;
    #[inline] fn to_u64(self) -> u64;
    #[inline] fn to_i8(self) -> i8;
    #[inline] fn to_i16(self) -> i16;
    #[inline] fn to_i32(self) -> i32;
    #[inline] fn to_i64(self) -> i64;
    #[inline] fn from_u8(u8) -> Self;
    #[inline] fn from_u16(u16) -> Self;
    #[inline] fn from_u32(u32) -> Self;
    #[inline] fn from_u64(u64) -> Self;
    #[inline] fn from_i8(i8) -> Self;
    #[inline] fn from_i16(i16) -> Self;
    #[inline] fn from_i32(i32) -> Self;
    #[inline] fn from_i64(i64) -> Self;
    #[inline] fn rotate_left(self, u32) -> Self;
    #[inline] fn rotate_right(self, u32) -> Self;
    #[inline] fn swap_bytes(self) -> Self;
    #[inline] fn from_be(self) -> Self;
    #[inline] fn from_le(self) -> Self;
    #[inline] fn to_be(self) -> Self;
    #[inline] fn to_le(self) -> Self;
    #[inline] fn pow(self, exp: u32) -> Self;
    #[inline] fn to_unsigned(self) -> Self::Unsigned;
    #[inline] fn to_signed(self) -> Self::Signed;
    #[inline] fn from_unsigned(Self::Unsigned) -> Self;
    #[inline] fn from_signed(Self::Signed) -> Self;
}

macro_rules! int_impl {
    ($T:ty, $UT:ty, $ST:ty) => (
        impl Int for $T {
            type Unsigned = $UT;
            type Signed = $ST;
            #[inline] fn one() -> Self { 1 as Self }
            #[inline] fn zero() -> Self { 0 as Self }

            #[inline] fn byte_size() -> Self {
                size_of::<Self>() as Self
            }

            #[inline] fn bit_size() -> Self {
                (Self::byte_size() * 8) as Self
            }

            #[inline] fn count_ones(self) -> $T {
                self.count_ones() as $T
            }
            #[inline] fn count_zeros(self) -> $T {
                self.count_zeros() as $T
            }
            #[inline] fn leading_zeros(self) -> $T {
                self.leading_zeros() as $T
            }
            #[inline] fn trailing_zeros(self) -> $T {
                self.trailing_zeros() as $T
            }
            #[inline] fn wrapping_neg(self) -> $T {
                self.wrapping_neg() as $T
            }
            #[inline] fn wrapping_add(self, o: Self) -> $T {
                self.wrapping_add(o) as $T
            }
            #[inline] fn wrapping_sub(self, o: Self) -> $T {
                self.wrapping_sub(o) as $T
            }
            #[inline] fn wrapping_shl(self, o: Self) -> $T {
                self.wrapping_shl(o as u32) as $T
            }
            #[inline] fn wrapping_shr(self, o: Self) -> $T {
                self.wrapping_shr(o as u32) as $T
            }

            #[inline] fn to_u8(self) -> u8 { self as u8 }
            #[inline] fn to_u16(self) -> u16 { self as u16 }
            #[inline] fn to_u32(self) -> u32 { self as u32 }
            #[inline] fn to_u64(self) -> u64 { self as u64 }
            #[inline] fn to_i8(self) -> i8 { self as i8 }
            #[inline] fn to_i16(self) -> i16 { self as i16 }
            #[inline] fn to_i32(self) -> i32 { self as i32 }
            #[inline] fn to_i64(self) -> i64 { self as i64 }
            #[inline] fn from_u8(x: u8) -> Self { x as Self }
            #[inline] fn from_u16(x: u16) -> Self { x as Self }
            #[inline] fn from_u32(x: u32) -> Self { x as Self }
            #[inline] fn from_u64(x: u64) -> Self { x as Self }
            #[inline] fn from_i8(x: i8) -> Self { x as Self }
            #[inline] fn from_i16(x: i16) -> Self { x as Self }
            #[inline] fn from_i32(x: i32) -> Self { x as Self }
            #[inline] fn from_i64(x: i64) -> Self { x as Self }

            #[inline] fn rotate_left(self, n: u32) -> Self { (self as $T).rotate_left(n) }
            #[inline] fn rotate_right(self, n: u32) -> Self { (self as $T).rotate_right(n) }
            #[inline] fn swap_bytes(self) -> Self { <$T>::swap_bytes(self) }

            #[inline] fn from_be(self) -> Self {
                <$T>::from_be(self)
            }

            #[inline] fn from_le(self) -> Self {
                <$T>::from_le(self)
            }

            #[inline] fn to_be(self) -> Self {
                <$T>::to_be(self)
            }

            #[inline] fn to_le(self) -> Self {
                <$T>::to_le(self)
            }

            #[inline] fn pow(self, exp: u32) -> Self {
                <$T>::pow(self, exp)
            }

            #[inline] fn to_unsigned(self) -> Self::Unsigned {
                self as $UT
            }
            #[inline] fn to_signed(self) -> Self::Signed {
                self as $ST
            }
            #[inline] fn from_unsigned(x: Self::Unsigned) -> Self {
                x as $T
            }
            #[inline] fn from_signed(x: Self::Signed) -> Self {
                x as $T
            }

        }
    )
}

int_impl!(u8, u8, i8);
int_impl!(u16, u16, i16);
int_impl!(u32, u32, i32);
int_impl!(u64, u64, i64);
int_impl!(usize, usize, isize);

int_impl!(i8, u8, i8);
int_impl!(i16, u16, i16);
int_impl!(i32, u32, i32);
int_impl!(i64, u64, i64);
int_impl!(isize, usize, isize);
<commit_msg>require Rem on Int<commit_after>//! Generic Integer traits.

use std::ops::{Add, Sub, Mul, Div, Rem};
use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
use std::cmp::{PartialEq, PartialOrd};
use std::mem::size_of;

/// Integer trait used to parametrize algorithms for all integer types.
pub trait Int
    : Sized
    + Copy
    + Add<Output=Self>
    + Sub<Output=Self>
    + Mul<Output=Self>
    + Div<Output=Self>
    + Rem<Output=Self>
    + Not<Output=Self>
    + BitAnd<Output=Self>
    + BitOr<Output=Self>
    + BitXor<Output=Self>
    + Shr<Self, Output=Self>
    + Shl<Self, Output=Self>
    + PartialEq + PartialOrd
{
    type Unsigned: Int;
    type Signed: Int;
    #[inline] fn one() -> Self;
    #[inline] fn zero() -> Self;
    #[inline] fn byte_size() -> Self;
    #[inline] fn bit_size() -> Self;
    #[inline] fn count_ones(self) -> Self;
    #[inline] fn count_zeros(self) -> Self;
    #[inline] fn leading_zeros(self) -> Self;
    #[inline] fn trailing_zeros(self) -> Self;
    #[inline] fn wrapping_neg(self) -> Self;
    #[inline] fn wrapping_add(self, Self) -> Self;
    #[inline] fn wrapping_sub(self, Self) -> Self;
    #[inline] fn wrapping_shl(self, Self) -> Self;
    #[inline] fn wrapping_shr(self, Self) -> Self;
    #[inline] fn to_u8(self) -> u8;
    #[inline] fn to_u16(self) -> u16;
    #[inline] fn to_u32(self) -> u32;
    #[inline] fn to_u64(self) -> u64;
    #[inline] fn to_i8(self) -> i8;
    #[inline] fn to_i16(self) -> i16;
    #[inline] fn to_i32(self) -> i32;
    #[inline] fn to_i64(self) -> i64;
    #[inline] fn from_u8(u8) -> Self;
    #[inline] fn from_u16(u16) -> Self;
    #[inline] fn from_u32(u32) -> Self;
    #[inline] fn from_u64(u64) -> Self;
    #[inline] fn from_i8(i8) -> Self;
    #[inline] fn from_i16(i16) -> Self;
    #[inline] fn from_i32(i32) -> Self;
    #[inline] fn from_i64(i64) -> Self;
    #[inline] fn rotate_left(self, u32) -> Self;
    #[inline] fn rotate_right(self, u32) -> Self;
    #[inline] fn swap_bytes(self) -> Self;
    #[inline] fn from_be(self) -> Self;
    #[inline] fn from_le(self) -> Self;
    #[inline] fn to_be(self) -> Self;
    #[inline] fn to_le(self) -> Self;
    #[inline] fn pow(self, exp: u32) -> Self;
    #[inline] fn to_unsigned(self) -> Self::Unsigned;
    #[inline] fn to_signed(self) -> Self::Signed;
    #[inline] fn from_unsigned(Self::Unsigned) -> Self;
    #[inline] fn from_signed(Self::Signed) -> Self;
}

macro_rules! int_impl {
    ($T:ty, $UT:ty, $ST:ty) => (
        impl Int for $T {
            type Unsigned = $UT;
            type Signed = $ST;
            #[inline] fn one() -> Self { 1 as Self }
            #[inline] fn zero() -> Self { 0 as Self }

            #[inline] fn byte_size() -> Self {
                size_of::<Self>() as Self
            }

            #[inline] fn bit_size() -> Self {
                (Self::byte_size() * 8) as Self
            }

            #[inline] fn count_ones(self) -> $T {
                self.count_ones() as $T
            }
            #[inline] fn count_zeros(self) -> $T {
                self.count_zeros() as $T
            }
            #[inline] fn leading_zeros(self) -> $T {
                self.leading_zeros() as $T
            }
            #[inline] fn trailing_zeros(self) -> $T {
                self.trailing_zeros() as $T
            }
            #[inline] fn wrapping_neg(self) -> $T {
                self.wrapping_neg() as $T
            }
            #[inline] fn wrapping_add(self, o: Self) -> $T {
                self.wrapping_add(o) as $T
            }
            #[inline] fn wrapping_sub(self, o: Self) -> $T {
                self.wrapping_sub(o) as $T
            }
            #[inline] fn wrapping_shl(self, o: Self) -> $T {
                self.wrapping_shl(o as u32) as $T
            }
            #[inline] fn wrapping_shr(self, o: Self) -> $T {
                self.wrapping_shr(o as u32) as $T
            }

            #[inline] fn to_u8(self) -> u8 { self as u8 }
            #[inline] fn to_u16(self) -> u16 { self as u16 }
            #[inline] fn to_u32(self) -> u32 { self as u32 }
            #[inline] fn to_u64(self) -> u64 { self as u64 }
            #[inline] fn to_i8(self) -> i8 { self as i8 }
            #[inline] fn to_i16(self) -> i16 { self as i16 }
            #[inline] fn to_i32(self) -> i32 { self as i32 }
            #[inline] fn to_i64(self) -> i64 { self as i64 }
            #[inline] fn from_u8(x: u8) -> Self { x as Self }
            #[inline] fn from_u16(x: u16) -> Self { x as Self }
            #[inline] fn from_u32(x: u32) -> Self { x as Self }
            #[inline] fn from_u64(x: u64) -> Self { x as Self }
            #[inline] fn from_i8(x: i8) -> Self { x as Self }
            #[inline] fn from_i16(x: i16) -> Self { x as Self }
            #[inline] fn from_i32(x: i32) -> Self { x as Self }
            #[inline] fn from_i64(x: i64) -> Self { x as Self }

            #[inline] fn rotate_left(self, n: u32) -> Self { (self as $T).rotate_left(n) }
            #[inline] fn rotate_right(self, n: u32) -> Self { (self as $T).rotate_right(n) }
            #[inline] fn swap_bytes(self) -> Self { <$T>::swap_bytes(self) }

            #[inline] fn from_be(self) -> Self {
                <$T>::from_be(self)
            }

            #[inline] fn from_le(self) -> Self {
                <$T>::from_le(self)
            }

            #[inline] fn to_be(self) -> Self {
                <$T>::to_be(self)
            }

            #[inline] fn to_le(self) -> Self {
                <$T>::to_le(self)
            }

            #[inline] fn pow(self, exp: u32) -> Self {
                <$T>::pow(self, exp)
            }

            #[inline] fn to_unsigned(self) -> Self::Unsigned {
                self as $UT
            }
            #[inline] fn to_signed(self) -> Self::Signed {
                self as $ST
            }
            #[inline] fn from_unsigned(x: Self::Unsigned) -> Self {
                x as $T
            }
            #[inline] fn from_signed(x: Self::Signed) -> Self {
                x as $T
            }

        }
    )
}

int_impl!(u8, u8, i8);
int_impl!(u16, u16, i16);
int_impl!(u32, u32, i32);
int_impl!(u64, u64, i64);
int_impl!(usize, usize, isize);

int_impl!(i8, u8, i8);
int_impl!(i16, u16, i16);
int_impl!(i32, u32, i32);
int_impl!(i64, u64, i64);
int_impl!(isize, usize, isize);
<|endoftext|>


<commit_before>use raw::{Env, Local};

use nodejs_sys as napi;

/// Return true if an `napi_value` `val` has the expected value type.
unsafe fn is_type(env: Env, val: Local, expect: napi::napi_valuetype) -> bool {
    let mut actual = napi::napi_valuetype::napi_undefined;
    if napi::napi_typeof(env, val, &mut actual as *mut _) == napi::napi_status::napi_ok {
        actual == expect
    } else {
        false
    }
}

pub unsafe extern "C" fn is_undefined(_env: Env, _val: Local) -> bool { unimplemented!() }

pub unsafe extern "C" fn is_null(_env: Env, _val: Local) -> bool { unimplemented!() }

/// Is `val` a JavaScript number?
pub unsafe extern "C" fn is_number(env: Env, val: Local) -> bool {
    is_type(env, val, napi::napi_valuetype::napi_number)
}

/// Is `val` a JavaScript boolean?
pub unsafe extern "C" fn is_boolean(env: Env, val: Local) -> bool {
    is_type(env, val, napi::napi_valuetype::napi_boolean)
}

/// Is `val` a JavaScript string?
pub unsafe extern "C" fn is_string(env: Env, val: Local) -> bool {
    is_type(env, val, napi::napi_valuetype::napi_string)
}

pub unsafe extern "C" fn is_object(env: Env, val: Local) -> bool {
    is_type(env, val, napi::napi_valuetype::napi_object)
}

pub unsafe extern "C" fn is_array(_env: Env, _val: Local) -> bool { unimplemented!() }

pub unsafe extern "C" fn is_function(env: Env, val: Local) -> bool {
    is_type(env, val, napi::napi_valuetype::napi_function)
}

pub unsafe extern "C" fn is_error(_env: Env, _val: Local) -> bool { unimplemented!() }

pub unsafe extern "C" fn is_buffer(_env: Env, _obj: Local) -> bool { unimplemented!() }

pub unsafe extern "C" fn is_arraybuffer(_env: Env, _obj: Local) -> bool { unimplemented!() }
<commit_msg>Implement is_arraybuffer tag check<commit_after>use raw::{Env, Local};

use nodejs_sys as napi;

/// Return true if an `napi_value` `val` has the expected value type.
unsafe fn is_type(env: Env, val: Local, expect: napi::napi_valuetype) -> bool {
    let mut actual = napi::napi_valuetype::napi_undefined;
    if napi::napi_typeof(env, val, &mut actual as *mut _) == napi::napi_status::napi_ok {
        actual == expect
    } else {
        false
    }
}

pub unsafe extern "C" fn is_undefined(_env: Env, _val: Local) -> bool { unimplemented!() }

pub unsafe extern "C" fn is_null(_env: Env, _val: Local) -> bool { unimplemented!() }

/// Is `val` a JavaScript number?
pub unsafe extern "C" fn is_number(env: Env, val: Local) -> bool {
    is_type(env, val, napi::napi_valuetype::napi_number)
}

/// Is `val` a JavaScript boolean?
pub unsafe extern "C" fn is_boolean(env: Env, val: Local) -> bool {
    is_type(env, val, napi::napi_valuetype::napi_boolean)
}

/// Is `val` a JavaScript string?
pub unsafe extern "C" fn is_string(env: Env, val: Local) -> bool {
    is_type(env, val, napi::napi_valuetype::napi_string)
}

pub unsafe extern "C" fn is_object(env: Env, val: Local) -> bool {
    is_type(env, val, napi::napi_valuetype::napi_object)
}

pub unsafe extern "C" fn is_array(_env: Env, _val: Local) -> bool { unimplemented!() }

pub unsafe extern "C" fn is_function(env: Env, val: Local) -> bool {
    is_type(env, val, napi::napi_valuetype::napi_function)
}

pub unsafe extern "C" fn is_error(_env: Env, _val: Local) -> bool { unimplemented!() }

pub unsafe extern "C" fn is_buffer(_env: Env, _obj: Local) -> bool { unimplemented!() }

/// Is `val` an ArrayBuffer instance?
pub unsafe extern "C" fn is_arraybuffer(env: Env, val: Local) -> bool {
    let mut result = false;
    assert_eq!(napi::napi_is_arraybuffer(env, val, &mut result as *mut _), napi::napi_status::napi_ok);
    result
}
<|endoftext|>


<commit_before>use std::cell::UnsafeCell;
use std::rc::Rc;

use {
    log::warn,
    rand::{
        distributions::{Distribution, Gamma},
        rngs::{adapter::ReseedingRng, OsRng},
        CryptoRng, Rng, RngCore, SeedableRng,
    },
    rand_chacha::ChaCha20Core as Core,
};

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully elliminated by the compiler in non-test code.
pub fn debug_delay() {
    use std::thread;
    use std::time::Duration;

    let mut rng = if let Some(rng) = try_thread_rng() {
        rng
    } else {
        warn!("already destroyed TLS when this debug delay was called");
        return;
    };

    let intensity: f64 = std::env::var("SLED_LOCK_FREE_DELAY_INTENSITY")
        .unwrap_or("100.0".into())
        .parse()
        .expect(
            "SLED_LOCK_FREE_DELAY_INTENSITY must be set to a \
             float (ideally between 1-1,000,000)",
        );

    if rng.gen_bool(1. / 1000.) {
        let gamma = Gamma::new(0.3, 1_000.0 * intensity);
        let duration = gamma.sample(&mut try_thread_rng().unwrap());
        thread::sleep(Duration::from_micros(duration as u64));
    }

    if rng.gen::<bool>() {
        thread::yield_now();
    }
}

#[derive(Copy, Clone, Debug)]
pub struct ThreadRng {
    // use of raw pointer implies type is neither Send nor Sync
    rng: *mut ReseedingRng<Core, OsRng>,
}

const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64;

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

/// Access a thread-rng that may have been destroyed.
fn try_thread_rng() -> Option<ThreadRng> {
    THREAD_RNG_KEY.try_with(|t| ThreadRng { rng: t.get() }).ok()
}

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

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

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

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}

impl CryptoRng for ThreadRng {}
<commit_msg>Move to rand_distr crate away from deprecated rand::distribution module<commit_after>use std::cell::UnsafeCell;

use {
    log::warn,
    rand::{
        rngs::{adapter::ReseedingRng, OsRng},
        CryptoRng, Rng, RngCore, SeedableRng,
    },
    rand_chacha::ChaCha20Core as Core,
    rand_distr::{Distribution, Gamma},
};

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully elliminated by the compiler in non-test code.
pub fn debug_delay() {
    use std::thread;
    use std::time::Duration;

    let mut rng = if let Some(rng) = try_thread_rng() {
        rng
    } else {
        warn!("already destroyed TLS when this debug delay was called");
        return;
    };

    let intensity: f64 = std::env::var("SLED_LOCK_FREE_DELAY_INTENSITY")
        .unwrap_or("100.0".into())
        .parse()
        .expect(
            "SLED_LOCK_FREE_DELAY_INTENSITY must be set to a \
             float (ideally between 1-1,000,000)",
        );

    if rng.gen_bool(1. / 1000.) {
        let gamma = Gamma::new(0.3, 1_000.0 * intensity).unwrap();
        let duration = gamma.sample(&mut try_thread_rng().unwrap());
        thread::sleep(Duration::from_micros(duration as u64));
    }

    if rng.gen::<bool>() {
        thread::yield_now();
    }
}

#[derive(Copy, Clone, Debug)]
pub struct ThreadRng {
    // use of raw pointer implies type is neither Send nor Sync
    rng: *mut ReseedingRng<Core, OsRng>,
}

const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64;

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

/// Access a thread-rng that may have been destroyed.
fn try_thread_rng() -> Option<ThreadRng> {
    THREAD_RNG_KEY.try_with(|t| ThreadRng { rng: t.get() }).ok()
}

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

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

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

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}

impl CryptoRng for ThreadRng {}
<|endoftext|>