<commit_before>use idna;
use std::fmt::{Display, Debug, Formatter, Result as FmtResult};
use std::net::Ipv4Addr;
use std::str::FromStr;
use serde::{Deserialize, Deserializer};
use serde::{Serialize, Serializer};

#[derive(Clone,PartialEq,Eq)]
pub struct EmailAddress {
    serialization: String,
    local_end: usize,
}

impl FromStr for EmailAddress {
    type Err = ();

    /// Parse and normalize an email address.
    /// https://github.com/portier/portier.github.io/blob/master/specs/Email-Normalization.md
    fn from_str(input: &str) -> Result<EmailAddress, ()> {
        let local_end = input.find('@').ok_or(())?;
        // Transform the local part to lowercase
        let local = input[..local_end].to_lowercase();
        if local == "" { return Err(()); }
        // Verify and normalize the domain
        let domain = idna::domain_to_ascii(&input[local_end + 1..]).map_err(|_| ())?;
        if domain == "" { return Err(()); }
        if domain.find(|c| matches!(c,
            '\0' | '\t' | '\n' | '\r' | ' ' | '#' | '%' | '/' | ':' | '?' | '@' | '[' | '\\' | ']'
        )).is_some() { return Err(()); }
        if domain.parse::<Ipv4Addr>().is_ok() { return Err(()); }
        Ok(EmailAddress::from_parts(&local, &domain))
    }
}

impl AsRef<str> for EmailAddress {
    /// Return the serialization of this email address.
    fn as_ref(&self) -> &str {
        &self.serialization
    }
}

impl Serialize for EmailAddress {
    /// Serialize this email address as a string.
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where S: Serializer {
        self.as_str().serialize(serializer)
    }
}

impl EmailAddress {
    /// Create an email address from trusted local and domain parts.
    fn from_parts(local: &str, domain: &str) -> EmailAddress {
        EmailAddress {
            serialization: format!("{}@{}", local, domain),
            local_end: local.len(),
        }
    }

    /// Create an EmailAddress from trusted input.
    ///
    /// The input is the already serialized form, preferably extracted from an
    /// EmailAddress parsed earlier.
    pub fn from_trusted(input: &str) -> EmailAddress {
        EmailAddress {
            serialization: input.to_owned(),
            local_end: input.find('@').expect("no @ found in input"),
        }
    }

    /// Deserialize implementation for trusted input.
    ///
    /// Because this assumes input is valid, it must be explicitely selected using
    /// `#[serde(deserialize_with = "EmailAddress::deserialize_trusted")]`
    pub fn deserialize_trusted<'de, D>(deserializer: D) -> Result<EmailAddress, D::Error>
            where D: Deserializer<'de> {
        <&str>::deserialize(deserializer).map(|s| EmailAddress::from_trusted(s))
    }

    /// Return the serialization.
    pub fn as_str(&self) -> &str {
        &self.serialization
    }

    /// Return the normalized local part.
    pub fn local(&self) -> &str {
        &self.serialization[..self.local_end]
    }

    /// Return the ASCII normalized domain.
    pub fn domain(&self) -> &str {
        &self.serialization[self.local_end + 1..]
    }

    /// Return the normalized local and domain parts as a tuple.
    pub fn parts(&self) -> (&str, &str) {
        (self.local(), self.domain())
    }

    /// Normalize a Google email address.
    ///
    /// This method can also be used to normalize G Suite addresses.
    pub fn normalize_google(&self) -> EmailAddress {
        let (local, domain) = self.parts();

        // Normalize googlemail.com to gmail.com
        let domain = match domain {
            "googlemail.com" => "gmail.com",
            domain => domain,
        };

        // Trim plus addresses
        let local = match self.local().find('+') {
            Some(pos) => &local[..pos],
            None => local,
        };

        // Ignore dots
        let local = local.replace(".", "");

        EmailAddress::from_parts(&local, domain)
    }
}

/// Display the serialization of this email address.
impl Display for EmailAddress {
    fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
        Display::fmt(&self.serialization, formatter)
    }
}

/// Debug the serialization of this email address.
impl Debug for EmailAddress {
    fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
        Debug::fmt(&self.serialization, formatter)
    }
}

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

    #[test]
    fn test_valid() {
        fn parse(input: &str, output: &str) {
            assert_eq!(
                input.parse::<EmailAddress>().unwrap(),
                EmailAddress::from_trusted(output)
            );
        }
        parse("example.foo+bar@example.com",
              "example.foo+bar@example.com");
        parse("EXAMPLE.FOO+BAR@EXAMPLE.COM",
              "example.foo+bar@example.com");
        parse("BJÖRN@göteborg.test",
              "björn@xn--gteborg-90a.test");
        parse("İⅢ@İⅢ.example",
              "i̇ⅲ@xn--iiii-qwc.example");
    }

    #[test]
    fn test_invalid() {
        fn parse(input: &str) {
            assert!(input.parse::<EmailAddress>().is_err());
        }
        parse("foo");
        parse("foo@");
        parse("@foo.example");
        parse("foo@127.0.0.1");
        parse("foo@[::1]");
    }

    #[test]
    fn test_google() {
        fn parse(input: &str, output: &str) {
            assert_eq!(
                input.parse::<EmailAddress>().unwrap().normalize_google(),
                EmailAddress::from_trusted(output)
            );
        }
        parse("example@gmail.com",
              "example@gmail.com");
        parse("example@googlemail.com",
              "example@gmail.com");
        parse("example.foo@gmail.com",
              "examplefoo@gmail.com");
        parse("example+bar@gmail.com",
              "example@gmail.com");
        parse("example.foo+bar@googlemail.com",
              "examplefoo@gmail.com");
        parse("EXAMPLE@GOOGLEMAIL.COM",
              "example@gmail.com");
        parse("EXAMPLE.FOO+BAR@GOOGLEMAIL.COM",
              "examplefoo@gmail.com");
    }
}
<commit_msg>Use the last occurence of @ in email normalization<commit_after>use idna;
use std::fmt::{Display, Debug, Formatter, Result as FmtResult};
use std::net::Ipv4Addr;
use std::str::FromStr;
use serde::{Deserialize, Deserializer};
use serde::{Serialize, Serializer};

#[derive(Clone,PartialEq,Eq)]
pub struct EmailAddress {
    serialization: String,
    local_end: usize,
}

impl FromStr for EmailAddress {
    type Err = ();

    /// Parse and normalize an email address.
    /// https://github.com/portier/portier.github.io/blob/master/specs/Email-Normalization.md
    fn from_str(input: &str) -> Result<EmailAddress, ()> {
        let local_end = input.rfind('@').ok_or(())?;
        // Transform the local part to lowercase
        let local = input[..local_end].to_lowercase();
        if local == "" { return Err(()); }
        // Verify and normalize the domain
        let domain = idna::domain_to_ascii(&input[local_end + 1..]).map_err(|_| ())?;
        if domain == "" { return Err(()); }
        if domain.find(|c| matches!(c,
            '\0' | '\t' | '\n' | '\r' | ' ' | '#' | '%' | '/' | ':' | '?' | '@' | '[' | '\\' | ']'
        )).is_some() { return Err(()); }
        if domain.parse::<Ipv4Addr>().is_ok() { return Err(()); }
        Ok(EmailAddress::from_parts(&local, &domain))
    }
}

impl AsRef<str> for EmailAddress {
    /// Return the serialization of this email address.
    fn as_ref(&self) -> &str {
        &self.serialization
    }
}

impl Serialize for EmailAddress {
    /// Serialize this email address as a string.
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where S: Serializer {
        self.as_str().serialize(serializer)
    }
}

impl EmailAddress {
    /// Create an email address from trusted local and domain parts.
    fn from_parts(local: &str, domain: &str) -> EmailAddress {
        EmailAddress {
            serialization: format!("{}@{}", local, domain),
            local_end: local.len(),
        }
    }

    /// Create an EmailAddress from trusted input.
    ///
    /// The input is the already serialized form, preferably extracted from an
    /// EmailAddress parsed earlier.
    pub fn from_trusted(input: &str) -> EmailAddress {
        EmailAddress {
            serialization: input.to_owned(),
            local_end: input.rfind('@').expect("no @ found in input"),
        }
    }

    /// Deserialize implementation for trusted input.
    ///
    /// Because this assumes input is valid, it must be explicitely selected using
    /// `#[serde(deserialize_with = "EmailAddress::deserialize_trusted")]`
    pub fn deserialize_trusted<'de, D>(deserializer: D) -> Result<EmailAddress, D::Error>
            where D: Deserializer<'de> {
        <&str>::deserialize(deserializer).map(|s| EmailAddress::from_trusted(s))
    }

    /// Return the serialization.
    pub fn as_str(&self) -> &str {
        &self.serialization
    }

    /// Return the normalized local part.
    pub fn local(&self) -> &str {
        &self.serialization[..self.local_end]
    }

    /// Return the ASCII normalized domain.
    pub fn domain(&self) -> &str {
        &self.serialization[self.local_end + 1..]
    }

    /// Return the normalized local and domain parts as a tuple.
    pub fn parts(&self) -> (&str, &str) {
        (self.local(), self.domain())
    }

    /// Normalize a Google email address.
    ///
    /// This method can also be used to normalize G Suite addresses.
    pub fn normalize_google(&self) -> EmailAddress {
        let (local, domain) = self.parts();

        // Normalize googlemail.com to gmail.com
        let domain = match domain {
            "googlemail.com" => "gmail.com",
            domain => domain,
        };

        // Trim plus addresses
        let local = match self.local().find('+') {
            Some(pos) => &local[..pos],
            None => local,
        };

        // Ignore dots
        let local = local.replace(".", "");

        EmailAddress::from_parts(&local, domain)
    }
}

/// Display the serialization of this email address.
impl Display for EmailAddress {
    fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
        Display::fmt(&self.serialization, formatter)
    }
}

/// Debug the serialization of this email address.
impl Debug for EmailAddress {
    fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
        Debug::fmt(&self.serialization, formatter)
    }
}

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

    #[test]
    fn test_valid() {
        fn parse(input: &str, output: &str) {
            assert_eq!(
                input.parse::<EmailAddress>().unwrap(),
                EmailAddress::from_trusted(output)
            );
        }
        parse("example.foo+bar@example.com",
              "example.foo+bar@example.com");
        parse("EXAMPLE.FOO+BAR@EXAMPLE.COM",
              "example.foo+bar@example.com");
        parse("BJÖRN@göteborg.test",
              "björn@xn--gteborg-90a.test");
        parse("İⅢ@İⅢ.example",
              "i̇ⅲ@xn--iiii-qwc.example");
        parse("\"ex@mple\"@example.com",
              "\"ex@mple\"@example.com");
    }

    #[test]
    fn test_invalid() {
        fn parse(input: &str) {
            assert!(input.parse::<EmailAddress>().is_err());
        }
        parse("foo");
        parse("foo@");
        parse("@foo.example");
        parse("foo@127.0.0.1");
        parse("foo@[::1]");
    }

    #[test]
    fn test_google() {
        fn parse(input: &str, output: &str) {
            assert_eq!(
                input.parse::<EmailAddress>().unwrap().normalize_google(),
                EmailAddress::from_trusted(output)
            );
        }
        parse("example@gmail.com",
              "example@gmail.com");
        parse("example@googlemail.com",
              "example@gmail.com");
        parse("example.foo@gmail.com",
              "examplefoo@gmail.com");
        parse("example+bar@gmail.com",
              "example@gmail.com");
        parse("example.foo+bar@googlemail.com",
              "examplefoo@gmail.com");
        parse("EXAMPLE@GOOGLEMAIL.COM",
              "example@gmail.com");
        parse("EXAMPLE.FOO+BAR@GOOGLEMAIL.COM",
              "examplefoo@gmail.com");
    }
}
<|endoftext|>


