<commit_before>use bytes::{BufMut, Bytes};
use chrono::{TimeZone, UTC};
use error::{Error, HyperError};
use futures::{Async, Future, Poll, Stream};
use futures::stream::Fuse;
use serde::de::{Deserialize, Deserializer, Error as SerdeError};
use std::time::Duration;
use tokio_core::reactor::{Handle, Timeout};
use types::DateTime;

macro_rules! string_enums {
    (
        $(
            $(#[$attr:meta])*
            pub enum $E:ident {
                $(
                    $(#[$v_attr:meta])*
                    :$V:ident($by:expr) // The leading (ugly) colon is to suppress local ambiguity error.
                ),*;
                $(#[$u_attr:meta])*
                :$U:ident(_),
            }
        )*
    ) => {
        $(
            $(#[$attr])*
            pub enum $E {
                $(
                    $(#[$v_attr])*
                    $V,
                )*
                $(#[$u_attr])*
                $U(String),
            }

            impl ::serde::Deserialize for $E {
                fn deserialize<D: ::serde::Deserializer>(d: D) -> ::std::result::Result<Self, D::Error> {
                    struct V;

                    impl ::serde::de::Visitor for V {
                        type Value = $E;

                        fn visit_str<E>(self, s: &str) -> ::std::result::Result<$E, E> {
                            match s {
                                $($by => Ok($E::$V),)*
                                _ => Ok($E::$U(s.to_owned())),
                            }
                        }

                        fn visit_string<E>(self, s: String) -> ::std::result::Result<$E, E> {
                            match s.as_str() {
                                $($by => Ok($E::$V),)*
                                _ => Ok($E::$U(s)),
                            }
                        }

                        fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                            write!(f, "a string")
                        }
                    }

                    d.deserialize_string(V)
                }
            }

            impl ::std::convert::AsRef<str> for $E {
                fn as_ref(&self) -> &str {
                    match *self {
                        $($E::$V => $by,)*
                        $E::$U(ref s) => s,
                    }
                }
            }

            impl ::std::cmp::PartialEq for $E {
                fn eq(&self, other: &$E) -> bool {
                    match *self {
                        $($E::$V => match *other {
                            $E::$V => true,
                            $E::$U(ref s) if $by == s => true,
                            _ => false,
                        },)*
                        $E::$U(ref s) => match *other {
                            $($E::$V => $by == s,)*
                            $E::$U(ref t) => s == t,
                        },
                    }
                }
            }

            impl ::std::hash::Hash for $E {
                fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
                    match *self {
                        $($E::$V => $by.hash(state),)*
                        $E::$U(ref s) => s.hash(state),
                    }
                }
            }

            impl ::std::cmp::Eq for $E {}
        )*
    }
}

pub struct BaseTimeout {
    dur: Duration,
    handle: Handle,
    timer: Timeout,
}

/// Adds a timeout to a `Stream`. Inspired by `tokio_timer::TimeoutStream`.
pub struct TimeoutStream<S> {
    stream: S,
    inner: Option<BaseTimeout>,
}

/// A stream over the lines (delimited by CRLF) of a `Body`.
pub struct Lines<B> where B: Stream {
    inner: Fuse<B>,
    buf: Bytes,
}

impl BaseTimeout {
    pub fn new(dur: Duration, handle: Handle) -> Option<Self> {
        Timeout::new(dur, &handle).ok().map(|timer| {
            BaseTimeout {
                dur: dur,
                handle: handle,
                timer: timer,
            }
        })
    }

    pub fn for_stream<S>(self, stream: S) -> TimeoutStream<S> {
        TimeoutStream {
            stream: stream,
            inner: Timeout::new(self.dur, &self.handle).ok().map(move |timer| {
                BaseTimeout {
                    timer: timer,
                    ..self
                }
            }),
        }
    }

    pub fn timer_mut(&mut self) -> &mut Timeout {
        &mut self.timer
    }
}

impl<S> TimeoutStream<S> {
    pub fn never(stream: S) -> Self {
        TimeoutStream {
            stream: stream,
            inner: None,
        }
    }
}

impl<S> Stream for TimeoutStream<S> where S: Stream<Error=HyperError> {
    type Item = S::Item;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<S::Item>, Error> {
        let ret;

        if let Some(ref mut inner) = self.inner {
            match self.stream.poll() {
                Ok(Async::Ready(Some(v))) => {
                    ret = Ok(Some(v).into());
                    if let Ok(timer) = Timeout::new(inner.dur, &inner.handle) {
                        inner.timer = timer;
                        return ret;
                    }
                    // goto timeout_new_failed;
                },
                Ok(Async::NotReady) => match inner.timer.poll() {
                    Ok(Async::Ready(())) => return Err(Error::TimedOut),
                    Ok(Async::NotReady) => return Ok(Async::NotReady),
                    Err(_) => unreachable!(), // `Timeout` never fails.
                },
                v => return v.map_err(Error::Hyper),
            }
        } else {
            return self.stream.poll().map_err(Error::Hyper);
        }

        // timeout_new_failed:
        self.inner = None;
        ret
    }
}

impl<B> Lines<B> where B: Stream {
    pub fn new(body: B) -> Self {
        Lines {
            inner: body.fuse(),
            buf: Bytes::new(),
        }
    }
}

impl<B> Stream for Lines<B> where B: Stream, B::Item: Into<Bytes> {
    type Item = Bytes;
    type Error = B::Error;

    fn poll(&mut self) -> Poll<Option<Bytes>, B::Error> {
        use std::mem;

        macro_rules! try_ready_some {
            ($poll:expr) => {{
                let poll = $poll;
                match try_ready!(poll) {
                    Some(v) => v,
                    None    => return Ok(None.into()),
                }
            }};
        }

        if self.buf.is_empty() {
            self.buf = try_ready_some!(self.inner.poll()).into();
        }

        fn remove_next_line(buf: &mut Bytes) -> Option<Bytes> {
            (buf as &Bytes).into_iter().enumerate()
                .find(|&(i, b)| b'\r' == b && Some(&b'\n') == buf.get(i + 1))
                .map(|(i, _)| buf.split_off(i + 2))
        }

        if let Some(buf) = remove_next_line(&mut self.buf) {
            let ret = mem::replace(&mut self.buf, buf);
            return Ok(Some(ret).into());
        }

        if self.buf.is_empty() {
            self.buf = try_ready_some!(self.inner.poll()).into();
        }

        // Extend the buffer until a newline is found:
        loop {
            match try_ready!(self.inner.poll()) {
                Some(chunk) => {
                    let mut chunk = chunk.into();
                    if &b'\r' == self.buf.last().unwrap() && Some(&b'\n') == chunk.first() {
                        let i = self.buf.len() + 1;
                        extend_from_bytes(&mut self.buf, chunk);
                        let next = self.buf.split_off(i);
                        let ret = mem::replace(&mut self.buf, next);
                        return Ok(Some(ret).into());
                    } else if let Some(next) = remove_next_line(&mut chunk) {
                        extend_from_bytes(&mut self.buf, chunk);
                        let ret = mem::replace(&mut self.buf, next);
                        return Ok(Some(ret).into());
                    } else {
                        extend_from_bytes(&mut self.buf, chunk);
                    }
                },
                None => {
                    let ret = mem::replace(&mut self.buf, Bytes::new());
                    return Ok(Some(ret).into());
                },
            };
        }
    }
}

pub fn parse_datetime(s: &str) -> ::chrono::format::ParseResult<DateTime> {
    UTC.datetime_from_str(s, "%a %b %e %H:%M:%S %z %Y")
}

pub fn deserialize_datetime<D: Deserializer>(d: D) -> Result<DateTime, D::Error> {
    parse_datetime(&String::deserialize(d)?).map_err(|e| D::Error::custom(e.to_string()))
}

// XXX: possibly can be replaced with carllerche/bytes#85
fn extend_from_bytes(dst: &mut Bytes, src: Bytes) {
    use std::mem;

    if src.is_empty() { return; }

    // Temporary swap just to take the ownership
    let buf = mem::replace(dst, src);

    *dst = match buf.try_mut() {
        Ok(mut buf) => {
            buf.reserve(dst.len());
            buf.put_slice(dst);
            buf.freeze()
        },
        Err(buf) => {
            let mut buf = buf.to_vec();
            buf.extend_from_slice(dst);
            buf.into()
        },
    };
}

#[cfg(test)]
mod test {
    use bytes::Bytes;
    use futures::stream;
    use super::*;

    #[test]
    fn lines() {
        let lines = vec![
            "abc\r\n",
            "d\r\n",
            "efg\r\n",
            "hijk\r\n",
            "\r\n",
            "lmn\r\n",
            "opq\rrs\r\n",
            "\n\rtuv\r\r\n",
            "wxyz",
        ];
        let body = vec![
            Bytes::from(b"abc\r\n".to_vec()),
            Bytes::from(b"d\r\nefg\r\n".to_vec()),
            Bytes::from(b"hi".to_vec()),
            Bytes::from(b"jk".to_vec()),
            Bytes::from(b"\r\n".to_vec()),
            Bytes::from(b"\r\n".to_vec()),
            Bytes::from(b"lmn\r\nop".to_vec()),
            Bytes::from(b"q\rrs\r".to_vec()),
            Bytes::from(b"\n\n\rtuv\r\r\n".to_vec()),
            Bytes::from(b"wxyz".to_vec()),
        ];

        let mut iter1 = lines.iter().cloned();
        let mut iter2 = Lines::new(stream::iter::<_,_,()>(body.into_iter().map(Ok)))
            .wait().map(|s| String::from_utf8(s.unwrap().to_vec()).unwrap());

        for _ in 0..(lines.len()+1) {
            assert_eq!(
                iter1.next(),
                iter2.next().as_ref().map(String::as_str)
            );
        }
    }
}
<commit_msg>Tiny performance tweak<commit_after>use bytes::{BufMut, Bytes};
use chrono::{TimeZone, UTC};
use error::{Error, HyperError};
use futures::{Async, Future, Poll, Stream};
use futures::stream::Fuse;
use serde::de::{Deserialize, Deserializer, Error as SerdeError};
use std::time::Duration;
use tokio_core::reactor::{Handle, Timeout};
use types::DateTime;

macro_rules! string_enums {
    (
        $(
            $(#[$attr:meta])*
            pub enum $E:ident {
                $(
                    $(#[$v_attr:meta])*
                    :$V:ident($by:expr) // The leading (ugly) colon is to suppress local ambiguity error.
                ),*;
                $(#[$u_attr:meta])*
                :$U:ident(_),
            }
        )*
    ) => {
        $(
            $(#[$attr])*
            pub enum $E {
                $(
                    $(#[$v_attr])*
                    $V,
                )*
                $(#[$u_attr])*
                $U(String),
            }

            impl ::serde::Deserialize for $E {
                fn deserialize<D: ::serde::Deserializer>(d: D) -> ::std::result::Result<Self, D::Error> {
                    struct V;

                    impl ::serde::de::Visitor for V {
                        type Value = $E;

                        fn visit_str<E>(self, s: &str) -> ::std::result::Result<$E, E> {
                            match s {
                                $($by => Ok($E::$V),)*
                                _ => Ok($E::$U(s.to_owned())),
                            }
                        }

                        fn visit_string<E>(self, s: String) -> ::std::result::Result<$E, E> {
                            match s.as_str() {
                                $($by => Ok($E::$V),)*
                                _ => Ok($E::$U(s)),
                            }
                        }

                        fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                            write!(f, "a string")
                        }
                    }

                    d.deserialize_string(V)
                }
            }

            impl ::std::convert::AsRef<str> for $E {
                fn as_ref(&self) -> &str {
                    match *self {
                        $($E::$V => $by,)*
                        $E::$U(ref s) => s,
                    }
                }
            }

            impl ::std::cmp::PartialEq for $E {
                fn eq(&self, other: &$E) -> bool {
                    match *self {
                        $($E::$V => match *other {
                            $E::$V => true,
                            $E::$U(ref s) if $by == s => true,
                            _ => false,
                        },)*
                        $E::$U(ref s) => match *other {
                            $($E::$V => $by == s,)*
                            $E::$U(ref t) => s == t,
                        },
                    }
                }
            }

            impl ::std::hash::Hash for $E {
                fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
                    match *self {
                        $($E::$V => $by.hash(state),)*
                        $E::$U(ref s) => s.hash(state),
                    }
                }
            }

            impl ::std::cmp::Eq for $E {}
        )*
    }
}

pub struct BaseTimeout {
    dur: Duration,
    handle: Handle,
    timer: Timeout,
}

/// Adds a timeout to a `Stream`. Inspired by `tokio_timer::TimeoutStream`.
pub struct TimeoutStream<S> {
    stream: S,
    inner: Option<BaseTimeout>,
}

/// A stream over the lines (delimited by CRLF) of a `Body`.
pub struct Lines<B> where B: Stream {
    inner: Fuse<B>,
    buf: Bytes,
}

impl BaseTimeout {
    pub fn new(dur: Duration, handle: Handle) -> Option<Self> {
        Timeout::new(dur, &handle).ok().map(|timer| {
            BaseTimeout {
                dur: dur,
                handle: handle,
                timer: timer,
            }
        })
    }

    pub fn for_stream<S>(self, stream: S) -> TimeoutStream<S> {
        TimeoutStream {
            stream: stream,
            inner: Timeout::new(self.dur, &self.handle).ok().map(move |timer| {
                BaseTimeout {
                    timer: timer,
                    ..self
                }
            }),
        }
    }

    pub fn timer_mut(&mut self) -> &mut Timeout {
        &mut self.timer
    }
}

impl<S> TimeoutStream<S> {
    pub fn never(stream: S) -> Self {
        TimeoutStream {
            stream: stream,
            inner: None,
        }
    }
}

impl<S> Stream for TimeoutStream<S> where S: Stream<Error=HyperError> {
    type Item = S::Item;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<S::Item>, Error> {
        let ret;

        if let Some(ref mut inner) = self.inner {
            match self.stream.poll() {
                Ok(Async::Ready(Some(v))) => {
                    ret = Ok(Some(v).into());
                    if let Ok(timer) = Timeout::new(inner.dur, &inner.handle) {
                        inner.timer = timer;
                        return ret;
                    }
                    // goto timeout_new_failed;
                },
                Ok(Async::NotReady) => match inner.timer.poll() {
                    Ok(Async::Ready(())) => return Err(Error::TimedOut),
                    Ok(Async::NotReady) => return Ok(Async::NotReady),
                    Err(_) => unreachable!(), // `Timeout` never fails.
                },
                v => return v.map_err(Error::Hyper),
            }
        } else {
            return self.stream.poll().map_err(Error::Hyper);
        }

        // timeout_new_failed:
        self.inner = None;
        ret
    }
}

impl<B> Lines<B> where B: Stream {
    pub fn new(body: B) -> Self {
        Lines {
            inner: body.fuse(),
            buf: Bytes::new(),
        }
    }
}

impl<B> Stream for Lines<B> where B: Stream, B::Item: Into<Bytes> {
    type Item = Bytes;
    type Error = B::Error;

    fn poll(&mut self) -> Poll<Option<Bytes>, B::Error> {
        use std::mem;

        macro_rules! try_ready_some {
            ($poll:expr) => {{
                let poll = $poll;
                match try_ready!(poll) {
                    Some(v) => v,
                    None    => return Ok(None.into()),
                }
            }};
        }

        if self.buf.is_empty() {
            self.buf = try_ready_some!(self.inner.poll()).into();
        }

        fn remove_next_line(buf: &mut Bytes) -> Option<Bytes> {
            (buf as &Bytes).into_iter().enumerate()
                .find(|&(i, b)| b'\r' == b && Some(&b'\n') == buf.get(i + 1))
                .map(|(i, _)| buf.split_off(i + 2))
        }

        if let Some(buf) = remove_next_line(&mut self.buf) {
            let ret = mem::replace(&mut self.buf, buf);
            return Ok(Some(ret).into());
        }

        if self.buf.is_empty() {
            self.buf = try_ready_some!(self.inner.poll()).into();
        }

        // Extend the buffer until a newline is found:
        loop {
            match try_ready!(self.inner.poll()) {
                Some(chunk) => {
                    let mut chunk = chunk.into();
                    if &b'\r' == self.buf.last().unwrap() && Some(&b'\n') == chunk.first() {
                        let i = self.buf.len() + 1;
                        extend_from_bytes(&mut self.buf, chunk);
                        let next = self.buf.split_off(i);
                        let ret = mem::replace(&mut self.buf, next);
                        return Ok(Some(ret).into());
                    } else if let Some(next) = remove_next_line(&mut chunk) {
                        extend_from_bytes(&mut self.buf, chunk);
                        let ret = mem::replace(&mut self.buf, next);
                        return Ok(Some(ret).into());
                    } else {
                        extend_from_bytes(&mut self.buf, chunk);
                    }
                },
                None => {
                    let ret = mem::replace(&mut self.buf, Bytes::new());
                    return Ok(Some(ret).into());
                },
            };
        }
    }
}

pub fn parse_datetime(s: &str) -> ::chrono::format::ParseResult<DateTime> {
    UTC.datetime_from_str(s, "%a %b %e %H:%M:%S %z %Y")
}

pub fn deserialize_datetime<D: Deserializer>(d: D) -> Result<DateTime, D::Error> {
    parse_datetime(&String::deserialize(d)?).map_err(|e| D::Error::custom(e.to_string()))
}

// XXX: possibly can be replaced with carllerche/bytes#85
fn extend_from_bytes(dst: &mut Bytes, src: Bytes) {
    use std::mem;

    if src.is_empty() { return; }

    // Temporary swap just to take the ownership
    let buf = mem::replace(dst, src);

    *dst = match buf.try_mut() {
        Ok(mut buf) => {
            buf.reserve(dst.len());
            buf.put_slice(dst);
            buf.freeze()
        },
        Err(buf) => {
            let mut vec = Vec::with_capacity(buf.len() + dst.len());
            vec.extend_from_slice(&buf);
            vec.extend_from_slice(dst);
            vec.into()
        },
    };
}

#[cfg(test)]
mod test {
    use bytes::Bytes;
    use futures::stream;
    use super::*;

    #[test]
    fn lines() {
        let lines = vec![
            "abc\r\n",
            "d\r\n",
            "efg\r\n",
            "hijk\r\n",
            "\r\n",
            "lmn\r\n",
            "opq\rrs\r\n",
            "\n\rtuv\r\r\n",
            "wxyz",
        ];
        let body = vec![
            Bytes::from(b"abc\r\n".to_vec()),
            Bytes::from(b"d\r\nefg\r\n".to_vec()),
            Bytes::from(b"hi".to_vec()),
            Bytes::from(b"jk".to_vec()),
            Bytes::from(b"\r\n".to_vec()),
            Bytes::from(b"\r\n".to_vec()),
            Bytes::from(b"lmn\r\nop".to_vec()),
            Bytes::from(b"q\rrs\r".to_vec()),
            Bytes::from(b"\n\n\rtuv\r\r\n".to_vec()),
            Bytes::from(b"wxyz".to_vec()),
        ];

        let mut iter1 = lines.iter().cloned();
        let mut iter2 = Lines::new(stream::iter::<_,_,()>(body.into_iter().map(Ok)))
            .wait().map(|s| String::from_utf8(s.unwrap().to_vec()).unwrap());

        for _ in 0..(lines.len()+1) {
            assert_eq!(
                iter1.next(),
                iter2.next().as_ref().map(String::as_str)
            );
        }
    }
}
<|endoftext|>


<commit_before>use toml::Value;

use libimagerror::into::IntoError;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::result::Result;

use vcs::git::action::StoreAction;

pub fn commit_interactive(config: &Value) -> bool {
    unimplemented!()
}

pub fn commit_message(config: &Value, action: StoreAction) -> Option<String> {
    if commit_interactive(config) {
        unimplemented!()
    } else {
        unimplemented!()
    }
}

pub fn abort_on_repo_init_err(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "abort_on_repo_init_failure", true, true)
}

pub fn ensure_branch(cfg: Option<&Value>) -> Result<Option<String>> {
    match cfg {
        Some(cfg) => {
            match cfg.lookup("ensure_branch") {
                Some(&Value::String(ref s)) => Ok(Some(s.clone())),
                Some(_) => {
                    warn!("Configuration error, 'ensure_branch' must be a String.");
                    Err(GHEK::ConfigTypeError.into_error())
                        .map_err_into(GHEK::ConfigTypeError)
                },
                None => {
                    debug!("No key `ensure_branch'");
                    Ok(None)
                },
            }
        },
        None => Ok(None),
    }
}

pub fn do_checkout_ensure_branch(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "try_checkout_ensure_branch", true, true)
}

fn get_bool_cfg(cfg: Option<&Value>, name: &str, on_fail: bool, on_unavail: bool) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup(name) {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, '{}' must be a Boolean (true|false).", name);
                warn!("Assuming 'true' now.");
                on_fail
            },
            None => {
                debug!("No key '{}' - Assuming 'true'", name);
                on_fail
            },
        }
    })
    .unwrap_or(on_unavail)
}

<commit_msg>Add stubs for getting information from the config<commit_after>use toml::Value;

use libimagerror::into::IntoError;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::result::Result;

use vcs::git::action::StoreAction;

pub fn author_name(config: &Value) -> Result<&str> {
    unimplemented!()
}

pub fn author_mail(config: &Value) -> Result<&str> {
    unimplemented!()
}

pub fn committer_name(config: &Value) -> Result<&str> {
    unimplemented!()
}

pub fn committer_mail(config: &Value) -> Result<&str> {
    unimplemented!()
}

pub fn commit_interactive(config: &Value) -> bool {
    unimplemented!()
}

pub fn commit_message(config: &Value, action: StoreAction) -> Option<String> {
    if commit_interactive(config) {
        unimplemented!()
    } else {
        unimplemented!()
    }
}

pub fn abort_on_repo_init_err(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "abort_on_repo_init_failure", true, true)
}

pub fn ensure_branch(cfg: Option<&Value>) -> Result<Option<String>> {
    match cfg {
        Some(cfg) => {
            match cfg.lookup("ensure_branch") {
                Some(&Value::String(ref s)) => Ok(Some(s.clone())),
                Some(_) => {
                    warn!("Configuration error, 'ensure_branch' must be a String.");
                    Err(GHEK::ConfigTypeError.into_error())
                        .map_err_into(GHEK::ConfigTypeError)
                },
                None => {
                    debug!("No key `ensure_branch'");
                    Ok(None)
                },
            }
        },
        None => Ok(None),
    }
}

pub fn do_checkout_ensure_branch(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "try_checkout_ensure_branch", true, true)
}