<commit_before>use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::node::{Node, NodeBorrow};
use crate::parsers::ParseValue;
use crate::rect::IRect;
use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use crate::xml::Attributes;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, FilterRender, Input, Primitive};

/// The `feMerge` filter primitive.
pub struct FeMerge {
    base: Primitive,
}

/// The `<feMergeNode>` element.
#[derive(Default)]
pub struct FeMergeNode {
    in_: Option<Input>,
}

impl Default for FeMerge {
    /// Constructs a new `Merge` with empty properties.
    #[inline]
    fn default() -> FeMerge {
        FeMerge {
            base: Primitive::new::<Self>(),
        }
    }
}

impl SetAttributes for FeMerge {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.set_attributes(attrs)
    }
}

impl SetAttributes for FeMergeNode {
    #[inline]
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.in_ = attrs
            .iter()
            .find(|(attr, _)| attr.expanded() == expanded_name!("", "in"))
            .and_then(|(attr, value)| attr.parse(value).ok());

        Ok(())
    }
}

impl Draw for FeMergeNode {}

impl FeMergeNode {
    fn render(
        &self,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
        bounds: IRect,
        output_surface: Option<SharedImageSurface>,
    ) -> Result<SharedImageSurface, FilterError> {
        let input = ctx.get_input(acquired_nodes, draw_ctx, self.in_.as_ref())?;

        if output_surface.is_none() {
            return Ok(input.surface().clone());
        }

        input
            .surface()
            .compose(&output_surface.unwrap(), bounds, cairo::Operator::Over)
            .map_err(FilterError::CairoError)
    }
}

impl FilterRender for FeMerge {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        // Compute the filter bounds, taking each child node's input into account.
        let mut bounds = self.base.get_bounds(ctx)?;
        for child in node.children().filter(|c| c.is_element()) {
            let elt = child.borrow_element();

            if elt.is_in_error() {
                return Err(FilterError::ChildNodeInError);
            }

            if let Element::FeMergeNode(ref merge_node) = *elt {
                let input = ctx.get_input(acquired_nodes, draw_ctx, merge_node.in_.as_ref())?;
                bounds = bounds.add_input(&input);
            }
        }

        let bounds = bounds.into_irect(ctx, draw_ctx);

        // Now merge them all.
        let mut output_surface = None;
        for child in node.children().filter(|c| c.is_element()) {
            if let Element::FeMergeNode(ref merge_node) = *child.borrow_element() {
                output_surface = merge_node
                    .render(ctx, acquired_nodes, draw_ctx, bounds, output_surface)
                    .ok();
            }
        }

        let surface = match output_surface {
            Some(s) => s,
            None => SharedImageSurface::empty(
                ctx.source_graphic().width(),
                ctx.source_graphic().height(),
                SurfaceType::AlphaOnly,
            )?,
        };

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput { surface, bounds },
        })
    }
}

impl FilterEffect for FeMerge {
    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}
<commit_msg>feMerge - extract the list of inputs to merge before doing the merging<commit_after>use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::node::{Node, NodeBorrow};
use crate::parsers::ParseValue;
use crate::rect::IRect;
use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use crate::xml::Attributes;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, FilterRender, Input, Primitive};

/// The `feMerge` filter primitive.
pub struct FeMerge {
    base: Primitive,
}

/// The `<feMergeNode>` element.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct FeMergeNode {
    in_: Option<Input>,
}

impl Default for FeMerge {
    /// Constructs a new `Merge` with empty properties.
    #[inline]
    fn default() -> FeMerge {
        FeMerge {
            base: Primitive::new::<Self>(),
        }
    }
}

impl SetAttributes for FeMerge {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.set_attributes(attrs)
    }
}

impl SetAttributes for FeMergeNode {
    #[inline]
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.in_ = attrs
            .iter()
            .find(|(attr, _)| attr.expanded() == expanded_name!("", "in"))
            .and_then(|(attr, value)| attr.parse(value).ok());

        Ok(())
    }
}

impl Draw for FeMergeNode {}

impl FeMergeNode {
    fn render(
        &self,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
        bounds: IRect,
        output_surface: Option<SharedImageSurface>,
    ) -> Result<SharedImageSurface, FilterError> {
        let input = ctx.get_input(acquired_nodes, draw_ctx, self.in_.as_ref())?;

        if output_surface.is_none() {
            return Ok(input.surface().clone());
        }

        input
            .surface()
            .compose(&output_surface.unwrap(), bounds, cairo::Operator::Over)
            .map_err(FilterError::CairoError)
    }
}

impl FilterRender for FeMerge {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let parameters = get_parameters(node)?;

        // Compute the filter bounds, taking each feMergeNode's input into account.
        let mut bounds = self.base.get_bounds(ctx)?;
        for merge_node in &parameters {
            let input = ctx.get_input(acquired_nodes, draw_ctx, merge_node.in_.as_ref())?;
            bounds = bounds.add_input(&input);
        }

        let bounds = bounds.into_irect(ctx, draw_ctx);

        // Now merge them all.
        let mut output_surface = None;
        for merge_node in &parameters {
            output_surface = merge_node
                .render(ctx, acquired_nodes, draw_ctx, bounds, output_surface)
                .ok();
        }

        let surface = match output_surface {
            Some(s) => s,
            None => SharedImageSurface::empty(
                ctx.source_graphic().width(),
                ctx.source_graphic().height(),
                SurfaceType::AlphaOnly,
            )?,
        };

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput { surface, bounds },
        })
    }
}

impl FilterEffect for FeMerge {
    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}

/// Takes a feMerge and walks its children to produce a list of feMergeNode arguments.
fn get_parameters(node: &Node) -> Result<Vec<FeMergeNode>, FilterError> {
    let mut merge_nodes = Vec::new();

    for child in node.children().filter(|c| c.is_element()) {
        let elt = child.borrow_element();

        if elt.is_in_error() {
            return Err(FilterError::ChildNodeInError);
        }

        if let Element::FeMergeNode(ref merge_node) = *elt {
            merge_nodes.push(merge_node.element_impl.clone());
        }
    }

    Ok(merge_nodes)
}

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

    #[test]
    fn extracts_parameters() {
        let document = Document::load_from_bytes(
            br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
  <filter id="filter">
    <feMerge id="merge">
      <feMergeNode in="SourceGraphic"/>
      <feMergeNode in="SourceAlpha"/>
    </feMerge>
  </filter>
</svg>
"#,
        );

        let merge = document.lookup_internal_node("merge").unwrap();

        let params = get_parameters(&merge).unwrap();

        assert_eq!(
            &params[..],
            vec![
                FeMergeNode {
                    in_: Some(Input::SourceGraphic)
                },
                FeMergeNode {
                    in_: Some(Input::SourceAlpha)
                },
            ]
        );
    }
}
<|endoftext|>


<commit_before>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! use futures::future::*;
//!
//! let future = ok::<_, bool>(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *shared1.wait().unwrap());
//! assert_eq!(6, *shared2.wait().unwrap());
//! ```

use {Future, Poll, Async};
use task::{self, Task};
use executor::{self, Notify, Spawn};

use std::{fmt, mem, ops};
use std::cell::UnsafeCell;
use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::collections::HashMap;

/// A future that is cloneable and can be polled in multiple threads.
/// Use `Future::shared()` method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F: Future> {
    inner: Arc<Inner<F>>,
    waiter: usize,
}

impl<F> fmt::Debug for Shared<F>
    where F: Future + fmt::Debug,
          F::Item: fmt::Debug,
          F::Error: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Shared")
            .field("inner", &self.inner)
            .field("waiter", &self.waiter)
            .finish()
    }
}

struct Inner<F: Future> {
    next_clone_id: AtomicUsize,
    future: UnsafeCell<Option<Spawn<F>>>,
    result: UnsafeCell<Option<Result<SharedItem<F::Item>, SharedError<F::Error>>>>,
    notifier: Arc<Notifier>,
}

struct Notifier {
    state: AtomicUsize,
    waiters: Mutex<HashMap<usize, Task>>,
}

const IDLE: usize = 0;
const POLLING: usize = 1;
const REPOLL: usize = 2;
const COMPLETE: usize = 3;
const POISONED: usize = 4;

pub fn new<F: Future>(future: F) -> Shared<F> {
    Shared {
        inner: Arc::new(Inner {
            next_clone_id: AtomicUsize::new(1),
            notifier: Arc::new(Notifier {
                state: AtomicUsize::new(IDLE),
                waiters: Mutex::new(HashMap::new()),
            }),
            future: UnsafeCell::new(Some(executor::spawn(future))),
            result: UnsafeCell::new(None),
        }),
        waiter: 0,
    }
}

impl<F> Shared<F> where F: Future {
    // TODO: make this private
    #[deprecated(since = "0.1.12", note = "use `Future::shared` instead")]
    #[cfg(feature = "with-deprecated")]
    #[doc(hidden)]
    pub fn new(future: F) -> Self {
        new(future)
    }

    /// If any clone of this `Shared` has completed execution, returns its result immediately
    /// without blocking. Otherwise, returns None without triggering the work represented by
    /// this `Shared`.
    pub fn peek(&self) -> Option<Result<SharedItem<F::Item>, SharedError<F::Error>>> {
        match self.inner.notifier.state.load(SeqCst) {
            COMPLETE => {
                Some(unsafe { self.clone_result() })
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => None,
        }
    }

    fn set_waiter(&mut self) {
        let mut waiters = self.inner.notifier.waiters.lock().unwrap();
        waiters.insert(self.waiter, task::current());
    }

    unsafe fn clone_result(&self) -> Result<SharedItem<F::Item>, SharedError<F::Error>> {
        match *self.inner.result.get() {
            Some(Ok(ref item)) => Ok(SharedItem { item: item.item.clone() }),
            Some(Err(ref e)) => Err(SharedError { error: e.error.clone() }),
            _ => unreachable!(),
        }
    }

    fn complete(&self) {
        unsafe { *self.inner.future.get() = None };
        self.inner.notifier.state.store(COMPLETE, SeqCst);
        self.inner.notifier.notify(0);
    }
}

impl<F> Future for Shared<F>
    where F: Future
{
    type Item = SharedItem<F::Item>;
    type Error = SharedError<F::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.set_waiter();

        match self.inner.notifier.state.compare_and_swap(IDLE, POLLING, SeqCst) {
            IDLE => {
                // Lock acquired, fall through
            }
            POLLING | REPOLL => {
                // Another task is currently polling, at this point we just want
                // to ensure that our task handle is currently registered

                return Ok(Async::NotReady);
            }
            COMPLETE => {
                return unsafe { self.clone_result().map(Async::Ready) };
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => unreachable!(),
        }

        loop {
            struct Reset<'a>(&'a AtomicUsize);

            impl<'a> Drop for Reset<'a> {
                fn drop(&mut self) {
                    use std::thread;

                    if thread::panicking() {
                        self.0.store(POISONED, SeqCst);
                    }
                }
            }

            let _reset = Reset(&self.inner.notifier.state);

            // Poll the future
            let res = unsafe {
                (*self.inner.future.get()).as_mut().unwrap()
                    .poll_future_notify(&self.inner.notifier, 0)
            };
            match res {
                Ok(Async::NotReady) => {
                    // Not ready, try to release the handle
                    match self.inner.notifier.state.compare_and_swap(POLLING, IDLE, SeqCst) {
                        POLLING => {
                            // Success
                            return Ok(Async::NotReady);
                        }
                        REPOLL => {
                            // Gotta poll again!
                            let prev = self.inner.notifier.state.swap(POLLING, SeqCst);
                            assert_eq!(prev, REPOLL);
                        }
                        _ => unreachable!(),
                    }

                }
                Ok(Async::Ready(i)) => {
                    unsafe {
                        (*self.inner.result.get()) = Some(Ok(SharedItem { item: Arc::new(i) }));
                    }

                    break;
                }
                Err(e) => {
                    unsafe {
                        (*self.inner.result.get()) = Some(Err(SharedError { error: Arc::new(e) }));
                    }

                    break;
                }
            }
        }

        self.complete();
        unsafe { self.clone_result().map(Async::Ready) }
    }
}

impl<F> Clone for Shared<F> where F: Future {
    fn clone(&self) -> Self {
        let next_clone_id = self.inner.next_clone_id.fetch_add(1, SeqCst);

        Shared {
            inner: self.inner.clone(),
            waiter: next_clone_id,
        }
    }
}

impl<F> Drop for Shared<F> where F: Future {
    fn drop(&mut self) {
        let mut waiters = self.inner.notifier.waiters.lock().unwrap();
        waiters.remove(&self.waiter);
    }
}

impl Notify for Notifier {
    fn notify(&self, _id: usize) {
        self.state.compare_and_swap(POLLING, REPOLL, SeqCst);

        let waiters = mem::replace(&mut *self.waiters.lock().unwrap(), HashMap::new());

        for (_, waiter) in waiters {
            waiter.notify();
        }
    }
}

unsafe impl<F: Future> Sync for Inner<F> {}
unsafe impl<F: Future> Send for Inner<F> {}

impl<F> fmt::Debug for Inner<F>
    where F: Future + fmt::Debug,
          F::Item: fmt::Debug,
          F::Error: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Inner")
            .finish()
    }
}

/// A wrapped item of the original future that is cloneable and implements Deref
/// for ease of use.
#[derive(Clone, Debug)]
pub struct SharedItem<T> {
    item: Arc<T>,
}

impl<T> ops::Deref for SharedItem<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.item.as_ref()
    }
}

/// A wrapped error of the original future that is cloneable and implements Deref
/// for ease of use.
#[derive(Clone, Debug)]
pub struct SharedError<E> {
    error: Arc<E>,
}

impl<E> ops::Deref for SharedError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.error.as_ref()
    }
}
<commit_msg>Implement `Error` and `Display` for `SharedError` when possible<commit_after>//! Definition of the Shared combinator, a future that is cloneable,
//! and can be polled in multiple threads.
//!
//! # Examples
//!
//! ```
//! use futures::future::*;
//!
//! let future = ok::<_, bool>(6);
//! let shared1 = future.shared();
//! let shared2 = shared1.clone();
//! assert_eq!(6, *shared1.wait().unwrap());
//! assert_eq!(6, *shared2.wait().unwrap());
//! ```

use {Future, Poll, Async};
use task::{self, Task};
use executor::{self, Notify, Spawn};

use std::{error, fmt, mem, ops};
use std::cell::UnsafeCell;
use std::sync::{Arc, Mutex};
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;
use std::collections::HashMap;

/// A future that is cloneable and can be polled in multiple threads.
/// Use `Future::shared()` method to convert any future into a `Shared` future.
#[must_use = "futures do nothing unless polled"]
pub struct Shared<F: Future> {
    inner: Arc<Inner<F>>,
    waiter: usize,
}

impl<F> fmt::Debug for Shared<F>
    where F: Future + fmt::Debug,
          F::Item: fmt::Debug,
          F::Error: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Shared")
            .field("inner", &self.inner)
            .field("waiter", &self.waiter)
            .finish()
    }
}

struct Inner<F: Future> {
    next_clone_id: AtomicUsize,
    future: UnsafeCell<Option<Spawn<F>>>,
    result: UnsafeCell<Option<Result<SharedItem<F::Item>, SharedError<F::Error>>>>,
    notifier: Arc<Notifier>,
}

struct Notifier {
    state: AtomicUsize,
    waiters: Mutex<HashMap<usize, Task>>,
}

const IDLE: usize = 0;
const POLLING: usize = 1;
const REPOLL: usize = 2;
const COMPLETE: usize = 3;
const POISONED: usize = 4;

pub fn new<F: Future>(future: F) -> Shared<F> {
    Shared {
        inner: Arc::new(Inner {
            next_clone_id: AtomicUsize::new(1),
            notifier: Arc::new(Notifier {
                state: AtomicUsize::new(IDLE),
                waiters: Mutex::new(HashMap::new()),
            }),
            future: UnsafeCell::new(Some(executor::spawn(future))),
            result: UnsafeCell::new(None),
        }),
        waiter: 0,
    }
}

impl<F> Shared<F> where F: Future {
    // TODO: make this private
    #[deprecated(since = "0.1.12", note = "use `Future::shared` instead")]
    #[cfg(feature = "with-deprecated")]
    #[doc(hidden)]
    pub fn new(future: F) -> Self {
        new(future)
    }

    /// If any clone of this `Shared` has completed execution, returns its result immediately
    /// without blocking. Otherwise, returns None without triggering the work represented by
    /// this `Shared`.
    pub fn peek(&self) -> Option<Result<SharedItem<F::Item>, SharedError<F::Error>>> {
        match self.inner.notifier.state.load(SeqCst) {
            COMPLETE => {
                Some(unsafe { self.clone_result() })
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => None,
        }
    }

    fn set_waiter(&mut self) {
        let mut waiters = self.inner.notifier.waiters.lock().unwrap();
        waiters.insert(self.waiter, task::current());
    }

    unsafe fn clone_result(&self) -> Result<SharedItem<F::Item>, SharedError<F::Error>> {
        match *self.inner.result.get() {
            Some(Ok(ref item)) => Ok(SharedItem { item: item.item.clone() }),
            Some(Err(ref e)) => Err(SharedError { error: e.error.clone() }),
            _ => unreachable!(),
        }
    }

    fn complete(&self) {
        unsafe { *self.inner.future.get() = None };
        self.inner.notifier.state.store(COMPLETE, SeqCst);
        self.inner.notifier.notify(0);
    }
}

impl<F> Future for Shared<F>
    where F: Future
{
    type Item = SharedItem<F::Item>;
    type Error = SharedError<F::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.set_waiter();

        match self.inner.notifier.state.compare_and_swap(IDLE, POLLING, SeqCst) {
            IDLE => {
                // Lock acquired, fall through
            }
            POLLING | REPOLL => {
                // Another task is currently polling, at this point we just want
                // to ensure that our task handle is currently registered

                return Ok(Async::NotReady);
            }
            COMPLETE => {
                return unsafe { self.clone_result().map(Async::Ready) };
            }
            POISONED => panic!("inner future panicked during poll"),
            _ => unreachable!(),
        }

        loop {
            struct Reset<'a>(&'a AtomicUsize);

            impl<'a> Drop for Reset<'a> {
                fn drop(&mut self) {
                    use std::thread;

                    if thread::panicking() {
                        self.0.store(POISONED, SeqCst);
                    }
                }
            }

            let _reset = Reset(&self.inner.notifier.state);

            // Poll the future
            let res = unsafe {
                (*self.inner.future.get()).as_mut().unwrap()
                    .poll_future_notify(&self.inner.notifier, 0)
            };
            match res {
                Ok(Async::NotReady) => {
                    // Not ready, try to release the handle
                    match self.inner.notifier.state.compare_and_swap(POLLING, IDLE, SeqCst) {
                        POLLING => {
                            // Success
                            return Ok(Async::NotReady);
                        }
                        REPOLL => {
                            // Gotta poll again!
                            let prev = self.inner.notifier.state.swap(POLLING, SeqCst);
                            assert_eq!(prev, REPOLL);
                        }
                        _ => unreachable!(),
                    }

                }
                Ok(Async::Ready(i)) => {
                    unsafe {
                        (*self.inner.result.get()) = Some(Ok(SharedItem { item: Arc::new(i) }));
                    }

                    break;
                }
                Err(e) => {
                    unsafe {
                        (*self.inner.result.get()) = Some(Err(SharedError { error: Arc::new(e) }));
                    }

                    break;
                }
            }
        }

        self.complete();
        unsafe { self.clone_result().map(Async::Ready) }
    }
}

impl<F> Clone for Shared<F> where F: Future {
    fn clone(&self) -> Self {
        let next_clone_id = self.inner.next_clone_id.fetch_add(1, SeqCst);

        Shared {
            inner: self.inner.clone(),
            waiter: next_clone_id,
        }
    }
}

impl<F> Drop for Shared<F> where F: Future {
    fn drop(&mut self) {
        let mut waiters = self.inner.notifier.waiters.lock().unwrap();
        waiters.remove(&self.waiter);
    }
}

impl Notify for Notifier {
    fn notify(&self, _id: usize) {
        self.state.compare_and_swap(POLLING, REPOLL, SeqCst);

        let waiters = mem::replace(&mut *self.waiters.lock().unwrap(), HashMap::new());

        for (_, waiter) in waiters {
            waiter.notify();
        }
    }
}

unsafe impl<F: Future> Sync for Inner<F> {}
unsafe impl<F: Future> Send for Inner<F> {}

impl<F> fmt::Debug for Inner<F>
    where F: Future + fmt::Debug,
          F::Item: fmt::Debug,
          F::Error: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Inner")
            .finish()
    }
}

/// A wrapped item of the original future that is cloneable and implements Deref
/// for ease of use.
#[derive(Clone, Debug)]
pub struct SharedItem<T> {
    item: Arc<T>,
}

impl<T> ops::Deref for SharedItem<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.item.as_ref()
    }
}

/// A wrapped error of the original future that is cloneable and implements Deref
/// for ease of use.
#[derive(Clone, Debug)]
pub struct SharedError<E> {
    error: Arc<E>,
}

impl<E> ops::Deref for SharedError<E> {
    type Target = E;

    fn deref(&self) -> &E {
        &self.error.as_ref()
    }
}

impl<E> fmt::Display for SharedError<E>
    where E: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.error.fmt(f)
    }
}

impl<E> error::Error for SharedError<E>
    where E: error::Error,
{
    fn description(&self) -> &str {
        self.error.description()
    }

    fn cause(&self) -> Option<&error::Error> {
        self.error.cause()
    }
}
<|endoftext|>


<commit_before><commit_msg>y2aa: Use f32 in preallocated image buffer<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// Prevent warning when casting u32 as i64
#![allow(clippy::cast_lossless)]
#![allow(dead_code)]

use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{self, Receiver, Sender};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use libc::{
    self, c_long, sched_param, time_t, timespec, CLOCK_MONOTONIC, PR_SET_TIMERSLACK, SCHED_RR,
};

use super::{Error, GpioState, Result};