fn get_bool_cfg(cfg: Option<&Value>, name: &str, on_fail: bool, on_unavail: bool) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup(name) {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, '{}' must be a Boolean (true|false).", name);
                warn!("Assuming 'true' now.");
                on_fail
            },
            None => {
                debug!("No key '{}' - Assuming 'true'", name);
                on_fail
            },
        }
    })
    .unwrap_or(on_unavail)
}

<|endoftext|>


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

macro_rules! builtins {
    ($file: expr) => {
    lazy_static! {
      static ref BUILTIN_FILE: &'static [u8] = include_bytes!($file);

      static ref BUILTIN_DEFS: Vec<Vec<u8>> = ::pumpkinscript::textparser::programs(*BUILTIN_FILE).unwrap().1;

      static ref BUILTINS: ::std::collections::BTreeMap<&'static [u8], Vec<u8>> = {
          let mut map = ::std::collections::BTreeMap::new();
          let ref defs : Vec<Vec<u8>> = *BUILTIN_DEFS;
          for definition in defs {
              match ::pumpkinscript::binparser::instruction(definition.as_slice()) {
                  ::pumpkinscript::ParseResult::Done(&[0x81, b':', ref rest..], _) => {
                      let instruction = &definition[0..definition.len() - rest.len() - 2];
                      map.insert(instruction, Vec::from(rest));
                  },
                  other => panic!("builtin definition parse error {:?}", other)
              }
          }
          map
      };
    }};
}