// Only call sleep_ns() if we have enough time remaining
const SLEEP_THRESHOLD: i64 = 250_000;
// Reserve some time for busy waiting
const BUSYWAIT_MAX: i64 = 200_000;
// Subtract from the remaining busy wait time to account for get_time_ns() overhead
const BUSYWAIT_REMAINDER: i64 = 100;

static mut MSG_WAITING: AtomicBool = AtomicBool::new(false);

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
enum Msg {
    Reconfigure(Duration, Duration),
    Stop,
}

#[derive(Debug)]
pub(crate) struct SoftPwm {
    pwm_thread: Option<thread::JoinHandle<Result<()>>>,
    sender: Sender<Msg>,
}

impl SoftPwm {
    pub(crate) fn new(
        pin: u8,
        gpio_state: Arc<GpioState>,
        period: Duration,
        pulse_width: Duration,
    ) -> SoftPwm {
        let (sender, receiver): (Sender<Msg>, Receiver<Msg>) = mpsc::channel();

        let pwm_thread = thread::spawn(move || -> Result<()> {
            // Set the scheduling policy to real-time round robin at the highest priority. This
            // will silently fail if we're not running as root.
            #[cfg(target_env = "gnu")]
            let params = sched_param {
                sched_priority: unsafe { libc::sched_get_priority_max(SCHED_RR) },
            };

            #[cfg(target_env = "musl")]
            let params = sched_param {
                sched_priority: unsafe { libc::sched_get_priority_max(SCHED_RR) },
                sched_ss_low_priority: 0,
                sched_ss_repl_period: timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                },
                sched_ss_init_budget: timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                },
                sched_ss_max_repl: 0,
            };

            unsafe {
                libc::sched_setscheduler(0, SCHED_RR, &params);
            }

            // Set timer slack to 1 ns (default = 50 µs). This is only relevant if we're unable
            // to set a real-time scheduling policy.
            unsafe {
                libc::prctl(PR_SET_TIMERSLACK, 1);
            }

            let mut period_ns =
                (period.as_secs() as i64 * 1_000_000_000) + period.subsec_nanos() as i64;

            let mut pulse_width_ns =
                (pulse_width.as_secs() as i64 * 1_000_000_000) + pulse_width.subsec_nanos() as i64;

            let mut start_ns = get_time_ns();

            loop {
                // PWM active
                if pulse_width_ns > 0 {
                    gpio_state.gpio_mem.set_high(pin);
                }

                // Sleep if we have enough time remaining, while reserving some time
                // for busy waiting to compensate for sleep taking longer than needed.
                if pulse_width_ns >= SLEEP_THRESHOLD {
                    sleep_ns(pulse_width_ns - BUSYWAIT_MAX);
                }

                // Busy-wait for the remaining active time, minus BUSYWAIT_REMAINDER
                // to account for get_time_ns() overhead
                loop {
                    if (pulse_width_ns - (get_time_ns() - start_ns)) <= BUSYWAIT_REMAINDER {
                        break;
                    }
                }

                // PWM inactive
                gpio_state.gpio_mem.set_low(pin);

                // This is slightly faster than directly checking try_recv()
                if unsafe { MSG_WAITING.compare_and_swap(true, false, Ordering::AcqRel) } {
                    while let Ok(msg) = receiver.try_recv() {
                        match msg {
                            Msg::Reconfigure(period, pulse_width) => {
                                // Reconfigure period and pulse width
                                pulse_width_ns = (pulse_width.as_secs() as i64 * 1_000_000_000)
                                    + pulse_width.subsec_nanos() as i64;

                                period_ns = (period.as_secs() as i64 * 1_000_000_000)
                                    + period.subsec_nanos() as i64;

                                if pulse_width_ns > period_ns {
                                    pulse_width_ns = period_ns;
                                }
                            }
                            Msg::Stop => {
                                // The main thread asked us to stop
                                return Ok(());
                            }
                        }
                    }
                }

                let remaining_ns = period_ns - (get_time_ns() - start_ns);

                // Sleep if we have enough time remaining, while reserving some time
                // for busy waiting to compensate for sleep taking longer than needed.
                if remaining_ns >= SLEEP_THRESHOLD {
                    sleep_ns(remaining_ns - BUSYWAIT_MAX);
                }

                // Busy-wait for the remaining inactive time, minus BUSYWAIT_REMAINDER
                // to account for get_time_ns() overhead
                loop {
                    let current_ns = get_time_ns();
                    if (period_ns - (current_ns - start_ns)) <= BUSYWAIT_REMAINDER {
                        start_ns = current_ns;
                        break;
                    }
                }
            }
        });

        SoftPwm {
            pwm_thread: Some(pwm_thread),
            sender,
        }
    }

    pub(crate) fn reconfigure(&mut self, period: Duration, pulse_width: Duration) {
        let _ = self.sender.send(Msg::Reconfigure(period, pulse_width));
        unsafe {
            MSG_WAITING.store(true, Ordering::Release);
        }
    }

    pub(crate) fn stop(&mut self) -> Result<()> {
        let _ = self.sender.send(Msg::Stop);
        unsafe {
            MSG_WAITING.store(true, Ordering::Release);
        }

        if let Some(pwm_thread) = self.pwm_thread.take() {
            match pwm_thread.join() {
                Ok(r) => return r,
                Err(_) => return Err(Error::ThreadPanic),
            }
        }

        Ok(())
    }
}

impl Drop for SoftPwm {
    fn drop(&mut self) {
        // Don't wait for the pwm thread to exit if the main thread is panicking,
        // because we could potentially block indefinitely while unwinding if the
        // pwm thread doesn't respond to the Stop message for some reason.
        if !thread::panicking() {
            let _ = self.stop();
        }
    }
}

// Required because Sender isn't Sync. Implementing Sync for SoftPwm is
// safe because all usage of Sender::send() is locked behind &mut self.
unsafe impl Sync for SoftPwm {}

#[inline(always)]
fn get_time_ns() -> i64 {
    let mut ts = timespec {
        tv_sec: 0,
        tv_nsec: 0,
    };

    unsafe {
        libc::clock_gettime(CLOCK_MONOTONIC, &mut ts);
    }

    (ts.tv_sec as i64 * 1_000_000_000) + ts.tv_nsec as i64
}

#[inline(always)]
fn sleep_ns(ns: i64) {
    let ts = timespec {
        tv_sec: (ns / 1_000_000_000) as time_t,
        tv_nsec: (ns % 1_000_000_000) as c_long,
    };

    unsafe {
        libc::clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, ptr::null_mut());
    }
}
<commit_msg>Remove MSG_WAITING flag.<commit_after>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// Prevent warning when casting u32 as i64
#![allow(clippy::cast_lossless)]
#![allow(dead_code)]

use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{self, Receiver, Sender};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use libc::{
    self, c_long, sched_param, time_t, timespec, CLOCK_MONOTONIC, PR_SET_TIMERSLACK, SCHED_RR,
};

use super::{Error, GpioState, Result};

// Only call sleep_ns() if we have enough time remaining
const SLEEP_THRESHOLD: i64 = 250_000;
// Reserve some time for busy waiting
const BUSYWAIT_MAX: i64 = 200_000;
// Subtract from the remaining busy wait time to account for get_time_ns() overhead
const BUSYWAIT_REMAINDER: i64 = 100;

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
enum Msg {
    Reconfigure(Duration, Duration),
    Stop,
}

#[derive(Debug)]
pub(crate) struct SoftPwm {
    pwm_thread: Option<thread::JoinHandle<Result<()>>>,
    sender: Sender<Msg>,
}

impl SoftPwm {
    pub(crate) fn new(
        pin: u8,
        gpio_state: Arc<GpioState>,
        period: Duration,
        pulse_width: Duration,
    ) -> SoftPwm {
        let (sender, receiver): (Sender<Msg>, Receiver<Msg>) = mpsc::channel();

        let pwm_thread = thread::spawn(move || -> Result<()> {
            // Set the scheduling policy to real-time round robin at the highest priority. This
            // will silently fail if we're not running as root.
            #[cfg(target_env = "gnu")]
            let params = sched_param {
                sched_priority: unsafe { libc::sched_get_priority_max(SCHED_RR) },
            };

            #[cfg(target_env = "musl")]
            let params = sched_param {
                sched_priority: unsafe { libc::sched_get_priority_max(SCHED_RR) },
                sched_ss_low_priority: 0,
                sched_ss_repl_period: timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                },
                sched_ss_init_budget: timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                },
                sched_ss_max_repl: 0,
            };

            unsafe {
                libc::sched_setscheduler(0, SCHED_RR, &params);
            }

            // Set timer slack to 1 ns (default = 50 µs). This is only relevant if we're unable
            // to set a real-time scheduling policy.
            unsafe {
                libc::prctl(PR_SET_TIMERSLACK, 1);
            }

            let mut period_ns =
                (period.as_secs() as i64 * 1_000_000_000) + period.subsec_nanos() as i64;

            let mut pulse_width_ns =
                (pulse_width.as_secs() as i64 * 1_000_000_000) + pulse_width.subsec_nanos() as i64;

            let mut start_ns = get_time_ns();

            loop {
                // PWM active
                if pulse_width_ns > 0 {
                    gpio_state.gpio_mem.set_high(pin);
                }

                // Sleep if we have enough time remaining, while reserving some time
                // for busy waiting to compensate for sleep taking longer than needed.
                if pulse_width_ns >= SLEEP_THRESHOLD {
                    sleep_ns(pulse_width_ns - BUSYWAIT_MAX);
                }

                // Busy-wait for the remaining active time, minus BUSYWAIT_REMAINDER
                // to account for get_time_ns() overhead
                loop {
                    if (pulse_width_ns - (get_time_ns() - start_ns)) <= BUSYWAIT_REMAINDER {
                        break;
                    }
                }

                // PWM inactive
                gpio_state.gpio_mem.set_low(pin);

                while let Ok(msg) = receiver.try_recv() {
                    match msg {
                        Msg::Reconfigure(period, pulse_width) => {
                            // Reconfigure period and pulse width
                            pulse_width_ns = (pulse_width.as_secs() as i64 * 1_000_000_000)
                                + pulse_width.subsec_nanos() as i64;

                            period_ns = (period.as_secs() as i64 * 1_000_000_000)
                                + period.subsec_nanos() as i64;

                            if pulse_width_ns > period_ns {
                                pulse_width_ns = period_ns;
                            }
                        }
                        Msg::Stop => {
                            // The main thread asked us to stop
                            return Ok(());
                        }
                    }
                }

                let remaining_ns = period_ns - (get_time_ns() - start_ns);

                // Sleep if we have enough time remaining, while reserving some time
                // for busy waiting to compensate for sleep taking longer than needed.
                if remaining_ns >= SLEEP_THRESHOLD {
                    sleep_ns(remaining_ns - BUSYWAIT_MAX);
                }

                // Busy-wait for the remaining inactive time, minus BUSYWAIT_REMAINDER
                // to account for get_time_ns() overhead
                loop {
                    let current_ns = get_time_ns();
                    if (period_ns - (current_ns - start_ns)) <= BUSYWAIT_REMAINDER {
                        start_ns = current_ns;
                        break;
                    }
                }
            }
        });

        SoftPwm {
            pwm_thread: Some(pwm_thread),
            sender,
        }
    }

    pub(crate) fn reconfigure(&mut self, period: Duration, pulse_width: Duration) {
        let _ = self.sender.send(Msg::Reconfigure(period, pulse_width));
    }

    pub(crate) fn stop(&mut self) -> Result<()> {
        let _ = self.sender.send(Msg::Stop);
        if let Some(pwm_thread) = self.pwm_thread.take() {
            match pwm_thread.join() {
                Ok(r) => return r,
                Err(_) => return Err(Error::ThreadPanic),
            }
        }

        Ok(())
    }
}

impl Drop for SoftPwm {
    fn drop(&mut self) {
        // Don't wait for the pwm thread to exit if the main thread is panicking,
        // because we could potentially block indefinitely while unwinding if the
        // pwm thread doesn't respond to the Stop message for some reason.
        if !thread::panicking() {
            let _ = self.stop();
        }
    }
}

// Required because Sender isn't Sync. Implementing Sync for SoftPwm is
// safe because all usage of Sender::send() is locked behind &mut self.
unsafe impl Sync for SoftPwm {}

#[inline(always)]
fn get_time_ns() -> i64 {
    let mut ts = timespec {
        tv_sec: 0,
        tv_nsec: 0,
    };

    unsafe {
        libc::clock_gettime(CLOCK_MONOTONIC, &mut ts);
    }

    (ts.tv_sec as i64 * 1_000_000_000) + ts.tv_nsec as i64
}

#[inline(always)]
fn sleep_ns(ns: i64) {
    let ts = timespec {
        tv_sec: (ns / 1_000_000_000) as time_t,
        tv_nsec: (ns % 1_000_000_000) as c_long,
    };

    unsafe {
        libc::clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, ptr::null_mut());
    }
}
<|endoftext|>


<commit_before>extern crate json;

use std::error::Error;
use std::fs::File;
use std::io;
use std::io::Error as IoError;
use std::io::ErrorKind::Other as ReadError;
use std::io::prelude::*;
use std::path::Path;

use string_gen::keywords::*;
use raw_code::{RawCode, CodeData, generate_raw};

pub fn process_json_file(filename: &str) -> io::Result<RawCode> {
    let path = Path::new(&filename);
    let mut file = match File::open(&path) {
        Ok(file) => file,
        Err(why) => {
            return Err(IoError::new(ReadError, format!("Failed to open {} for reading: {}",
                                                       path.display(), why.description())));
        }
    };

    let mut json_data = String::new();
    try!(file.read_to_string(&mut json_data));

    process_json_str(json_data.as_str())
}

pub fn process_json_str(json_str: &str) -> io::Result<RawCode> {
    let mut code_data   = Vec::<CodeData>::new();
    let mut config_tags = Vec::<CodeData>::new();
    let mut config_data = Vec::<CodeData>::new();

    let parsed_json = json::parse(json_str).unwrap();
    for i in parsed_json.entries() {
        if i.0 == CONFIG {
            if i.1.len() == 0 {
                let cfg_file = String::from(i.1.as_str().unwrap());
                config_tags.push((String::from(i.0), vec![(String::from(NAME), cfg_file)], 0));
            }
            else {
                let mut filename_vec = Vec::<(String, String)>::new();
                for e in i.1.entries() {
                    let cfg_file = String::from(e.1.as_str().unwrap());
                    filename_vec.push((String::from(NAME), cfg_file));
                }
                config_tags.push((String::from(i.0), filename_vec, 0));
            }
        }
        else {
            process(&i, &mut code_data, 0);
        }
    }

    // process configs, if found
    let mut json_cfg = String::new();
    for c in config_tags.iter() {
        for a in c.1.iter() {
            if a.0 == NAME {
                let path = Path::new(&a.1);
                let mut file = match File::open(&path) {
                    Ok(file) => file,
                    Err(why) => {
                        return Err(IoError::new(ReadError,format!("Failed to open {} for reading: {}",
                                                                  path.display(), why.description())));
                    }
                };
                json_cfg.clear();
                try!(file.read_to_string(&mut json_cfg));

                let parsed_json = json::parse(json_cfg.as_str()).unwrap();
                for i in parsed_json.entries() {
                    process(&i, &mut config_data, 0);
                }
            }
        }
    }

    Ok(generate_raw(&code_data, &config_data))
}

fn process(json: &(&str, &json::JsonValue), data: &mut Vec<CodeData>, depth: u8) {
    data.push((String::from(json.0), Vec::<(String, String)>::new(), depth));
    let mut attribs = Vec::<(String, String)>::new();
    let idx = data.len() - 1;

    for i in json.1.entries() {
        if i.1.entries().count() == 0 && i.1.members().count() == 0 {
            if ATTRIB_ARRAY.contains(&i.0) {
                attribs.push((String::from(i.0), String::from(i.1.as_str().unwrap())));
            }
            else {
                // simplified JSON: unknown keywords will be identified as a type->name pair
                attribs.push((String::from(NAME), String::from(i.1.as_str().unwrap())));
                attribs.push((String::from(TYPE), String::from(i.0)));
            }
        }
        for j in i.1.members() {
            process(&(&i.0, &j), data, depth+1);
        }
        if i.1.entries().count() > 0 {
            process(&i, data, depth+1);
        }
    }

    for j in json.1.members() {
        process(&(&json.0, &j), data, depth);
    }

    // assign collected attributes to element
    data[idx].1 = attribs;

    // if element is only a list of members, remove it from the list
    if json.1.entries().count() == 0 && json.1.members().count() > 0 {
        data.remove(idx);
    }
}
<commit_msg>iterate over members, not entries<commit_after>extern crate json;

use std::error::Error;
use std::fs::File;
use std::io;
use std::io::Error as IoError;
use std::io::ErrorKind::Other as ReadError;
use std::io::prelude::*;
use std::path::Path;

use string_gen::keywords::*;
use raw_code::{RawCode, CodeData, generate_raw};

pub fn process_json_file(filename: &str) -> io::Result<RawCode> {
    let path = Path::new(&filename);
    let mut file = match File::open(&path) {
        Ok(file) => file,
        Err(why) => {
            return Err(IoError::new(ReadError, format!("Failed to open {} for reading: {}",
                                                       path.display(), why.description())));
        }
    };

    let mut json_data = String::new();
    try!(file.read_to_string(&mut json_data));

    process_json_str(json_data.as_str())
}

pub fn process_json_str(json_str: &str) -> io::Result<RawCode> {
    let mut code_data   = Vec::<CodeData>::new();
    let mut config_tags = Vec::<CodeData>::new();
    let mut config_data = Vec::<CodeData>::new();

    let parsed_json = json::parse(json_str).unwrap();
    for i in parsed_json.entries() {
        if i.0 == CONFIG {
            if i.1.len() == 0 {
                let cfg_file = String::from(i.1.as_str().unwrap());
                config_tags.push((String::from(i.0), vec![(String::from(NAME), cfg_file)], 0));
            }
            else {
                let mut filename_vec = Vec::<(String, String)>::new();
                for e in i.1.members() {
                    let cfg_file = String::from(e.as_str().unwrap());
                    filename_vec.push((String::from(NAME), cfg_file));
                }
                config_tags.push((String::from(i.0), filename_vec, 0));
            }
        }
        else {
            process(&i, &mut code_data, 0);
        }
    }

    // process configs, if found
    let mut json_cfg = String::new();
    for c in config_tags.iter() {
        for a in c.1.iter() {
            if a.0 == NAME {
                let path = Path::new(&a.1);
                let mut file = match File::open(&path) {
                    Ok(file) => file,
                    Err(why) => {
                        return Err(IoError::new(ReadError,format!("Failed to open {} for reading: {}",
                                                                  path.display(), why.description())));
                    }
                };
                json_cfg.clear();
                try!(file.read_to_string(&mut json_cfg));

                let parsed_json = json::parse(json_cfg.as_str()).unwrap();
                for i in parsed_json.entries() {
                    process(&i, &mut config_data, 0);
                }
            }
        }
    }

    Ok(generate_raw(&code_data, &config_data))
}

fn process(json: &(&str, &json::JsonValue), data: &mut Vec<CodeData>, depth: u8) {
    data.push((String::from(json.0), Vec::<(String, String)>::new(), depth));
    let mut attribs = Vec::<(String, String)>::new();
    let idx = data.len() - 1;

    for i in json.1.entries() {
        if i.1.entries().count() == 0 && i.1.members().count() == 0 {
            if ATTRIB_ARRAY.contains(&i.0) {
                attribs.push((String::from(i.0), String::from(i.1.as_str().unwrap())));
            }
            else {
                // simplified JSON: unknown keywords will be identified as a type->name pair
                attribs.push((String::from(NAME), String::from(i.1.as_str().unwrap())));
                attribs.push((String::from(TYPE), String::from(i.0)));
            }
        }
        for j in i.1.members() {
            process(&(&i.0, &j), data, depth+1);
        }
        if i.1.entries().count() > 0 {
            process(&i, data, depth+1);
        }
    }

    for j in json.1.members() {
        process(&(&json.0, &j), data, depth);
    }

    // assign collected attributes to element
    data[idx].1 = attribs;

    // if element is only a list of members, remove it from the list
    if json.1.entries().count() == 0 && json.1.members().count() > 0 {
        data.remove(idx);
    }
}
<|endoftext|>


<commit_before>extern crate ratelimit_meter;
#[macro_use] extern crate nonzero_ext;

use ratelimit_meter::{DirectRateLimiter, NegativeMultiDecision, GCRA};
use std::thread;
use std::time::{Duration, Instant};

#[test]
fn accepts_first_cell() {
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(5u32))
        .build()
        .unwrap();
    assert_eq!(Ok(()), gcra.check());
}
#[test]
fn rejects_too_many() {
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(1u32))
        .build()
        .unwrap();
    let now = Instant::now();
    gcra.check_at(now).unwrap();
    gcra.check_at(now).unwrap();
    assert_ne!(Ok(()), gcra.check_at(now), "{:?}", gcra);
}

#[test]
fn allows_after_interval() {
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(1u32))
        .build()
        .unwrap();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    gcra.check_at(now).unwrap();
    assert_eq!(Ok(()), gcra.check_at(now + ms));
    assert_ne!(Ok(()), gcra.check_at(now + ms * 2));
    // should be ok again in 1s:
    let next = now + Duration::from_secs(1);
    assert_eq!(Ok(()), gcra.check_at(next));
}

#[test]
fn allows_n_after_interval() {
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(2u32))
        .build()
        .unwrap();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    assert_eq!(Ok(()), gcra.check_n_at(2, now));
    assert!(!gcra.check_n_at(2, now + ms).is_ok());
    // should be ok again in 1.5s:
    let next = now + Duration::from_secs(1);
    assert_eq!(Ok(()), gcra.check_n_at(2, next), "now: {:?}", next);

    // should always accommodate 0 cells:
    assert_eq!(Ok(()), gcra.check_n_at(0, next));
}

#[test]
fn correctly_handles_per() {
    let ms = Duration::from_millis(1);
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(1u32))
        .per(ms * 20)
        .build()
        .unwrap();
    let now = Instant::now();

    assert_eq!(Ok(()), gcra.check_at(now));
    assert_eq!(Ok(()), gcra.check_at(now + ms));
    assert!(!gcra.check_at(now + ms * 10).is_ok());
    assert_eq!(Ok(()), gcra.check_at(now + ms * 20));
}