macro_rules! handle_builtins {
    () => {
        #[inline]
        fn handle_builtins(&mut self,
                           env: &mut Env<'a>,
                           instruction: &'a [u8],
                           _: EnvId)
                           -> PassResult<'a> {
            if BUILTINS.contains_key(instruction) {
                let vec = BUILTINS.get(instruction).unwrap();
                env.program.push(vec.as_slice());
                Ok(())
            } else {
                Err(Error::UnknownInstruction)
            }
        }
    };
}

macro_rules! handle_error {
    ($env: expr, $err: expr) => {
       handle_error!($env, $err, Ok(()))
    };
    ($env: expr, $err: expr, $body: expr) => {{
        if $env.tracking_errors > 0 {
            $env.aborting_try.push($err);
            $body
        } else {
            return Err($err)
        }
    }};
}

macro_rules! try_instruction {
  ($env: expr, $handler : expr) => {
    match $handler {
        Err(Error::UnknownInstruction) => (),
        Err(err @ Error::ProgramError(_)) => return handle_error!($env, err),
        Err(err) => return Err(err),
        Ok(()) => return Ok(())
    }
  };
}

macro_rules! stack_pop {
    ($env: expr) => {
        match $env.pop() {
            None => {
                return Err(error_empty_stack!())
            }
            Some(e) => {
                e
            }
        }
    }
}

macro_rules! instruction_is {
    ($instruction: expr, $exp: expr) => {
        if $instruction != $exp {
            return Err(Error::UnknownInstruction)
        }
    };
}

macro_rules! error_program {
    ($desc: expr, $details: expr, $code: expr) => {{
        let mut error = Vec::new();

        write_size_header!($desc, error);
        error.extend_from_slice($desc);

        if $details.len() > 0 {
            write_size!($details.len() + offset_by_size($details.len()), error);
        }

        write_size_header!($details, error);
        error.extend_from_slice($details);

        error.extend_from_slice($code);

        Error::ProgramError(error)
    }}
}

macro_rules! error_database {
    ($err: expr) => {{
        let vec = Vec::new();

        error_program!(
            $err.description().as_bytes(),
            &vec,
            ERROR_DATABASE
        )
    }}
}

macro_rules! error_no_transaction {
    () => {{
        let vec = Vec::new();
        error_program!(
            "No transaction".as_bytes(),
            &vec,
            ERROR_NO_TX
        )
    }}
}

macro_rules! error_unknown_key {
    ($key: expr) => {{
        error_program!(
            "Unknown key".as_bytes(),
            $key,
            ERROR_UNKNOWN_KEY
        )
    }}
}

macro_rules! error_duplicate_key {
    ($key: expr) => {{
        error_program!(
            "Duplicate key".as_bytes(),
            $key,
            ERROR_DUPLICATE_KEY
        )
    }}
}

macro_rules! error_decoding {
    () => {{
        let vec = Vec::new();
        error_program!(
            "Decoding error".as_bytes(),
            &vec,
            ERROR_DECODING
        )
    }}
}

macro_rules! error_empty_stack {
    () => {{
        let vec = Vec::new();
        error_program!(
            "Empty stack".as_bytes(),
            &vec,
            ERROR_EMPTY_STACK
        )
    }}
}

macro_rules! error_invalid_value {
    ($value: expr) => {{
        error_program!(
            "Invalid value".as_bytes(),
            &$value,
            ERROR_INVALID_VALUE
        )
    }}
}

macro_rules! error_no_value {
    () => {{
        let vec = Vec::new();
        error_program!(
            "No value".as_bytes(),
            &vec,
            ERROR_NO_VALUE
        )
    }}
}

macro_rules! error_unknown_instruction {
    ($instruction: expr) => { {
        let (_, w) = binparser::instruction_or_internal_instruction($instruction).unwrap();

        let instruction = match str::from_utf8(&w[1..]) {
            Ok(instruction) => instruction,
            Err(_) => "Error parsing instruction"
        };

        let desc = format!("Unknown instruction: {}", instruction);
        let desc_bytes = desc.as_bytes();

        error_program!(
            desc_bytes,
            $instruction,
            ERROR_UNKNOWN_INSTRUCTION
        )
    } }
}

macro_rules! alloc_slice {
    ($size: expr, $env: expr) => {{
        let slice = $env.alloc($size);
        if slice.is_err() {
            return Err(slice.unwrap_err());
        }
        slice.unwrap()
    }};
}

macro_rules! alloc_and_write {
    ($bytes: expr, $env: expr) => {{
        let slice = alloc_slice!($bytes.len(), $env);
        slice.copy_from_slice($bytes);
        slice
    }};
}

#[cfg(test)]
macro_rules! eval {
        ($script: expr, $env: ident, $expr: expr) => {
           eval!($script, $env, _result, $expr);
        };
        ($script: expr, $env: ident, $result: ident, $expr: expr) => {{
           let (sender, receiver) = mpsc::channel();
           eval!($script, $env, $result, sender, receiver, $expr);
        }};
        ($script: expr, $env: ident, $result: ident, $sender: expr, $receiver: ident, $expr: expr) => {
          {
            let dir = TempDir::new("pumpkindb").unwrap();
            let path = dir.path().to_str().unwrap();
            fs::create_dir_all(path).expect("can't create directory");
            let env = unsafe {
                lmdb::EnvBuilder::new()
                    .expect("can't create env builder")
                    .open(path, lmdb::open::NOTLS, 0o600)
                    .expect("can't open env")
            };

            let db = storage::Storage::new(&env);
            crossbeam::scope(|scope| {
                let mut nvmem = MmapedFile::new_anonymous(20).unwrap();
                let region = nvmem.claim(20).unwrap();
                let timestamp = Arc::new(timestamp::Timestamp::new(region));
                let mut simple = messaging::Simple::new();
                let messaging_accessor = simple.accessor();
                let publisher_thread = scope.spawn(move || simple.run());
                let publisher_clone = messaging_accessor.clone();
                let subscriber_clone = messaging_accessor.clone();
                let timestamp_clone = timestamp.clone();
                let (sender, receiver) = Scheduler::<dispatcher::StandardDispatcher<
                    messaging::SimpleAccessor, messaging::SimpleAccessor, MmapedRegion, >>::create_sender();
                let handle = scope.spawn(move || {
                    let mut scheduler = Scheduler::new(
                        dispatcher::StandardDispatcher::new(&db,
                          publisher_clone.clone(), subscriber_clone.clone(),
                          timestamp_clone),
                        receiver);
                    scheduler.run()
                });
                let script = parse($script).unwrap();
                let (callback, receiver) = mpsc::channel::<ResponseMessage>();
                let _ = sender.send(RequestMessage::ScheduleEnv(EnvId::new(),
                                    script.clone(), callback, Box::new($sender)));
                match receiver.recv() {
                   Ok(ResponseMessage::EnvTerminated(_, stack, stack_size)) => {
                      let _ = sender.send(RequestMessage::Shutdown);
                      messaging_accessor.shutdown();
                      let $result = Ok::<(), Error>(());
                      let mut stack_ = Vec::with_capacity(stack.len());
                      for i in 0..(&stack).len() {
                          stack_.push((&stack[i]).as_slice());
                      }
                      let mut $env = Env::new_with_stack(stack_, stack_size).unwrap();
                      $expr;
                   }
                   Ok(ResponseMessage::EnvFailed(_, err, stack, stack_size)) => {
                      let _ = sender.send(RequestMessage::Shutdown);
                      messaging_accessor.shutdown();
                      let $result = Err::<(), Error>(err);
                      let stack = stack.unwrap();
                      let mut stack_ = Vec::with_capacity(stack.len());
                      for i in 0..(&stack).len() {
                          stack_.push((&stack)[i].as_slice());
                      }
                      let mut $env = Env::new_with_stack(stack_, stack_size.unwrap()).unwrap();
                      $expr;
                   }
                   Err(err) => {
                      let _ = sender.send(RequestMessage::Shutdown);
                      messaging_accessor.shutdown();
                      panic!("recv error: {:?}", err);
                   }
                }
                let _ = handle.join();
                let _ = publisher_thread.join();
          });
        };
      }
}