#[test]
fn never_allows_more_than_capacity() {
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(5u32))
        .build()
        .unwrap();
    let now = Instant::now();
    let ms = Duration::from_millis(1);

    // Should not allow the first 15 cells on a capacity 5 bucket:
    assert!(gcra.check_n_at(15, now).is_err());

    // After 3 and 20 seconds, it should not allow 15 on that bucket either:
    assert!(gcra.check_n_at(15, now + (ms * 3 * 1000)).is_err());

    let result = gcra.check_n_at(15, now + (ms * 20 * 1000));
    match result {
        Err(NegativeMultiDecision::InsufficientCapacity(n)) => assert_eq!(n, 15),
        _ => panic!("Did not expect {:?}", result),
    }
}

#[test]
fn actual_threadsafety() {
    let mut lim = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(20u32))
        .build()
        .unwrap();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    let mut children = vec![];

    lim.check_at(now).unwrap();
    for _i in 0..20 {
        let mut lim = lim.clone();
        children.push(thread::spawn(move || {
            lim.check_at(now).unwrap();
        }));
    }
    for child in children {
        child.join().unwrap();
    }
    assert!(!lim.check_at(now + ms * 2).is_ok());
    assert_eq!(Ok(()), lim.check_at(now + ms * 1000));
}
<commit_msg>Add a test for GCRA's wait time calculation, too<commit_after>extern crate ratelimit_meter;
#[macro_use] extern crate nonzero_ext;

use ratelimit_meter::{DirectRateLimiter, NegativeMultiDecision, GCRA, NonConformance};
use std::thread;
use std::time::{Duration, Instant};

#[test]
fn accepts_first_cell() {
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(5u32))
        .build()
        .unwrap();
    assert_eq!(Ok(()), gcra.check());
}
#[test]
fn rejects_too_many() {
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(1u32))
        .build()
        .unwrap();
    let now = Instant::now();
    gcra.check_at(now).unwrap();
    gcra.check_at(now).unwrap();
    assert_ne!(Ok(()), gcra.check_at(now), "{:?}", gcra);
}

#[test]
fn allows_after_interval() {
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(1u32))
        .build()
        .unwrap();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    gcra.check_at(now).unwrap();
    assert_eq!(Ok(()), gcra.check_at(now + ms));
    assert_ne!(Ok(()), gcra.check_at(now + ms * 2));
    // should be ok again in 1s:
    let next = now + Duration::from_secs(1);
    assert_eq!(Ok(()), gcra.check_at(next));
}

#[test]
fn allows_n_after_interval() {
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(2u32))
        .build()
        .unwrap();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    assert_eq!(Ok(()), gcra.check_n_at(2, now));
    assert!(!gcra.check_n_at(2, now + ms).is_ok());
    // should be ok again in 1.5s:
    let next = now + Duration::from_secs(1);
    assert_eq!(Ok(()), gcra.check_n_at(2, next), "now: {:?}", next);

    // should always accommodate 0 cells:
    assert_eq!(Ok(()), gcra.check_n_at(0, next));
}

#[test]
fn correctly_handles_per() {
    let ms = Duration::from_millis(1);
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(1u32))
        .per(ms * 20)
        .build()
        .unwrap();
    let now = Instant::now();

    assert_eq!(Ok(()), gcra.check_at(now));
    assert_eq!(Ok(()), gcra.check_at(now + ms));
    assert!(!gcra.check_at(now + ms * 10).is_ok());
    assert_eq!(Ok(()), gcra.check_at(now + ms * 20));
}

#[test]
fn never_allows_more_than_capacity() {
    let mut gcra = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(5u32))
        .build()
        .unwrap();
    let now = Instant::now();
    let ms = Duration::from_millis(1);

    // Should not allow the first 15 cells on a capacity 5 bucket:
    assert!(gcra.check_n_at(15, now).is_err());

    // After 3 and 20 seconds, it should not allow 15 on that bucket either:
    assert!(gcra.check_n_at(15, now + (ms * 3 * 1000)).is_err());

    let result = gcra.check_n_at(15, now + (ms * 20 * 1000));
    match result {
        Err(NegativeMultiDecision::InsufficientCapacity(n)) => assert_eq!(n, 15),
        _ => panic!("Did not expect {:?}", result),
    }
}

#[test]
fn correct_wait_time() {
    // Bucket adding a new element per 200ms:
    let mut lb = DirectRateLimiter::<GCRA>::per_second(nonzero!(5u32));
    let mut now = Instant::now();
    let ms = Duration::from_millis(1);
    let mut conforming = 0;
    for _i in 0..20 {
        now += ms;
        let res = lb.check_at(now);
        match res {
            Ok(()) => {
                conforming += 1;
            }
            Err(wait) => {
                now += wait.wait_time_from(now);
                assert_eq!(Ok(()), lb.check_at(now));
                conforming += 1;
            }
        }
    }
    assert_eq!(20, conforming);
}

#[test]
fn actual_threadsafety() {
    let mut lim = DirectRateLimiter::<GCRA>::build_with_capacity(nonzero!(20u32))
        .build()
        .unwrap();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    let mut children = vec![];

    lim.check_at(now).unwrap();
    for _i in 0..20 {
        let mut lim = lim.clone();
        children.push(thread::spawn(move || {
            lim.check_at(now).unwrap();
        }));
    }
    for child in children {
        child.join().unwrap();
    }
    assert!(!lim.check_at(now + ms * 2).is_ok());
    assert_eq!(Ok(()), lim.check_at(now + ms * 1000));
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate libc;
extern crate jni;

use jni::*;

fn main() {
	let opt = JavaVMOption::new("-Xcheck:jni",
								0 as *const ::libc::c_void);
	println!("Opt is {:?}", opt);

	let opt2 = JavaVMOption::new("-ea",
								0 as *const ::libc::c_void);
	println!("Opt is {:?}", opt2);

	let args = JavaVMInitArgs::new(
		jni::JniVersion::JNI_VERSION_1_4, &[opt, opt2][..], false);
	println!("Args is {:?}", args);

	let mut jvm = JavaVM::new(args, "").unwrap();
	let mut vec = Vec::new();

	println!("Jvm is {:?}", &jvm);

	let env = jvm.get_env();
	println!("Env is {:?}", &env);

	println!("Version is {:?}", env.version());
	let string_name = JavaChars::new("java/lang/String");
	let cls = JavaClass::find(&env, &string_name).unwrap();

	let proto = JavaChars::new("Hello, world!");
	let st = JavaString::new(&env, &proto);
	println!("St is {:?}", st.to_str().unwrap());
	assert_eq!(st.to_str(), proto.to_string());

	println!("St len is {:?} == {:?}", st.to_str().unwrap().len(),
			 proto.to_string().unwrap().len());

	println!("Clses are {:?}, {:?}, {:?}, {:?}", cls,
			 st.get_class(),
			 cls.is_same(&st.get_class()),
			 st.is_instance_of(&cls));

	println!("st[2:7] == {:?}", st.region(2, 5));

	let gst = st.global();
	let wgst = gst.weak();
	let wst = st.weak();
	println!("Wst is null: {:?}", wst.is_null());
	println!("{:?} {:?} {:?} {:?} {:?}", st, gst, wgst, wst,
			 wgst);
	println!("Wst is null: {:?}", wst.is_null());
	vec.push(env.clone());

	let java_chars = JavaChars::new("Hello, error!");
	vec[0].fatal_error(&java_chars)
}
// vim: set noexpandtab:
// vim: set tabstop=4:
// vim: set shiftwidth=4:
// Local Variables:
// mode: rust
// indent-tabs-mode: t
// rust-indent-offset: 4
// tab-width: 4
// End:
<commit_msg>Cleaned up and made test pass.  Deleted editor config from file.<commit_after>#![allow(dead_code)]
extern crate libc;
extern crate jni;

use jni::*;

#[test]
fn test () {
    self::main()
}
fn main() {
	let opt = JavaVMOption::new("-Xcheck:jni",
                                    0 as *const ::libc::c_void);
	println!("Opt is {:?}", opt);

	let opt2 = JavaVMOption::new("-ea",
				     0 as *const ::libc::c_void);
	println!("Opt is {:?}", opt2);

	let args = JavaVMInitArgs::new(
		jni::JniVersion::JNI_VERSION_1_4, &[opt, opt2][..], false);
	println!("Args is {:?}", args);

	let (mut jvm, cap) = JavaVM::new(args, "").unwrap();
	let mut vec = Vec::new();

	println!("Jvm is {:?}", &jvm);

	let env = jvm.get_env();
	println!("Env is {:?}", &env);

	println!("Version is {:?}", env.version());
	let string_name = JavaChars::new("java/lang/String");
	let cls = JavaClass::find(&env, &string_name).unwrap();

	let proto = JavaChars::new("Hello, world!");
	let st = JavaString::new(&env, &proto);
	println!("St is {:?}", st.to_str().unwrap());
	assert_eq!(st.to_str(), proto.to_string());

	println!("St len is {:?} == {:?}", st.to_str().unwrap().len(),
			 proto.to_string().unwrap().len());

	println!("Clses are {:?}, {:?}, {:?}, {:?}", cls,
			 st.get_class(),
			 cls.is_same(&st.get_class()),
			 st.is_instance_of(&cls));

	println!("st[2:7] == {:?}", st.region(2, 5));

	let gst = st.global();
	let wgst = gst.weak();
	let wst = st.weak();
	println!("Wst is null: {:?}", wst.is_null());
	println!("{:?} {:?} {:?} {:?} {:?}", st, gst, wgst, wst,
			 wgst);
	println!("Wst is null: {:?}", wst.is_null());
	vec.push(env.clone());

	// let java_chars = JavaChars::new("Hello, error!");
	// vec[0].fatal_error(&java_chars)
}
<|endoftext|>


<commit_before>use mio::net::{TcpListener, TcpStream};
use mio::*;
use std::sync::{Arc, Barrier};
use std::thread;
use std::time::Duration;

mod util;

use util::{any_local_address, assert_send, assert_sync, init};

#[test]
fn is_send_and_sync() {
    assert_sync::<Poll>();
    assert_send::<Poll>();

    assert_sync::<Registry>();
    assert_send::<Registry>();
}

#[test]
fn run_once_with_nothing() {
    init();

    let mut events = Events::with_capacity(16);
    let mut poll = Poll::new().unwrap();
    poll.poll(&mut events, Some(Duration::from_millis(100)))
        .unwrap();
}

#[test]
fn add_then_drop() {
    init();

    let mut events = Events::with_capacity(16);
    let l = TcpListener::bind(any_local_address()).unwrap();
    let mut poll = Poll::new().unwrap();
    poll.registry()
        .register(&l, Token(1), Interests::READABLE | Interests::WRITABLE)
        .unwrap();
    drop(l);
    poll.poll(&mut events, Some(Duration::from_millis(100)))
        .unwrap();
}

#[test]
fn test_poll_closes_fd() {
    init();

    for _ in 0..2000 {
        let mut poll = Poll::new().unwrap();
        let mut events = Events::with_capacity(4);

        poll.poll(&mut events, Some(Duration::from_millis(0)))
            .unwrap();

        drop(poll);
    }
}

#[test]
fn test_drop_cancels_interest_and_shuts_down() {
    init();

    use mio::net::TcpStream;
    use std::io;
    use std::io::Read;
    use std::net::TcpListener;
    use std::thread;

    let l = TcpListener::bind("127.0.0.1:0").unwrap();
    let addr = l.local_addr().unwrap();

    let t = thread::spawn(move || {
        let mut s = l.incoming().next().unwrap().unwrap();
        s.set_read_timeout(Some(Duration::from_secs(5)))
            .expect("set_read_timeout");
        let r = s.read(&mut [0; 16]);
        match r {
            Ok(_) => (),
            Err(e) => {
                if e.kind() != io::ErrorKind::UnexpectedEof {
                    panic!(e);
                }
            }
        }
    });

    let mut poll = Poll::new().unwrap();
    let mut s = TcpStream::connect(addr).unwrap();

    poll.registry()
        .register(&s, Token(1), Interests::READABLE | Interests::WRITABLE)
        .unwrap();
    let mut events = Events::with_capacity(16);
    'outer: loop {
        poll.poll(&mut events, None).unwrap();
        for event in &events {
            if event.token() == Token(1) {
                // connected
                break 'outer;
            }
        }
    }

    let mut b = [0; 1024];
    match s.read(&mut b) {
        Ok(_) => panic!("unexpected ok"),
        Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => (),
        Err(e) => panic!("unexpected error: {:?}", e),
    }

    drop(s);
    t.join().unwrap();
}