#[cfg(test)]
macro_rules! bench_eval {
        ($script: expr, $b: expr) => {
          {
            let dir = TempDir::new("pumpkindb").unwrap();
            let path = dir.path().to_str().unwrap();
            fs::create_dir_all(path).expect("can't create directory");
            let env = unsafe {
                let mut builder = lmdb::EnvBuilder::new().expect("can't create env builder");
                builder.set_mapsize(1024 * 1024 * 1024).expect("can't set mapsize");
                builder.open(path, lmdb::open::NOTLS, 0o600).expect("can't open env")
            };

            let db = Arc::new(storage::Storage::new(&env));
            let cpus = ::num_cpus::get();
            crossbeam::scope(|scope| {
                let mut simple = messaging::Simple::new();
                let messaging_accessor = simple.accessor();
                let messaging_accessor_ = simple.accessor();
                let simple_thread = scope.spawn(move || simple.run());
                let mut nvmem = MmapedFile::new_anonymous(20).unwrap();
                let region = nvmem.claim(20).unwrap();
                let timestamp = Arc::new(timestamp::Timestamp::new(region));

                let mut handles = vec![];
                let mut senders = vec![];
                for i in 0..cpus {
                    let publisher_clone = messaging_accessor.clone();
                    let subscriber_clone = messaging_accessor.clone();
                    let timestamp_clone = timestamp.clone();
                    let (sender, receiver) = Scheduler::<dispatcher::StandardDispatcher<
                        messaging::SimpleAccessor, messaging::SimpleAccessor, MmapedRegion, >>::create_sender();
                    let storage = db.clone();
                    let handle = scope.spawn(move || {
                        let mut scheduler = Scheduler::new(
                            dispatcher::StandardDispatcher::new(&storage,
                               publisher_clone, subscriber_clone, timestamp_clone),
                            receiver,
                        );
                        scheduler.run()
                    });
                    handles.push(handle);
                    senders.push(sender.clone());
                }
                let original_senders = senders.clone();
                let script = parse($script).unwrap();
                $b.iter(move || {
                    let mut rng = ::rand::thread_rng();
                    let s = senders.clone();
                    let index: usize = rng.gen_range(0, s.len() - 1);
                    let sender = s.get(index).unwrap();

                    let (callback, receiver) = mpsc::channel::<ResponseMessage>();
                    let (sender0, _) = mpsc::channel();
                    let _ = sender.send(RequestMessage::ScheduleEnv(EnvId::new(),
                                        script.clone(), callback, Box::new(sender0)));
                    match receiver.recv() {
                       Ok(ResponseMessage::EnvTerminated(_, stack, stack_size)) => (),
                       Ok(ResponseMessage::EnvFailed(_, err, stack, stack_size)) => {
                          let _ = sender.send(RequestMessage::Shutdown);
                          messaging_accessor.shutdown();
                          panic!("error: {:?}", err);
                       }
                       Err(err) => {
                          let _ = sender.send(RequestMessage::Shutdown);
                          messaging_accessor.shutdown();
                          panic!("recv error: {:?}", err);
                       }
                    }
                });
                for s in original_senders {
                   let _ = s.send(RequestMessage::Shutdown);
                }
                messaging_accessor_.shutdown();
                for handle in handles {
                   handle.join();
                }
                simple_thread.join();
          });
        };
      }
}

#[cfg(test)]
macro_rules! data {
    ($ptr:expr) => {
        {
          let (_, size) = binparser::data_size($ptr).unwrap();
          &$ptr[offset_by_size(size)..$ptr.len()]
        }
    };
}

#[cfg(test)]
macro_rules! parsed_data {
        ($s: expr) => {
           data!(parse($s).unwrap().as_slice())
        };
}

#[cfg(test)]
macro_rules! assert_error {
    ($result: expr, $expected: expr) => {{
        assert!($result.is_err());
        let error = $result.err().unwrap();
        assert!(matches!(error, Error::ProgramError(_)));
        if let Error::ProgramError(inner) = error {
            assert_eq!(inner, parsed_data!($expected));
        } else {
        }
    }};
}
<commit_msg>Problem: impossible to reuse pumpkindb_engine's convenience macros<commit_after>// Copyright (c) 2017, All Contributors (see CONTRIBUTORS file)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#[macro_export]
macro_rules! builtins {
    ($file: expr) => {
    lazy_static! {
      static ref BUILTIN_FILE: &'static [u8] = include_bytes!($file);

      static ref BUILTIN_DEFS: Vec<Vec<u8>> = ::pumpkinscript::textparser::programs(*BUILTIN_FILE).unwrap().1;

      static ref BUILTINS: ::std::collections::BTreeMap<&'static [u8], Vec<u8>> = {
          let mut map = ::std::collections::BTreeMap::new();
          let ref defs : Vec<Vec<u8>> = *BUILTIN_DEFS;
          for definition in defs {
              match ::pumpkinscript::binparser::instruction(definition.as_slice()) {
                  ::pumpkinscript::ParseResult::Done(&[0x81, b':', ref rest..], _) => {
                      let instruction = &definition[0..definition.len() - rest.len() - 2];
                      map.insert(instruction, Vec::from(rest));
                  },
                  other => panic!("builtin definition parse error {:?}", other)
              }
          }
          map
      };
    }};
}

#[macro_export]
macro_rules! handle_builtins {
    () => {
        #[inline]
        fn handle_builtins(&mut self,
                           env: &mut Env<'a>,
                           instruction: &'a [u8],
                           _: EnvId)
                           -> PassResult<'a> {
            if BUILTINS.contains_key(instruction) {
                let vec = BUILTINS.get(instruction).unwrap();
                env.program.push(vec.as_slice());
                Ok(())
            } else {
                Err(Error::UnknownInstruction)
            }
        }
    };
}

#[macro_export]
macro_rules! handle_error {
    ($env: expr, $err: expr) => {
       handle_error!($env, $err, Ok(()))
    };
    ($env: expr, $err: expr, $body: expr) => {{
        if $env.tracking_errors > 0 {
            $env.aborting_try.push($err);
            $body
        } else {
            return Err($err)
        }
    }};
}

#[macro_export]
macro_rules! try_instruction {
  ($env: expr, $handler : expr) => {
    match $handler {
        Err(Error::UnknownInstruction) => (),
        Err(err @ Error::ProgramError(_)) => return handle_error!($env, err),
        Err(err) => return Err(err),
        Ok(()) => return Ok(())
    }
  };
}

#[macro_export]
macro_rules! stack_pop {
    ($env: expr) => {
        match $env.pop() {
            None => {
                return Err(error_empty_stack!())
            }
            Some(e) => {
                e
            }
        }
    }
}

#[macro_export]
macro_rules! instruction_is {
    ($instruction: expr, $exp: expr) => {
        if $instruction != $exp {
            return Err(Error::UnknownInstruction)
        }
    };
}

#[macro_export]
macro_rules! error_program {
    ($desc: expr, $details: expr, $code: expr) => {{
        let mut error = Vec::new();

        write_size_header!($desc, error);
        error.extend_from_slice($desc);

        if $details.len() > 0 {
            write_size!($details.len() + offset_by_size($details.len()), error);
        }

        write_size_header!($details, error);
        error.extend_from_slice($details);

        error.extend_from_slice($code);

        Error::ProgramError(error)
    }}
}

#[macro_export]
macro_rules! error_database {
    ($err: expr) => {{
        let vec = Vec::new();

        error_program!(
            $err.description().as_bytes(),
            &vec,
            ERROR_DATABASE
        )
    }}
}

#[macro_export]
macro_rules! error_no_transaction {
    () => {{
        let vec = Vec::new();
        error_program!(
            "No transaction".as_bytes(),
            &vec,
            ERROR_NO_TX
        )
    }}
}

#[macro_export]
macro_rules! error_unknown_key {
    ($key: expr) => {{
        error_program!(
            "Unknown key".as_bytes(),
            $key,
            ERROR_UNKNOWN_KEY
        )
    }}
}

#[macro_export]
macro_rules! error_duplicate_key {
    ($key: expr) => {{
        error_program!(
            "Duplicate key".as_bytes(),
            $key,
            ERROR_DUPLICATE_KEY
        )
    }}
}

#[macro_export]
macro_rules! error_decoding {
    () => {{
        let vec = Vec::new();
        error_program!(
            "Decoding error".as_bytes(),
            &vec,
            ERROR_DECODING
        )
    }}
}

#[macro_export]
macro_rules! error_empty_stack {
    () => {{
        let vec = Vec::new();
        error_program!(
            "Empty stack".as_bytes(),
            &vec,
            ERROR_EMPTY_STACK
        )
    }}
}

#[macro_export]
macro_rules! error_invalid_value {
    ($value: expr) => {{
        error_program!(
            "Invalid value".as_bytes(),
            &$value,
            ERROR_INVALID_VALUE
        )
    }}
}

#[macro_export]
macro_rules! error_no_value {
    () => {{
        let vec = Vec::new();
        error_program!(
            "No value".as_bytes(),
            &vec,
            ERROR_NO_VALUE
        )
    }}
}

#[macro_export]
macro_rules! error_unknown_instruction {
    ($instruction: expr) => { {
        let (_, w) = binparser::instruction_or_internal_instruction($instruction).unwrap();

        let instruction = match str::from_utf8(&w[1..]) {
            Ok(instruction) => instruction,
            Err(_) => "Error parsing instruction"
        };

        let desc = format!("Unknown instruction: {}", instruction);
        let desc_bytes = desc.as_bytes();

        error_program!(
            desc_bytes,
            $instruction,
            ERROR_UNKNOWN_INSTRUCTION
        )
    } }
}

#[macro_export]
macro_rules! alloc_slice {
    ($size: expr, $env: expr) => {{
        let slice = $env.alloc($size);
        if slice.is_err() {
            return Err(slice.unwrap_err());
        }
        slice.unwrap()
    }};
}

#[macro_export]
macro_rules! alloc_and_write {
    ($bytes: expr, $env: expr) => {{
        let slice = alloc_slice!($bytes.len(), $env);
        slice.copy_from_slice($bytes);
        slice
    }};
}

#[cfg(test)]
macro_rules! eval {
        ($script: expr, $env: ident, $expr: expr) => {
           eval!($script, $env, _result, $expr);
        };
        ($script: expr, $env: ident, $result: ident, $expr: expr) => {{
           let (sender, receiver) = mpsc::channel();
           eval!($script, $env, $result, sender, receiver, $expr);
        }};
        ($script: expr, $env: ident, $result: ident, $sender: expr, $receiver: ident, $expr: expr) => {
          {
            let dir = TempDir::new("pumpkindb").unwrap();
            let path = dir.path().to_str().unwrap();
            fs::create_dir_all(path).expect("can't create directory");
            let env = unsafe {
                lmdb::EnvBuilder::new()
                    .expect("can't create env builder")
                    .open(path, lmdb::open::NOTLS, 0o600)
                    .expect("can't open env")
            };

            let db = storage::Storage::new(&env);
            crossbeam::scope(|scope| {
                let mut nvmem = MmapedFile::new_anonymous(20).unwrap();
                let region = nvmem.claim(20).unwrap();
                let timestamp = Arc::new(timestamp::Timestamp::new(region));
                let mut simple = messaging::Simple::new();
                let messaging_accessor = simple.accessor();
                let publisher_thread = scope.spawn(move || simple.run());
                let publisher_clone = messaging_accessor.clone();
                let subscriber_clone = messaging_accessor.clone();
                let timestamp_clone = timestamp.clone();
                let (sender, receiver) = Scheduler::<dispatcher::StandardDispatcher<
                    messaging::SimpleAccessor, messaging::SimpleAccessor, MmapedRegion, >>::create_sender();
                let handle = scope.spawn(move || {
                    let mut scheduler = Scheduler::new(
                        dispatcher::StandardDispatcher::new(&db,
                          publisher_clone.clone(), subscriber_clone.clone(),
                          timestamp_clone),
                        receiver);
                    scheduler.run()
                });
                let script = parse($script).unwrap();
                let (callback, receiver) = mpsc::channel::<ResponseMessage>();
                let _ = sender.send(RequestMessage::ScheduleEnv(EnvId::new(),
                                    script.clone(), callback, Box::new($sender)));
                match receiver.recv() {
                   Ok(ResponseMessage::EnvTerminated(_, stack, stack_size)) => {
                      let _ = sender.send(RequestMessage::Shutdown);
                      messaging_accessor.shutdown();
                      let $result = Ok::<(), Error>(());
                      let mut stack_ = Vec::with_capacity(stack.len());
                      for i in 0..(&stack).len() {
                          stack_.push((&stack[i]).as_slice());
                      }
                      let mut $env = Env::new_with_stack(stack_, stack_size).unwrap();
                      $expr;
                   }
                   Ok(ResponseMessage::EnvFailed(_, err, stack, stack_size)) => {
                      let _ = sender.send(RequestMessage::Shutdown);
                      messaging_accessor.shutdown();
                      let $result = Err::<(), Error>(err);
                      let stack = stack.unwrap();
                      let mut stack_ = Vec::with_capacity(stack.len());
                      for i in 0..(&stack).len() {
                          stack_.push((&stack)[i].as_slice());
                      }
                      let mut $env = Env::new_with_stack(stack_, stack_size.unwrap()).unwrap();
                      $expr;
                   }
                   Err(err) => {
                      let _ = sender.send(RequestMessage::Shutdown);
                      messaging_accessor.shutdown();
                      panic!("recv error: {:?}", err);
                   }
                }
                let _ = handle.join();
                let _ = publisher_thread.join();
          });
        };
      }
}

#[cfg(test)]
macro_rules! bench_eval {
        ($script: expr, $b: expr) => {
          {
            let dir = TempDir::new("pumpkindb").unwrap();
            let path = dir.path().to_str().unwrap();
            fs::create_dir_all(path).expect("can't create directory");
            let env = unsafe {
                let mut builder = lmdb::EnvBuilder::new().expect("can't create env builder");
                builder.set_mapsize(1024 * 1024 * 1024).expect("can't set mapsize");
                builder.open(path, lmdb::open::NOTLS, 0o600).expect("can't open env")
            };

            let db = Arc::new(storage::Storage::new(&env));
            let cpus = ::num_cpus::get();
            crossbeam::scope(|scope| {
                let mut simple = messaging::Simple::new();
                let messaging_accessor = simple.accessor();
                let messaging_accessor_ = simple.accessor();
                let simple_thread = scope.spawn(move || simple.run());
                let mut nvmem = MmapedFile::new_anonymous(20).unwrap();
                let region = nvmem.claim(20).unwrap();
                let timestamp = Arc::new(timestamp::Timestamp::new(region));

                let mut handles = vec![];
                let mut senders = vec![];
                for i in 0..cpus {
                    let publisher_clone = messaging_accessor.clone();
                    let subscriber_clone = messaging_accessor.clone();
                    let timestamp_clone = timestamp.clone();
                    let (sender, receiver) = Scheduler::<dispatcher::StandardDispatcher<
                        messaging::SimpleAccessor, messaging::SimpleAccessor, MmapedRegion, >>::create_sender();
                    let storage = db.clone();
                    let handle = scope.spawn(move || {
                        let mut scheduler = Scheduler::new(
                            dispatcher::StandardDispatcher::new(&storage,
                               publisher_clone, subscriber_clone, timestamp_clone),
                            receiver,
                        );
                        scheduler.run()
                    });
                    handles.push(handle);
                    senders.push(sender.clone());
                }
                let original_senders = senders.clone();
                let script = parse($script).unwrap();
                $b.iter(move || {
                    let mut rng = ::rand::thread_rng();
                    let s = senders.clone();
                    let index: usize = rng.gen_range(0, s.len() - 1);
                    let sender = s.get(index).unwrap();

                    let (callback, receiver) = mpsc::channel::<ResponseMessage>();
                    let (sender0, _) = mpsc::channel();
                    let _ = sender.send(RequestMessage::ScheduleEnv(EnvId::new(),
                                        script.clone(), callback, Box::new(sender0)));
                    match receiver.recv() {
                       Ok(ResponseMessage::EnvTerminated(_, stack, stack_size)) => (),
                       Ok(ResponseMessage::EnvFailed(_, err, stack, stack_size)) => {
                          let _ = sender.send(RequestMessage::Shutdown);
                          messaging_accessor.shutdown();
                          panic!("error: {:?}", err);
                       }
                       Err(err) => {
                          let _ = sender.send(RequestMessage::Shutdown);
                          messaging_accessor.shutdown();
                          panic!("recv error: {:?}", err);
                       }
                    }
                });
                for s in original_senders {
                   let _ = s.send(RequestMessage::Shutdown);
                }
                messaging_accessor_.shutdown();
                for handle in handles {
                   handle.join();
                }
                simple_thread.join();
          });
        };
      }
}

#[cfg(test)]
macro_rules! data {
    ($ptr:expr) => {
        {
          let (_, size) = binparser::data_size($ptr).unwrap();
          &$ptr[offset_by_size(size)..$ptr.len()]
        }
    };
}

#[cfg(test)]
macro_rules! parsed_data {
        ($s: expr) => {
           data!(parse($s).unwrap().as_slice())
        };
}

#[cfg(test)]
macro_rules! assert_error {
    ($result: expr, $expected: expr) => {{
        assert!($result.is_err());
        let error = $result.err().unwrap();
        assert!(matches!(error, Error::ProgramError(_)));
        if let Error::ProgramError(inner) = error {
            assert_eq!(inner, parsed_data!($expected));
        } else {
        }
    }};
}
<|endoftext|>


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

use core::cell::Cell;
use core::mem;
use hil::digest::{DigestEngine, DigestMode, DigestError};
use kernel::common::cells::VolatileCell;
use super::keymgr::{KEYMGR0_REGS, Registers};

#[allow(unused)]
enum ShaTrigMask {
    Go = 0x1,
    Reset = 0x2,
    Step = 0x4,
    Stop = 0x8,
}

#[allow(unused)]
enum ShaCfgEnMask {
    BigEndian = 0x01,
    Sha1 = 0x02,

    BusError = 0x08,
    Livestream = 0x10,
    Hmac = 0x20,

    IntEnDone = 0x1_0000,
    IntMaskDone = 0x2_0000,
}

pub struct ShaEngine {
    regs: *mut Registers,
    current_mode: Cell<Option<DigestMode>>,
}

impl ShaEngine {
    const unsafe fn new(regs: *mut Registers) -> ShaEngine {
        ShaEngine {
            regs: regs,
            current_mode: Cell::new(None),
        }
    }
}

pub static mut KEYMGR0_SHA: ShaEngine = unsafe { ShaEngine::new(KEYMGR0_REGS) };

const HMAC_KEY_SIZE_BYTES: usize = 32;
const HMAC_KEY_SIZE_WORDS: usize = HMAC_KEY_SIZE_BYTES / 4;

impl DigestEngine for ShaEngine {
    fn initialize(&self, mode: DigestMode) -> Result<(), DigestError> {
        let ref regs = unsafe { &*self.regs }.sha;

        regs.itop.set(0); // clear status

        // Compile-time check for DigestMode exhaustiveness
        match mode {
            DigestMode::Sha1 |
            DigestMode::Sha256 |
            DigestMode::Sha256Hmac => (),
        };
        self.current_mode.set(Some(mode));

        regs.trig.set(ShaTrigMask::Stop as u32);

        let mut flags = ShaCfgEnMask::Livestream as u32 | ShaCfgEnMask::IntEnDone as u32;
        match mode {
            DigestMode::Sha1 => flags |= ShaCfgEnMask::Sha1 as u32,
            DigestMode::Sha256 => (),
            DigestMode::Sha256Hmac => flags |= ShaCfgEnMask::Hmac as u32,
        }
        regs.cfg_en.set(flags);

        regs.trig.set(ShaTrigMask::Go as u32);

        Ok(())
    }