#[test]
fn test_registry_behind_arc() {
    // `Registry` should work behind an `Arc`, being `Sync` and `Send`.
    init();

    let mut poll = Poll::new().unwrap();
    let registry = Arc::new(poll.registry().try_clone().unwrap());
    let mut events = Events::with_capacity(128);

    let listener = TcpListener::bind(any_local_address()).unwrap();
    let addr = listener.local_addr().unwrap();
    let barrier = Arc::new(Barrier::new(3));

    let registry2 = Arc::clone(&registry);
    let registry3 = Arc::clone(&registry);
    let barrier2 = Arc::clone(&barrier);
    let barrier3 = Arc::clone(&barrier);

    let handle1 = thread::spawn(move || {
        registry2
            .register(&listener, Token(0), Interests::READABLE)
            .unwrap();
        barrier2.wait();
    });
    let handle2 = thread::spawn(move || {
        let stream = TcpStream::connect(addr).unwrap();
        registry3
            .register(&stream, Token(1), Interests::READABLE | Interests::WRITABLE)
            .unwrap();
        barrier3.wait();
    });

    poll.poll(&mut events, Some(Duration::from_millis(500)))
        .unwrap();
    assert!(events.iter().count() >= 1);

    // Let the threads return.
    barrier.wait();

    handle1.join().unwrap();
    handle2.join().unwrap();
}

// On kqueue platforms registering twice (not *re*registering) works.
#[test]
#[cfg(any(target_os = "linux", target_os = "windows"))]
pub fn test_double_register() {
    init();
    let poll = Poll::new().unwrap();

    let l = TcpListener::bind("127.0.0.1:0".parse().unwrap()).unwrap();

    poll.registry()
        .register(&l, Token(0), Interests::READABLE)
        .unwrap();

    assert!(poll
        .registry()
        .register(&l, Token(1), Interests::READABLE)
        .is_err());
}
<commit_msg>Test without timeout<commit_after>use mio::net::{TcpListener, TcpStream};
use mio::*;
use std::sync::{Arc, Barrier};
use std::thread;
use std::time::Duration;

mod util;

use util::{any_local_address, assert_send, assert_sync, init};

#[test]
fn is_send_and_sync() {
    assert_sync::<Poll>();
    assert_send::<Poll>();

    assert_sync::<Registry>();
    assert_send::<Registry>();
}

#[test]
fn run_once_with_nothing() {
    init();

    let mut events = Events::with_capacity(16);
    let mut poll = Poll::new().unwrap();
    poll.poll(&mut events, Some(Duration::from_millis(100)))
        .unwrap();
}

#[test]
fn add_then_drop() {
    init();

    let mut events = Events::with_capacity(16);
    let l = TcpListener::bind(any_local_address()).unwrap();
    let mut poll = Poll::new().unwrap();
    poll.registry()
        .register(&l, Token(1), Interests::READABLE | Interests::WRITABLE)
        .unwrap();
    drop(l);
    poll.poll(&mut events, Some(Duration::from_millis(100)))
        .unwrap();
}

#[test]
fn test_poll_closes_fd() {
    init();

    for _ in 0..2000 {
        let mut poll = Poll::new().unwrap();
        let mut events = Events::with_capacity(4);

        poll.poll(&mut events, Some(Duration::from_millis(0)))
            .unwrap();

        drop(poll);
    }
}

#[test]
fn test_drop_cancels_interest_and_shuts_down() {
    init();

    use mio::net::TcpStream;
    use std::io;
    use std::io::Read;
    use std::net::TcpListener;
    use std::thread;

    let l = TcpListener::bind("127.0.0.1:0").unwrap();
    let addr = l.local_addr().unwrap();

    let t = thread::spawn(move || {
        let mut s = l.incoming().next().unwrap().unwrap();
        s.set_read_timeout(Some(Duration::from_secs(5)))
            .expect("set_read_timeout");
        let r = s.read(&mut [0; 16]);
        match r {
            Ok(_) => (),
            Err(e) => {
                if e.kind() != io::ErrorKind::UnexpectedEof {
                    panic!(e);
                }
            }
        }
    });

    let mut poll = Poll::new().unwrap();
    let mut s = TcpStream::connect(addr).unwrap();

    poll.registry()
        .register(&s, Token(1), Interests::READABLE | Interests::WRITABLE)
        .unwrap();
    let mut events = Events::with_capacity(16);
    'outer: loop {
        poll.poll(&mut events, None).unwrap();
        for event in &events {
            if event.token() == Token(1) {
                // connected
                break 'outer;
            }
        }
    }

    let mut b = [0; 1024];
    match s.read(&mut b) {
        Ok(_) => panic!("unexpected ok"),
        Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => (),
        Err(e) => panic!("unexpected error: {:?}", e),
    }

    drop(s);
    t.join().unwrap();
}

#[test]
fn test_registry_behind_arc() {
    // `Registry` should work behind an `Arc`, being `Sync` and `Send`.
    init();

    let mut poll = Poll::new().unwrap();
    let registry = Arc::new(poll.registry().try_clone().unwrap());
    let mut events = Events::with_capacity(128);

    let listener = TcpListener::bind(any_local_address()).unwrap();
    let addr = listener.local_addr().unwrap();
    let barrier = Arc::new(Barrier::new(3));

    let registry2 = Arc::clone(&registry);
    let registry3 = Arc::clone(&registry);
    let barrier2 = Arc::clone(&barrier);
    let barrier3 = Arc::clone(&barrier);

    let handle1 = thread::spawn(move || {
        registry2
            .register(&listener, Token(0), Interests::READABLE)
            .unwrap();
        barrier2.wait();
    });
    let handle2 = thread::spawn(move || {
        let stream = TcpStream::connect(addr).unwrap();
        registry3
            .register(&stream, Token(1), Interests::READABLE | Interests::WRITABLE)
            .unwrap();
        barrier3.wait();
    });

    poll.poll(&mut events, None)
        .unwrap();
    assert!(events.iter().count() >= 1);

    // Let the threads return.
    barrier.wait();

    handle1.join().unwrap();
    handle2.join().unwrap();
}

// On kqueue platforms registering twice (not *re*registering) works.
#[test]
#[cfg(any(target_os = "linux", target_os = "windows"))]
pub fn test_double_register() {
    init();
    let poll = Poll::new().unwrap();

    let l = TcpListener::bind("127.0.0.1:0".parse().unwrap()).unwrap();

    poll.registry()
        .register(&l, Token(0), Interests::READABLE)
        .unwrap();

    assert!(poll
        .registry()
        .register(&l, Token(1), Interests::READABLE)
        .is_err());
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::Write;
use std::path::Path;

use linefeed::Reader;
use linefeed::terminal::DefaultTerminal;
use sqlite;

use tools;
use shell;

pub fn init(rl: &mut Reader<DefaultTerminal>) {
    let mut hist_size: usize = 9999; // make default bigger but not huge
    if let Ok(x) = env::var("HISTORY_SIZE") {
        if let Ok(y) = x.parse::<usize>() {
            hist_size = y;
        }
    }
    rl.set_history_size(hist_size);

    let history_table = get_history_table();
    let hfile = get_history_file();
    let path = Path::new(hfile.as_str());
    if !path.exists() {
        let _parent = path.parent().expect("no parent found");
        let parent = _parent.to_str().expect("parent to_str error");
        fs::create_dir_all(parent).expect("dirs create failed");
        fs::File::create(hfile.as_str()).expect("file create failed");
    }

    let mut histories: HashMap<String, bool> = HashMap::new();
    match sqlite::open(hfile.clone()) {
        Ok(conn) => {
            let sql_create = format!(
                "
                CREATE TABLE IF NOT EXISTS {}
                    (inp TEXT,
                     rtn INTEGER,
                     tsb REAL,
                     tse REAL,
                     sessionid TEXT,
                     out TEXT,
                     info TEXT
                    );
            ",
                history_table
            );
            match conn.execute(sql_create) {
                Ok(_) => {}
                Err(e) => println_stderr!("cicada: sqlite exec error - {:?}", e),
            }

            if let Ok(x) = env::var("HISTORY_DELETE_DUPS") {
                if x == "1" {
                    delete_duplicated_histories();
                }
            }

            let sql_select =
                format!(
                "SELECT inp FROM {} ORDER BY tsb;",
                history_table,
            );
            match conn.iterate(sql_select, |pairs| {
                for &(_, value) in pairs.iter() {
                    let inp = value.expect("cicada: sqlite pairs error");
                    let _k = inp.to_string();
                    if histories.contains_key(&_k) {
                        continue;
                    }
                    histories.insert(_k, true);
                    rl.add_history(inp.trim().to_string());
                }
                true
            }) {
                Ok(_) => {}
                Err(e) => println_stderr!("cicada: sqlite select error - {:?}", e),
            }
        }
        Err(e) => {
            println_stderr!("cicada: sqlite conn error - {:?}", e);
        }
    }
}

pub fn get_history_file() -> String {
    if let Ok(hfile) = env::var("HISTORY_FILE") {
        return hfile;
    } else if let Ok(d) = env::var("XDG_DATA_HOME") {
        return format!("{}/{}", d, "cicada/history.sqlite");
    } else {
        let home = tools::get_user_home();
        return format!("{}/{}", home, ".local/share/cicada/history.sqlite");
    }
}

pub fn get_history_table() -> String {
    if let Ok(hfile) = env::var("HISTORY_TABLE") {
        return hfile;
    } else {
        return String::from("cicada_history");
    }
}

fn delete_duplicated_histories() {
    let hfile = get_history_file();
    let history_table = get_history_table();
    match sqlite::open(hfile.clone()) {
        Ok(conn) => {
            let sql = format!(
                "DELETE FROM {} WHERE rowid NOT IN (
                SELECT MAX(rowid) FROM {} GROUP BY inp)",
                history_table,
                history_table
            );
            match conn.execute(sql) {
                Ok(_) => {}
                Err(e) => println_stderr!("cicada: sqlite exec error - {:?}", e),
            }
        }
        Err(e) => println_stderr!("cicada: sqlite open file error - {:?}", e),
    }
}