    fn  initialize_hmac(&self, key: &[u8]) -> Result<(), DigestError> {
        let ref regs = unsafe { &*self.regs }.sha;

        regs.itop.set(0); // clear status
        self.current_mode.set(Some(DigestMode::Sha256Hmac));

        //regs.trig.set(ShaTrigMask::Stop as u32);

        if key.len() < HMAC_KEY_SIZE_BYTES {
            print!("Key too small: {}\n", key.len());
            return Err(DigestError::BufferTooSmall(HMAC_KEY_SIZE_BYTES));
        }
        for i in 0..HMAC_KEY_SIZE_WORDS {
            let word: u32 = (key[4 * i + 0] as u32) << 0  |
                            (key[4 * i + 1] as u32) << 8  |
                            (key[4 * i + 2] as u32) << 16 |
                            (key[4 * i + 3] as u32) << 24;
            regs.key_w[i].set(word);
        }

        let flags = ShaCfgEnMask::Livestream as u32 |
                    ShaCfgEnMask::IntEnDone as u32 |
                    ShaCfgEnMask::Hmac as u32;

        regs.cfg_en.set(flags);
        regs.trig.set(ShaTrigMask::Go as u32);

        return Ok(());
    }

    fn update(&self, data: &[u8]) -> Result<usize, DigestError> {
        let ref regs = unsafe { &*self.regs }.sha;

        if self.current_mode.get().is_none() {
            print!("ERROR: SHA::update called but engine not initialized!\n");
            return Err(DigestError::NotConfigured);
        }

        let fifo_u8: &VolatileCell<u8> = unsafe { mem::transmute(&regs.input_fifo) };

        // TODO(yuriks): Feed FIFO word at a time when possible
        for b in data {
            fifo_u8.set(*b);
        }
        Ok(data.len())
    }

    fn finalize(&self, output: &mut [u8]) -> Result<usize, DigestError> {
        let ref regs = unsafe { &*self.regs }.sha;

        let expected_output_size = match self.current_mode.get() {
            None => return Err(DigestError::NotConfigured),
            Some(mode) => mode.output_size(),
        };
        if output.len() < expected_output_size {
            return Err(DigestError::BufferTooSmall(expected_output_size));
        }

        // Tell hardware we're done streaming and then wait for the hash calculation to finish.
        regs.itop.set(0);
        regs.trig.set(ShaTrigMask::Stop as u32);
        while regs.itop.get() == 0 {}

        for i in 0..(expected_output_size / 4) {
            let word = regs.sts_h[i].get();
            output[i * 4 + 0] = (word >> 0) as u8;
            output[i * 4 + 1] = (word >> 8) as u8;
            output[i * 4 + 2] = (word >> 16) as u8;
            output[i * 4 + 3] = (word >> 24) as u8;
        }

        regs.itop.set(0);

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

use core::cell::Cell;
use core::mem;
use hil::digest::{DigestEngine, DigestMode, DigestError};
use kernel::common::cells::VolatileCell;
use super::keymgr::{KEYMGR0_REGS, Registers};

#[allow(unused)]
enum ShaTrigMask {
    Go = 0x1,
    Reset = 0x2,
    Step = 0x4,
    Stop = 0x8,
}

#[allow(unused)]
enum ShaCfgEnMask {
    BigEndian = 0x01,
    Sha1 = 0x02,

    BusError = 0x08,
    Livestream = 0x10,
    Hmac = 0x20,

    IntEnDone = 0x1_0000,
    IntMaskDone = 0x2_0000,
}

pub struct ShaEngine {
    regs: *mut Registers,
    current_mode: Cell<Option<DigestMode>>,
}

impl ShaEngine {
    const unsafe fn new(regs: *mut Registers) -> ShaEngine {
        ShaEngine {
            regs: regs,
            current_mode: Cell::new(None),
        }
    }
}

pub static mut KEYMGR0_SHA: ShaEngine = unsafe { ShaEngine::new(KEYMGR0_REGS) };

const HMAC_KEY_SIZE_BYTES: usize = 32;
const HMAC_KEY_SIZE_WORDS: usize = HMAC_KEY_SIZE_BYTES / 4;

impl DigestEngine for ShaEngine {
    fn initialize(&self, mode: DigestMode) -> Result<(), DigestError> {
        let ref regs = unsafe { &*self.regs }.sha;

        regs.itop.set(0); // clear status

        // Compile-time check for DigestMode exhaustiveness
        match mode {
            DigestMode::Sha1 |
            DigestMode::Sha256 |
            DigestMode::Sha256Hmac => (),
        };
        self.current_mode.set(Some(mode));

        regs.trig.set(ShaTrigMask::Stop as u32);

        let mut flags = ShaCfgEnMask::Livestream as u32 | ShaCfgEnMask::IntEnDone as u32;
        match mode {
            DigestMode::Sha1 => flags |= ShaCfgEnMask::Sha1 as u32,
            DigestMode::Sha256 => (),
            DigestMode::Sha256Hmac => flags |= ShaCfgEnMask::Hmac as u32,
        }
        regs.cfg_en.set(flags);

        regs.trig.set(ShaTrigMask::Go as u32);

        Ok(())
    }

    fn  initialize_hmac(&self, key: &[u8]) -> Result<(), DigestError> {
        let ref regs = unsafe { &*self.regs }.sha;

        regs.itop.set(0); // clear status
        self.current_mode.set(Some(DigestMode::Sha256Hmac));

        if key.len() < HMAC_KEY_SIZE_BYTES {
            print!("Key too small: {}\n", key.len());
            return Err(DigestError::BufferTooSmall(HMAC_KEY_SIZE_BYTES));
        }
        for i in 0..HMAC_KEY_SIZE_WORDS {
            let word: u32 = (key[4 * i + 0] as u32) << 0  |
                            (key[4 * i + 1] as u32) << 8  |
                            (key[4 * i + 2] as u32) << 16 |
                            (key[4 * i + 3] as u32) << 24;
            regs.key_w[i].set(word);
        }

        let flags = ShaCfgEnMask::Livestream as u32 |
                    ShaCfgEnMask::IntEnDone as u32 |
                    ShaCfgEnMask::Hmac as u32;

        regs.cfg_en.set(flags);
        regs.trig.set(ShaTrigMask::Go as u32);

        return Ok(());
    }

    fn update(&self, data: &[u8]) -> Result<usize, DigestError> {
        let ref regs = unsafe { &*self.regs }.sha;

        if self.current_mode.get().is_none() {
            print!("ERROR: SHA::update called but engine not initialized!\n");
            return Err(DigestError::NotConfigured);
        }

        let fifo_u8: &VolatileCell<u8> = unsafe { mem::transmute(&regs.input_fifo) };

        // TODO(yuriks): Feed FIFO word at a time when possible
        for b in data {
            fifo_u8.set(*b);
        }
        Ok(data.len())
    }

    fn finalize(&self, output: &mut [u8]) -> Result<usize, DigestError> {
        let ref regs = unsafe { &*self.regs }.sha;

        let expected_output_size = match self.current_mode.get() {
            None => return Err(DigestError::NotConfigured),
            Some(mode) => mode.output_size(),
        };
        if output.len() < expected_output_size {
            return Err(DigestError::BufferTooSmall(expected_output_size));
        }

        // Tell hardware we're done streaming and then wait for the hash calculation to finish.
        regs.itop.set(0);
        regs.trig.set(ShaTrigMask::Stop as u32);
        while regs.itop.get() == 0 {}

        for i in 0..(expected_output_size / 4) {
            let word = regs.sts_h[i].get();
            output[i * 4 + 0] = (word >> 0) as u8;
            output[i * 4 + 1] = (word >> 8) as u8;
            output[i * 4 + 2] = (word >> 16) as u8;
            output[i * 4 + 3] = (word >> 24) as u8;
        }

        regs.itop.set(0);

        Ok(expected_output_size)
    }
}
<|endoftext|>


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

#![no_std]
#![allow(unused_attributes)]
#![unstable(feature = "alloc_jemalloc",
            reason = "this library is unlikely to be stabilized in its current \
                      form or name",
            issue = "27783")]
#![deny(warnings)]
#![feature(alloc)]
#![feature(alloc_system)]
#![feature(libc)]
#![feature(linkage)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
#![rustc_alloc_kind = "exe"]

extern crate alloc;
extern crate alloc_system;
extern crate libc;

#[cfg(not(dummy_jemalloc))]
pub use contents::*;
#[cfg(not(dummy_jemalloc))]
mod contents {
    use core::ptr;

    use alloc::heap::{Alloc, AllocErr, Layout};
    use alloc_system::System;
    use libc::{c_int, c_void, size_t};

    // Note that the symbols here are prefixed by default on macOS and Windows (we
    // don't explicitly request it), and on Android and DragonFly we explicitly
    // request it as unprefixing cause segfaults (mismatches in allocators).
    extern "C" {
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_mallocx")]
        fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_calloc")]
        fn calloc(size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_rallocx")]
        fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_xallocx")]
        fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_sdallocx")]
        fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_nallocx")]
        fn nallocx(size: size_t, flags: c_int) -> size_t;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_sallocx")]
        fn sallocx(ptr: *mut c_void, flags: c_int) -> size_t;
    }

    const MALLOCX_ZERO: c_int = 0x40;

    // The minimum alignment guaranteed by the architecture. This value is used to
    // add fast paths for low alignment values. In practice, the alignment is a
    // constant at the call site and the branch will be optimized out.
    #[cfg(all(any(target_arch = "arm",
                  target_arch = "mips",
                  target_arch = "powerpc")))]
    const MIN_ALIGN: usize = 8;
    #[cfg(all(any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "aarch64",
                  target_arch = "powerpc64",
                  target_arch = "mips64",
                  target_arch = "s390x",
                  target_arch = "sparc64")))]
    const MIN_ALIGN: usize = 16;

    // MALLOCX_ALIGN(a) macro
    fn mallocx_align(a: usize) -> c_int {
        a.trailing_zeros() as c_int
    }

    fn align_to_flags(align: usize) -> c_int {
        if align <= MIN_ALIGN {
            0
        } else {
            mallocx_align(align)
        }
    }

    // for symbol names src/librustc/middle/allocator.rs
    // for signatures src/librustc_allocator/lib.rs

    // linkage directives are provided as part of the current compiler allocator
    // ABI

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc(size: usize,
                                     align: usize,
                                     err: *mut u8) -> *mut u8 {
        let flags = align_to_flags(align);
        let ptr = mallocx(size as size_t, flags) as *mut u8;
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(size, align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_oom(err: *const u8) -> ! {
        System.oom((*(err as *const AllocErr)).clone())
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
                                       size: usize,
                                       align: usize) {
        let flags = align_to_flags(align);
        sdallocx(ptr as *mut c_void, size, flags);
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_usable_size(layout: *const u8,
                                           min: *mut usize,
                                           max: *mut usize) {
        let layout = &*(layout as *const Layout);
        let flags = align_to_flags(layout.align());
        let size = nallocx(layout.size(), flags) as usize;
        *min = layout.size();
        if size > 0 {
            *max = size;
        } else {
            *max = layout.size();
        }
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_realloc(ptr: *mut u8,
                                       _old_size: usize,
                                       old_align: usize,
                                       new_size: usize,
                                       new_align: usize,
                                       err: *mut u8) -> *mut u8 {
        if new_align != old_align {
            ptr::write(err as *mut AllocErr,
                       AllocErr::Unsupported { details: "can't change alignments" });
            return 0 as *mut u8
        }

        let flags = align_to_flags(new_align);
        let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(new_size, new_align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc_zeroed(size: usize,
                                            align: usize,
                                            err: *mut u8) -> *mut u8 {
        let ptr = if align <= MIN_ALIGN {
            calloc(size as size_t, 1) as *mut u8
        } else {
            let flags = align_to_flags(align) | MALLOCX_ZERO;
            mallocx(size as size_t, flags) as *mut u8
        };
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(size, align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc_excess(size: usize,
                                            align: usize,
                                            excess: *mut usize,
                                            err: *mut u8) -> *mut u8 {
        let p = __rde_alloc(size, align, err);
        if !p.is_null() {
            *excess = size;
        }
        return p
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8,
                                              _old_size: usize,
                                              old_align: usize,
                                              new_size: usize,
                                              new_align: usize,
                                              excess: *mut usize,
                                              err: *mut u8) -> *mut u8 {
        if new_align != old_align {
            ptr::write(err as *mut AllocErr,
                       AllocErr::Unsupported { details: "can't change alignments" });
            return 0 as *mut u8
        }

        let flags = align_to_flags(new_align);
        let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(new_size, new_align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        } else {
            let alloc_size = sallocx(ptr as *mut c_void, flags);
            *excess = alloc_size;
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8,
                                             old_size: usize,
                                             old_align: usize,
                                             new_size: usize,
                                             new_align: usize) -> u8 {
        __rde_shrink_in_place(ptr, old_size, old_align, new_size, new_align)
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8,
                                               _old_size: usize,
                                               old_align: usize,
                                               new_size: usize,
                                               new_align: usize) -> u8 {
        if old_align == new_align {
            let flags = align_to_flags(new_align);
            (xallocx(ptr as *mut c_void, new_size, 0, flags) == new_size) as u8
        } else {
            0
        }
    }
}
<commit_msg>use nallocx instead of sallocx<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![no_std]
#![allow(unused_attributes)]
#![unstable(feature = "alloc_jemalloc",
            reason = "this library is unlikely to be stabilized in its current \
                      form or name",
            issue = "27783")]
#![deny(warnings)]
#![feature(alloc)]
#![feature(alloc_system)]
#![feature(libc)]
#![feature(linkage)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
#![rustc_alloc_kind = "exe"]

extern crate alloc;
extern crate alloc_system;
extern crate libc;

#[cfg(not(dummy_jemalloc))]
pub use contents::*;
#[cfg(not(dummy_jemalloc))]
mod contents {
    use core::ptr;

    use alloc::heap::{Alloc, AllocErr, Layout};
    use alloc_system::System;
    use libc::{c_int, c_void, size_t};

    // Note that the symbols here are prefixed by default on macOS and Windows (we
    // don't explicitly request it), and on Android and DragonFly we explicitly
    // request it as unprefixing cause segfaults (mismatches in allocators).
    extern "C" {
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_mallocx")]
        fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_calloc")]
        fn calloc(size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_rallocx")]
        fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_xallocx")]
        fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_sdallocx")]
        fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
                   link_name = "je_nallocx")]
        fn nallocx(size: size_t, flags: c_int) -> size_t;
    }

    const MALLOCX_ZERO: c_int = 0x40;

    // The minimum alignment guaranteed by the architecture. This value is used to
    // add fast paths for low alignment values. In practice, the alignment is a
    // constant at the call site and the branch will be optimized out.
    #[cfg(all(any(target_arch = "arm",
                  target_arch = "mips",
                  target_arch = "powerpc")))]
    const MIN_ALIGN: usize = 8;
    #[cfg(all(any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "aarch64",
                  target_arch = "powerpc64",
                  target_arch = "mips64",
                  target_arch = "s390x",
                  target_arch = "sparc64")))]
    const MIN_ALIGN: usize = 16;

    // MALLOCX_ALIGN(a) macro
    fn mallocx_align(a: usize) -> c_int {
        a.trailing_zeros() as c_int
    }

    fn align_to_flags(align: usize) -> c_int {
        if align <= MIN_ALIGN {
            0
        } else {
            mallocx_align(align)
        }
    }

    // for symbol names src/librustc/middle/allocator.rs
    // for signatures src/librustc_allocator/lib.rs

    // linkage directives are provided as part of the current compiler allocator
    // ABI

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc(size: usize,
                                     align: usize,
                                     err: *mut u8) -> *mut u8 {
        let flags = align_to_flags(align);
        let ptr = mallocx(size as size_t, flags) as *mut u8;
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(size, align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_oom(err: *const u8) -> ! {
        System.oom((*(err as *const AllocErr)).clone())
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
                                       size: usize,
                                       align: usize) {
        let flags = align_to_flags(align);
        sdallocx(ptr as *mut c_void, size, flags);
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_usable_size(layout: *const u8,
                                           min: *mut usize,
                                           max: *mut usize) {
        let layout = &*(layout as *const Layout);
        let flags = align_to_flags(layout.align());
        let size = nallocx(layout.size(), flags) as usize;
        *min = layout.size();
        if size > 0 {
            *max = size;
        } else {
            *max = layout.size();
        }
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_realloc(ptr: *mut u8,
                                       _old_size: usize,
                                       old_align: usize,
                                       new_size: usize,
                                       new_align: usize,
                                       err: *mut u8) -> *mut u8 {
        if new_align != old_align {
            ptr::write(err as *mut AllocErr,
                       AllocErr::Unsupported { details: "can't change alignments" });
            return 0 as *mut u8
        }

        let flags = align_to_flags(new_align);
        let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(new_size, new_align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc_zeroed(size: usize,
                                            align: usize,
                                            err: *mut u8) -> *mut u8 {
        let ptr = if align <= MIN_ALIGN {
            calloc(size as size_t, 1) as *mut u8
        } else {
            let flags = align_to_flags(align) | MALLOCX_ZERO;
            mallocx(size as size_t, flags) as *mut u8
        };
        if ptr.is_null() {
            let layout = Layout::from_size_align_unchecked(size, align);
            ptr::write(err as *mut AllocErr,
                       AllocErr::Exhausted { request: layout });
        }
        ptr
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_alloc_excess(size: usize,
                                            align: usize,
                                            excess: *mut usize,
                                            err: *mut u8) -> *mut u8 {
        let p = __rde_alloc(size, align, err);
        if !p.is_null() {
            *excess = size;
        }
        return p
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8,
                                              old_size: usize,
                                              old_align: usize,
                                              new_size: usize,
                                              new_align: usize,
                                              excess: *mut usize,
                                              err: *mut u8) -> *mut u8 {
        let p = __rde_realloc(ptr, old_size, old_align, new_size, new_align, err);
        if !p.is_null() {
            let flags = align_to_flags(new_align);
            *excess = nallocx(new_size, flags) as usize;
        }
        p
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8,
                                             old_size: usize,
                                             old_align: usize,
                                             new_size: usize,
                                             new_align: usize) -> u8 {
        __rde_shrink_in_place(ptr, old_size, old_align, new_size, new_align)
    }

    #[no_mangle]
    #[linkage = "external"]
    pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8,
                                               _old_size: usize,
                                               old_align: usize,
                                               new_size: usize,
                                               new_align: usize) -> u8 {
        if old_align == new_align {
            let flags = align_to_flags(new_align);
            (xallocx(ptr as *mut c_void, new_size, 0, flags) == new_size) as u8
        } else {
            0
        }
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Penney's_game
// H = true, T = false

extern crate rand;

use std::io::{stdout, stdin, Write};
use rand::{Rng, thread_rng};

fn toss_coin(print:bool) -> char {
    let c : char;
    if thread_rng().gen::<bool>() {c = 'H'} else {c = 'T'}
    if print {
        print!("{}",c);
        stdout().flush().ok().expect("Could not flush stdout");
        }
    c
}

fn gen_sequence(seed : Option<&str>) -> String {
    let mut seq = String::new();
    match seed {
        Some(s) => {
            let c0 = s.chars().next().unwrap();
            if c0 == 'H' {seq.push('T')
                } else {seq.push('H')}
            seq.push(c0);
            seq.push(s.chars().nth(1).unwrap());
        },
        None => {
            for _ in (0..3) {
                seq.push(toss_coin(false))
            }
        }
    }
    seq
}

fn read_sequence() -> String {
    let mut seq = String::new();
    'reading: loop {
        seq.clear();
        println!("Please, enter sequence of 3 coins: H (heads) or T (tails): ");
        stdin().read_line(&mut seq)
                   .ok().expect("failed to read line");
        seq = seq.trim().to_uppercase();
        if seq.len() != 3 { continue
        } else {
            for c in seq.chars() {
                match c {
                    'H' | 'T' => continue,
                    _ => {
                        println!("Please enter correct sequence!");
                        continue 'reading;
                    }
                };
            }
            return seq;
        }
    }
}

fn main() {
    let useq : String;
    let aiseq : String;
    if thread_rng().gen::<bool>() {
        println!("You choose first!");
        useq = read_sequence();
        println!("Your sequence: {}", useq);
        aiseq = gen_sequence( Some(&useq) );
        println!("My sequence: {}", aiseq);
    } else {
        println!("I choose first!");
        aiseq = gen_sequence(None);
        println!("My sequence: {}", aiseq);
        useq = read_sequence();
        println!("Your sequence: {}", useq);
    }
    println!("Tossing coins...");
    let mut coins = String::new();
    for _ in (0..2) { //toss first 2 coins
        coins.push(toss_coin(true));
        std::thread::sleep_ms(500);
    }
    loop {
        coins.push(toss_coin(true));
        std::thread::sleep_ms(500);
        if coins.contains(&useq) {
            println!("\nYou win!");
            break;
        }
        if coins.contains(&aiseq) {
            println!("\nI win!");
            break;
        }
    }
}
<commit_msg>Add main loop, check same sequences<commit_after>// http://rosettacode.org/wiki/Penney's_game
// H = true, T = false

extern crate rand;

use std::io::{stdout, stdin, Read, Write};
use rand::{Rng, thread_rng};

fn toss_coin(print:bool) -> char {
    let c : char;
    if thread_rng().gen::<bool>() {c = 'H'} else {c = 'T'}
    if print {
        print!("{}",c);
        stdout().flush().ok().expect("Could not flush stdout");
        }
    c
}

fn gen_sequence(seed : Option<&str>) -> String {
    let mut seq = String::new();
    match seed {
        Some(s) => {
            let c0 = s.chars().next().unwrap();
            if c0 == 'H' {seq.push('T')
                } else {seq.push('H')}
            seq.push(c0);
            seq.push(s.chars().nth(1).unwrap());
        },
        None => {
            for _ in 0..3 {
                seq.push(toss_coin(false))
            }
        }
    }
    seq
}

fn read_sequence(used_seq : Option<&str>) -> String {
    let mut seq = String::new();
    loop {
        seq.clear();
        println!("Please, enter sequence of 3 coins: H (heads) or T (tails): ");
        stdin().read_line(&mut seq).ok().expect("failed to read line");
        seq = seq.trim().to_uppercase();
        if !(
            seq.chars().all(|c| c == 'H' || c == 'T') &&
            seq.len() == 3 &&
            seq != used_seq.unwrap_or("")
            ) {
            println!("Please enter correct sequence!");
            continue;
        }
        return seq;
    }
}

fn main() {
    println!("--Penney's game--");
    loop {
        let useq : String;
        let aiseq : String;
        if thread_rng().gen::<bool>() {
            println!("You choose first!");
            useq = read_sequence(None);
            println!("Your sequence: {}", useq);
            aiseq = gen_sequence( Some(&useq) );
            println!("My sequence: {}", aiseq);
        } else {
            println!("I choose first!");
            aiseq = gen_sequence(None);
            println!("My sequence: {}", aiseq);
            useq = read_sequence(Some(&aiseq));
            println!("Your sequence: {}", useq);
        }
        println!("Tossing coins...");
        let mut coins = String::new();
        for _ in 0..2 { //toss first 2 coins
            coins.push(toss_coin(true));
            std::thread::sleep_ms(500);
        }
        loop {
            coins.push(toss_coin(true));
            std::thread::sleep_ms(500);
            if coins.contains(&useq) {
                println!("\nYou win!");
                break;
            }
            if coins.contains(&aiseq) {
                println!("\nI win!");
                break;
            }
        }

        println!(" Play again? Y to play, Q to exit.");
        let mut input = String::new();
        stdin().read_line(&mut input).ok().expect("failed to read line");
        match input.chars().next().unwrap() {
            'Y' | 'y' => continue,
            _ => break
        }
    }
}
<|endoftext|>


<commit_before>use std::io;

use quic::QUIC_VERSION;
use quic::errors::{Error, Result};
use super::frames::Frame;

pub const FLAG_VERSION: u8 = 0b00000001;
pub const FLAG_PUBLIC_RESET: u8 = 0b00000010;
pub const FLAG_KEY_PHASE: u8 = 0b00000100;
pub const FLAG_CONNECTION_ID: u8 = 0b00001000;
pub const FLAG_PACKET_NUMBER_SIZE_1: u8 = 0b00010000;
pub const FLAG_PACKET_NUMBER_SIZE_2: u8 = 0b00100000;
pub const FLAG_MULTIPATH: u8 = 0b01000000;
pub const FLAG_UNUSED: u8 = 0b10000000;

#[derive(Clone, Debug, Default, PartialEq)]
pub struct PacketPayload {
    // TODO: add TLS stuff one day
    pub frames: Vec<Frame>,
}

impl PacketPayload {
    pub fn encode<W: io::Write>(&self, write: &mut W, packet_number_size: usize) -> Result<()> {
        assert!(!self.frames.is_empty());

        for frame in &self.frames {
            // TODO: pass correct last_frame
            frame.encode(write, packet_number_size, false)?;
        }

        Ok(())
    }

    pub fn decode<R: io::Read + io::Seek>(read: &mut R, packet_number_size: usize) -> Result<PacketPayload> {
        let mut frames = Vec::new();
        loop {
            match Frame::decode(read, packet_number_size) {
                Ok(frame) => {
                    frames.push(frame);
                },
                Err(Error::Io(ref e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
                    break;
                },
                Err(e) => {
                    return Err(e);
                }
            }
        }

        if frames.is_empty() {
            return Err(Error::Decoding(String::from("At least one frame expected")));
        }

        Ok(PacketPayload { frames: frames })
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum PacketBody<P> {
    PublicReset,
    Regular {
        version: Option<u32>,
        packet_number: u64,
        payload: P,
    },
    VersionNegotiation {
        versions: Vec<u32>,
    },
}

#[derive(Clone, Debug, PartialEq)]
pub struct Packet<P> {
    // flags
    pub has_version: bool,
    pub public_reset: bool,
    pub key_phase: bool,
    pub has_connection_id: bool,
    pub packet_number_size: usize,
    pub multipath: bool,

    pub connection_id: Option<u64>,
    pub packet_body: PacketBody<P>,
}
<commit_msg>Remove type params<commit_after>use std::io;

use quic::QUIC_VERSION;
use quic::errors::{Error, Result};
use super::frames::Frame;

pub const FLAG_VERSION: u8 = 0b00000001;
pub const FLAG_PUBLIC_RESET: u8 = 0b00000010;
pub const FLAG_KEY_PHASE: u8 = 0b00000100;
pub const FLAG_CONNECTION_ID: u8 = 0b00001000;
pub const FLAG_PACKET_NUMBER_SIZE_1: u8 = 0b00010000;
pub const FLAG_PACKET_NUMBER_SIZE_2: u8 = 0b00100000;
pub const FLAG_MULTIPATH: u8 = 0b01000000;
pub const FLAG_UNUSED: u8 = 0b10000000;

#[derive(Clone, Debug, Default, PartialEq)]
pub struct PacketPayload {
    // TODO: add TLS stuff one day
    pub frames: Vec<Frame>,
}

impl PacketPayload {
    pub fn encode<W: io::Write>(&self, write: &mut W, packet_number_size: usize) -> Result<()> {
        assert!(!self.frames.is_empty());

        for frame in &self.frames {
            // TODO: pass correct last_frame
            frame.encode(write, packet_number_size, false)?;
        }

        Ok(())
    }

    pub fn decode<R: io::Read + io::Seek>(read: &mut R, packet_number_size: usize) -> Result<PacketPayload> {
        let mut frames = Vec::new();
        loop {
            match Frame::decode(read, packet_number_size) {
                Ok(frame) => {
                    frames.push(frame);
                },
                Err(Error::Io(ref e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
                    break;
                },
                Err(e) => {
                    return Err(e);
                }
            }
        }

        if frames.is_empty() {
            return Err(Error::Decoding(String::from("At least one frame expected")));
        }

        Ok(PacketPayload { frames: frames })
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum PacketBody {
    PublicReset,
    Regular {
        version: Option<u32>,
        packet_number: u64,
        payload: PacketPayload,
    },
    VersionNegotiation {
        versions: Vec<u32>,
    },
}

#[derive(Clone, Debug, PartialEq)]
pub struct Packet {
    // flags
    pub has_version: bool,
    pub public_reset: bool,
    pub key_phase: bool,
    pub has_connection_id: bool,
    pub packet_number_size: usize,
    pub multipath: bool,

    pub connection_id: Option<u64>,
    pub packet_body: PacketBody,
}
<|endoftext|>


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

extern "system" {

    #[link_name = "NeonSys_Primitive_Undefined"]
    pub fn undefined(out: &mut Local);

    #[link_name = "NeonSys_Primitive_Null"]
    pub fn null(out: &mut Local);

    #[link_name = "NeonSys_Primitive_Boolean"]
    pub fn boolean(out: &mut Local, b: bool);

    #[link_name = "NeonSys_Primitive_BooleanValue"]
    pub fn boolean_value(p: Local) -> bool;

    #[link_name = "NeonSys_Primitive_Integer"]
    pub fn integer(out: &mut Local, isolate: *mut Isolate, x: i32);

    #[link_name = "NeonSys_Primitive_IsUint32"]
    pub fn is_u32(p: Local) -> bool;

    #[link_name = "NeonSys_Primitive_IsInt32"]
    pub fn is_i32(p: Local) -> bool;

    #[link_name = "NeonSys_Primitive_IntegerValue"]
    pub fn integer_value(p: Local) -> i64;

    #[link_name = "NeonSys_Primitive_Number"]
    pub fn number(out: &mut Local, isolate: *mut Isolate, v: f64);

    #[link_name = "NeonSys_Primitive_NumberValue"]
    pub fn number_value(p: Local) -> f64;
}
<commit_msg>expand neon_sys::primitive mod documentation<commit_after>//! Facilities for working with primitive values.

use raw::{Local, Isolate};

extern "system" {

    /// Mutates the `out` argument provided to refer to the `v8::Undefined` object.
    #[link_name = "NeonSys_Primitive_Undefined"]
    pub fn undefined(out: &mut Local);

    /// Mutates the `out` argument provided to refer to the `v8::Null` object.
    #[link_name = "NeonSys_Primitive_Null"]
    pub fn null(out: &mut Local);

    /// Mutates the `out` argument provided to refer to the `v8::Boolean` object.
    #[link_name = "NeonSys_Primitive_Boolean"]
    pub fn boolean(out: &mut Local, b: bool);

    /// Gets the underlying value of a `v8::Boolean` object.
    #[link_name = "NeonSys_Primitive_BooleanValue"]
    pub fn boolean_value(p: Local) -> bool;

    /// Mutates the `out` argument provided to refer to a newly created `v8::Integer` object.
    #[link_name = "NeonSys_Primitive_Integer"]
    pub fn integer(out: &mut Local, isolate: *mut Isolate, x: i32);

    /// Indicates if the value is a 32-bit unsigned integer.
    #[link_name = "NeonSys_Primitive_IsUint32"]
    pub fn is_u32(p: Local) -> bool;

    /// Indicates if the value is a 32-bit signed integer.
    #[link_name = "NeonSys_Primitive_IsInt32"]
    pub fn is_i32(p: Local) -> bool;

    /// Gets the underlying value of a `v8::Integer` object.
    #[link_name = "NeonSys_Primitive_IntegerValue"]
    pub fn integer_value(p: Local) -> i64;

    /// Mutates the `out` argument provided to refer to a newly created `v8::Number` object.
    #[link_name = "NeonSys_Primitive_Number"]
    pub fn number(out: &mut Local, isolate: *mut Isolate, v: f64);

    /// Gets the underlying value of a `v8::Number` object.
    #[link_name = "NeonSys_Primitive_NumberValue"]
    pub fn number_value(p: Local) -> f64;
}
<|endoftext|>