pub fn add(
    sh: &mut shell::Shell,
    rl: &mut Reader<DefaultTerminal>,
    line: &str,
    status: i32,
    tsb: f64,
    tse: f64,
) {
    rl.add_history(line.to_string());
    if line == sh.previous_cmd {
        return;
    }

    sh.previous_cmd = line.to_string();
    let hfile = get_history_file();
    let history_table = get_history_table();
    let conn = sqlite::open(hfile).expect("sqlite open error");
    let sql = format!(
        "INSERT INTO \
        {} (inp, rtn, tsb, tse, sessionid) \
        VALUES('{}', {}, {}, {}, '{}');",
        history_table,
        str::replace(line.trim(), "'", "''"),
        status,
        tsb,
        tse,
        "cicada"
    );
    match conn.execute(sql) {
        Ok(_) => {}
        Err(e) => println!("failed to save history: {:?}", e),
    }
}
<commit_msg>update history default size<commit_after>use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::Write;
use std::path::Path;

use linefeed::Reader;
use linefeed::terminal::DefaultTerminal;
use sqlite;

use tools;
use shell;

pub fn init(rl: &mut Reader<DefaultTerminal>) {
    let mut hist_size: usize = 999;
    if let Ok(x) = env::var("HISTORY_SIZE") {
        if let Ok(y) = x.parse::<usize>() {
            hist_size = y;
        }
    }
    rl.set_history_size(hist_size);

    let history_table = get_history_table();
    let hfile = get_history_file();
    let path = Path::new(hfile.as_str());
    if !path.exists() {
        let _parent = path.parent().expect("no parent found");
        let parent = _parent.to_str().expect("parent to_str error");
        fs::create_dir_all(parent).expect("dirs create failed");
        fs::File::create(hfile.as_str()).expect("file create failed");
    }

    let mut histories: HashMap<String, bool> = HashMap::new();
    match sqlite::open(hfile.clone()) {
        Ok(conn) => {
            let sql_create = format!(
                "
                CREATE TABLE IF NOT EXISTS {}
                    (inp TEXT,
                     rtn INTEGER,
                     tsb REAL,
                     tse REAL,
                     sessionid TEXT,
                     out TEXT,
                     info TEXT
                    );
            ",
                history_table
            );
            match conn.execute(sql_create) {
                Ok(_) => {}
                Err(e) => println_stderr!("cicada: sqlite exec error - {:?}", e),
            }

            if let Ok(x) = env::var("HISTORY_DELETE_DUPS") {
                if x == "1" {
                    delete_duplicated_histories();
                }
            }

            let sql_select =
                format!(
                "SELECT inp FROM {} ORDER BY tsb;",
                history_table,
            );
            match conn.iterate(sql_select, |pairs| {
                for &(_, value) in pairs.iter() {
                    let inp = value.expect("cicada: sqlite pairs error");
                    let _k = inp.to_string();
                    if histories.contains_key(&_k) {
                        continue;
                    }
                    histories.insert(_k, true);
                    rl.add_history(inp.trim().to_string());
                }
                true
            }) {
                Ok(_) => {}
                Err(e) => println_stderr!("cicada: sqlite select error - {:?}", e),
            }
        }
        Err(e) => {
            println_stderr!("cicada: sqlite conn error - {:?}", e);
        }
    }
}

pub fn get_history_file() -> String {
    if let Ok(hfile) = env::var("HISTORY_FILE") {
        return hfile;
    } else if let Ok(d) = env::var("XDG_DATA_HOME") {
        return format!("{}/{}", d, "cicada/history.sqlite");
    } else {
        let home = tools::get_user_home();
        return format!("{}/{}", home, ".local/share/cicada/history.sqlite");
    }
}

pub fn get_history_table() -> String {
    if let Ok(hfile) = env::var("HISTORY_TABLE") {
        return hfile;
    } else {
        return String::from("cicada_history");
    }
}

fn delete_duplicated_histories() {
    let hfile = get_history_file();
    let history_table = get_history_table();
    match sqlite::open(hfile.clone()) {
        Ok(conn) => {
            let sql = format!(
                "DELETE FROM {} WHERE rowid NOT IN (
                SELECT MAX(rowid) FROM {} GROUP BY inp)",
                history_table,
                history_table
            );
            match conn.execute(sql) {
                Ok(_) => {}
                Err(e) => println_stderr!("cicada: sqlite exec error - {:?}", e),
            }
        }
        Err(e) => println_stderr!("cicada: sqlite open file error - {:?}", e),
    }
}

pub fn add(
    sh: &mut shell::Shell,
    rl: &mut Reader<DefaultTerminal>,
    line: &str,
    status: i32,
    tsb: f64,
    tse: f64,
) {
    rl.add_history(line.to_string());
    if line == sh.previous_cmd {
        return;
    }

    sh.previous_cmd = line.to_string();
    let hfile = get_history_file();
    let history_table = get_history_table();
    let conn = sqlite::open(hfile).expect("sqlite open error");
    let sql = format!(
        "INSERT INTO \
        {} (inp, rtn, tsb, tse, sessionid) \
        VALUES('{}', {}, {}, {}, '{}');",
        history_table,
        str::replace(line.trim(), "'", "''"),
        status,
        tsb,
        tse,
        "cicada"
    );
    match conn.execute(sql) {
        Ok(_) => {}
        Err(e) => println!("failed to save history: {:?}", e),
    }
}
<|endoftext|>


<commit_before>#[cfg(unix)]
mod unix;

#[cfg(unix)]
pub use self::unix::*;

#[cfg(windows)]
mod unix;

#[cfg(windows)]
pub use self::windows::*;

<commit_msg>fix windows mod decl.<commit_after>#[cfg(unix)]
mod unix;

#[cfg(unix)]
pub use self::unix::*;

#[cfg(windows)]
mod windows;

#[cfg(windows)]
pub use self::windows::*;

<|endoftext|>


<commit_before>#![crate_id = "github.com/TomBebbington/js.rs#js:0.1"]
#![comment = "Javascript parsing, compilation and execution using LibJIT"]
#![license = "MIT"]
#![crate_type = "lib"]
#![doc(
    html_favicon_url = "http://tombebbington.github.io/favicon.png"
  ))
#![experimental]
#![feature(phase, macro_rules, globs)]
#![deny(non_uppercase_statics, missing_doc, unnecessary_parens, unrecognized_lint,
	unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation,
	uppercase_variables, non_camel_case_types, unused_must_use)]
//! This is a library with seperate modules for Javascript parsing, the Javascript
//! standard library, and Javascript execution through LibJIT
extern crate collections;
extern crate jit;
#[phase(plugin, link)]
extern crate log;
extern crate serialize;
extern crate time;
extern crate url;
/// The backend-defining traits and the Javascript standard library
pub mod front {
	#[macro_escape]
	/// A macro which makes Javascript objects with pretty Rust syntax
	pub mod macro;
	/// Backend-defining traits
	pub mod run {
		/// For compiling Javascript values
		pub mod compiler;
		/// For executing the compiled Javascript values
		pub mod executor;
	}
	/// The Javascript standard library
	pub mod stdlib {
		/// The `Array` global object
		pub mod array;
		/// The `Boolean` global object
		pub mod boolean;
		/// The `console` global object
		pub mod console;
		/// The `Error` global objects
		pub mod error;
		/// The `Function` global object
		pub mod function;
		/// The `JSON` global object
		pub mod json;
		/// The `Math` global object
		pub mod math;
		/// The `Number` global object and related global methods
		pub mod number;
		/// The `Object` global object
		pub mod object;
		/// The `String` global object
		pub mod string;
		/// The global URI methods
		pub mod uri;
		/// An arbritary Javascript value
		pub mod value;
	}
}
/// The default backend implemented on top of LibJIT
pub mod back {
	/// The compiler, which transforms Javascript expressions to LibJIT IR
	pub mod compiler;
	/// The executor, which runs the LibJIT IR by compiling it then running it
	pub mod executor;
}
/// Javascript parsing and syntax
pub mod syntax {
	/// The Javascript Abstract Syntax Tree
	pub mod ast {
		/// Constants
		pub mod constant;
		/// Expressions
		pub mod expr;
		/// Keywords
		pub mod keyword;
		/// Operators
		pub mod op;
		/// Positions
		pub mod pos;
		/// Punctuators
		pub mod punc;
		/// Tokens
		pub mod token;
		/// An expression typer
		pub mod typer;
		/// Types
		pub mod types;
	}
	/// Parses a string stream into a sequence of tokens
	pub mod lexer;
	/// Parses a sequence of tokens into expressions
	pub mod parser;
}<commit_msg>Close *BOTH* delimiters *correctly*<commit_after>#![crate_id = "github.com/TomBebbington/js.rs#js:0.1"]
#![comment = "Javascript parsing, compilation and execution using LibJIT"]
#![license = "MIT"]
#![crate_type = "lib"]
#![doc(
    html_favicon_url = "http://tombebbington.github.io/favicon.png"
  )]
#![experimental]
#![feature(phase, macro_rules, globs)]
#![deny(non_uppercase_statics, missing_doc, unnecessary_parens, unrecognized_lint,
	unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation,
	uppercase_variables, non_camel_case_types, unused_must_use)]
//! This is a library with seperate modules for Javascript parsing, the Javascript
//! standard library, and Javascript execution through LibJIT
extern crate collections;
extern crate jit;
#[phase(plugin, link)]
extern crate log;
extern crate serialize;
extern crate time;
extern crate url;
/// The backend-defining traits and the Javascript standard library
pub mod front {
	#[macro_escape]
	/// A macro which makes Javascript objects with pretty Rust syntax
	pub mod macro;
	/// Backend-defining traits
	pub mod run {
		/// For compiling Javascript values
		pub mod compiler;
		/// For executing the compiled Javascript values
		pub mod executor;
	}
	/// The Javascript standard library
	pub mod stdlib {
		/// The `Array` global object
		pub mod array;
		/// The `Boolean` global object
		pub mod boolean;
		/// The `console` global object
		pub mod console;
		/// The `Error` global objects
		pub mod error;
		/// The `Function` global object
		pub mod function;
		/// The `JSON` global object
		pub mod json;
		/// The `Math` global object
		pub mod math;
		/// The `Number` global object and related global methods
		pub mod number;
		/// The `Object` global object
		pub mod object;
		/// The `String` global object
		pub mod string;
		/// The global URI methods
		pub mod uri;
		/// An arbritary Javascript value
		pub mod value;
	}
}
/// The default backend implemented on top of LibJIT
pub mod back {
	/// The compiler, which transforms Javascript expressions to LibJIT IR
	pub mod compiler;
	/// The executor, which runs the LibJIT IR by compiling it then running it
	pub mod executor;
}
/// Javascript parsing and syntax
pub mod syntax {
	/// The Javascript Abstract Syntax Tree
	pub mod ast {
		/// Constants
		pub mod constant;
		/// Expressions
		pub mod expr;
		/// Keywords
		pub mod keyword;
		/// Operators
		pub mod op;
		/// Positions
		pub mod pos;
		/// Punctuators
		pub mod punc;
		/// Tokens
		pub mod token;
		/// An expression typer
		pub mod typer;
		/// Types
		pub mod types;
	}
	/// Parses a string stream into a sequence of tokens
	pub mod lexer;
	/// Parses a sequence of tokens into expressions
	pub mod parser;
}<|endoftext|>