<commit_before>use bytes::{BufMut, Bytes, BytesMut};

use futures;

use nom::{self, Needed};

use imap_proto;
use imap_proto::types::{Request, RequestId, Response};

use std::io;
use std::mem;

use tokio::net::TcpStream;
use tokio_codec::{Decoder, Encoder, Framed};
use tokio_tls::TlsStream;

pub struct ImapCodec {
    decode_need_message_bytes: usize,
}

impl Default for ImapCodec {
    fn default() -> Self {
        Self {
            decode_need_message_bytes: 0,
        }
    }
}

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
        if self.decode_need_message_bytes > buf.len() {
            return Ok(None);
        }
        let (response, rsp_len) = match imap_proto::parse_response(buf) {
            Ok((remaining, response)) => {
                // This SHOULD be acceptable/safe: BytesMut storage memory is
                // allocated on the heap and should not move. It will not be
                // freed as long as we keep a reference alive, which we do
                // by retaining a reference to the split buffer, below.
                let response = unsafe { mem::transmute(response) };
                (response, buf.len() - remaining.len())
            }
            Err(nom::Err::Incomplete(Needed::Size(min))) => {
                self.decode_need_message_bytes = min;
                return Ok(None);
            }
            Err(nom::Err::Incomplete(_)) => {
                return Ok(None);
            }
            Err(err) => {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!("{} during parsing of {:?}", err, buf),
                ));
            }
        };
        let raw = buf.split_to(rsp_len).freeze();
        self.decode_need_message_bytes = 0;
        Ok(Some(ResponseData { raw, response }))
    }
}

impl Encoder for ImapCodec {
    type Item = Request;
    type Error = io::Error;
    fn encode(&mut self, msg: Self::Item, dst: &mut BytesMut) -> Result<(), io::Error> {
        dst.put(msg.0.as_bytes());
        dst.put(b' ');
        dst.put(&msg.1);
        dst.put("\r\n");
        Ok(())
    }
}

#[derive(Debug)]
pub struct ResponseData {
    raw: Bytes,
    // This reference is really scoped to the lifetime of the `raw`
    // member, but unfortunately Rust does not allow that yet. It
    // is transmuted to `'static` by the `Decoder`, instead, and
    // references returned to callers of `ResponseData` are limited
    // to the lifetime of the `ResponseData` struct.
    pub response: Response<'static>,
}

impl ResponseData {
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done { ref tag, .. } => Some(tag),
            _ => None,
        }
    }
    pub fn parsed(&self) -> &Response {
        unsafe { mem::transmute(&self.response) }
    }
}

pub type ImapTls = Framed<TlsStream<TcpStream>, ImapCodec>;

impl ImapTransport for ImapTls {}

pub trait ImapTransport:
    futures::Stream<Item = ResponseData, Error = io::Error>
    + futures::Sink<SinkItem = Request, SinkError = io::Error>
{
}
<commit_msg>Improve safety of unsafe transmute (fixes #30)<commit_after>use bytes::{BufMut, Bytes, BytesMut};

use futures;

use nom::{self, Needed};

use imap_proto;
use imap_proto::types::{Request, RequestId, Response};

use std::io;
use std::mem;

use tokio::net::TcpStream;
use tokio_codec::{Decoder, Encoder, Framed};
use tokio_tls::TlsStream;

pub struct ImapCodec {
    decode_need_message_bytes: usize,
}

impl Default for ImapCodec {
    fn default() -> Self {
        Self {
            decode_need_message_bytes: 0,
        }
    }
}

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
        if self.decode_need_message_bytes > buf.len() {
            return Ok(None);
        }
        let (response, rsp_len) = match imap_proto::parse_response(buf) {
            Ok((remaining, response)) => {
                // This SHOULD be acceptable/safe: BytesMut storage memory is
                // allocated on the heap and should not move. It will not be
                // freed as long as we keep a reference alive, which we do
                // by retaining a reference to the split buffer, below.
                let response = unsafe { mem::transmute(response) };
                (response, buf.len() - remaining.len())
            }
            Err(nom::Err::Incomplete(Needed::Size(min))) => {
                self.decode_need_message_bytes = min;
                return Ok(None);
            }
            Err(nom::Err::Incomplete(_)) => {
                return Ok(None);
            }
            Err(err) => {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!("{} during parsing of {:?}", err, buf),
                ));
            }
        };
        let raw = buf.split_to(rsp_len).freeze();
        self.decode_need_message_bytes = 0;
        Ok(Some(ResponseData { raw, response }))
    }
}

impl Encoder for ImapCodec {
    type Item = Request;
    type Error = io::Error;
    fn encode(&mut self, msg: Self::Item, dst: &mut BytesMut) -> Result<(), io::Error> {
        dst.put(msg.0.as_bytes());
        dst.put(b' ');
        dst.put(&msg.1);
        dst.put("\r\n");
        Ok(())
    }
}

#[derive(Debug)]
pub struct ResponseData {
    raw: Bytes,
    // This reference is really scoped to the lifetime of the `raw`
    // member, but unfortunately Rust does not allow that yet. It
    // is transmuted to `'static` by the `Decoder`, instead, and
    // references returned to callers of `ResponseData` are limited
    // to the lifetime of the `ResponseData` struct.
    //
    // `raw` is never mutated during the lifetime of `ResponseData`,
    // and `Response` does not not implement any specific drop glue.
    response: Response<'static>,
}

impl ResponseData {
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done { ref tag, .. } => Some(tag),
            _ => None,
        }
    }
    pub fn parsed<'a>(&'a self) -> &'a Response {
        &self.response
    }
}

pub type ImapTls = Framed<TlsStream<TcpStream>, ImapCodec>;

impl ImapTransport for ImapTls {}

pub trait ImapTransport:
    futures::Stream<Item = ResponseData, Error = io::Error>
    + futures::Sink<SinkItem = Request, SinkError = io::Error>
{
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

extern crate gcc;
extern crate pkg_config;

use std::ascii::AsciiExt;
use std::process::Command;
use gcc::Config;
use std::env;
use std::path::Path;

const MIN_MAJOR: u16 = 3;
const MIN_MINOR: u16 = 4;
const MINOR_STEP: u16 = 2;

fn main() {
    let lib = pkg_config::find_library("gtk+-3.0")
        .unwrap_or_else(|e| panic!("{}", e));
    let mut parts = lib.version.splitn(3, '.')
        .map(|s| s.parse())
        .take_while(|r| r.is_ok())
        .map(|r| r.unwrap());
    let version: (u16, u16) = (parts.next().unwrap_or(0), parts.next().unwrap_or(0));
    let mut cfgs = Vec::new();
    if version.0 == MIN_MAJOR && version.1 > MIN_MINOR {
        let major = version.0;
        let mut minor = MIN_MINOR;
        while minor <= version.1 {
            cfgs.push(format!("gtk_{}_{}", major, minor));
            minor += MINOR_STEP;
        }
    }
    for cfg in &cfgs {
        println!("cargo:rustc-cfg={}", cfg);
    }
    println!("cargo:cfg={}", cfgs.join(" "));

    env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");

    // call native pkg-config, there is no way to do this with pkg-config for now
    let cmd = Command::new("pkg-config").arg("--cflags").arg("gtk+-3.0")
                .output().unwrap();
    if !cmd.status.success() {
        panic!("{}", String::from_utf8_lossy(&cmd.stderr));
    }

    // make the vector of path to set to gcc::Config
    let output = String::from_utf8(cmd.stdout).unwrap();

    // build include path
    let mut gcc_conf = Config::new();
    for s in output.split_whitespace() {
        if s.starts_with("-I") {
            let path: &Path = s[2..].as_ref();
            gcc_conf.include(path);
        }
    }
    gcc_conf.file("src/gtk_glue.c");

    // pass the GTK feature flags
    for cfg in &cfgs {
        gcc_conf.flag(&format!("-D{}", cfg.to_ascii_uppercase()));
    }

    // build library
    gcc_conf.compile("librgtk_glue.a");
}
<commit_msg>Update the build script to play nice with GTK 3.4<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

extern crate gcc;
extern crate pkg_config;

use std::ascii::AsciiExt;
use std::process::Command;
use gcc::Config;
use std::env;
use std::path::Path;

const MIN_MAJOR: u16 = 3;
const MIN_MINOR: u16 = 4;
const MINOR_STEP: u16 = 2;

fn main() {
    let lib = pkg_config::find_library("gtk+-3.0")
        .unwrap_or_else(|e| panic!("{}", e));
    let mut parts = lib.version.splitn(3, '.')
        .map(|s| s.parse())
        .take_while(|r| r.is_ok())
        .map(|r| r.unwrap());
    let version: (u16, u16) = (parts.next().unwrap_or(0), parts.next().unwrap_or(0));
    let mut cfgs = Vec::new();
    if version.0 == MIN_MAJOR && version.1 >= MIN_MINOR {
        let major = version.0;
        let mut minor = MIN_MINOR;
        while minor <= version.1 {
            cfgs.push(format!("gtk_{}_{}", major, minor));
            minor += MINOR_STEP;
        }
    }
    for cfg in &cfgs {
        println!("cargo:rustc-cfg={}", cfg);
    }
    println!("cargo:cfg={}", cfgs.join(" "));

    env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");

    // call native pkg-config, there is no way to do this with pkg-config for now
    let cmd = Command::new("pkg-config").arg("--cflags").arg("gtk+-3.0")
                .output().unwrap();
    if !cmd.status.success() {
        panic!("{}", String::from_utf8_lossy(&cmd.stderr));
    }

    // make the vector of path to set to gcc::Config
    let output = String::from_utf8(cmd.stdout).unwrap();

    // build include path
    let mut gcc_conf = Config::new();
    for s in output.split_whitespace() {
        if s.starts_with("-I") {
            let path: &Path = s[2..].as_ref();
            gcc_conf.include(path);
        }
    }
    gcc_conf.file("src/gtk_glue.c");

    // pass the GTK feature flags
    for cfg in &cfgs {
        gcc_conf.flag(&format!("-D{}", cfg.to_ascii_uppercase()));
    }

    // build library
    gcc_conf.compile("librgtk_glue.a");
}
<|endoftext|>


<commit_before>use super::traits::{EdgeWeight, Edges, Graph};
use closed01::Closed01;
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use petgraph::{EdgeDirection, Directed};
use petgraph::Graph as PetGraph;
use std::fmt::Debug;

#[derive(Debug)]
pub struct Edge {
    /// Node index type. Our graphs never exceed 4 billion nodes.
    pointing_node: u32,
    weight: EdgeWeight,
}

impl Edge {
    pub fn new_unweighted(node_idx: usize) -> Edge {
        Edge::new(node_idx, Closed01::zero())
    }

    pub fn new(node_idx: usize, weight: EdgeWeight) -> Edge {
        assert!(node_idx <= u32::max_value() as usize);
        Edge {
            pointing_node: node_idx as u32,
            weight: weight,
        }
    }
}

#[derive(Debug)]
pub struct EdgeList {
    edges: Vec<Edge>,
}

impl EdgeList {
    pub fn new(edges: Vec<Edge>) -> EdgeList {
        EdgeList { edges: edges }
    }
}

impl Edges for EdgeList {
    #[inline]
    fn num_edges(&self) -> usize {
        self.edges.len()
    }

    #[inline]
    fn nth_edge(&self, n: usize) -> Option<usize> {
        self.edges.get(n).map(|n| n.pointing_node as usize)
    }

    #[inline]
    fn nth_edge_weight(&self, n: usize) -> Option<EdgeWeight> {
        self.edges.get(n).map(|n| n.weight)
    }
}

#[derive(Debug)]
pub struct Node<T: Debug + Clone> {
    in_edges: EdgeList,
    out_edges: EdgeList,
    node_value: T,
}

impl<T: Debug + Clone> Node<T> {
    pub fn new(in_edges: EdgeList, out_edges: EdgeList, node_value: T) -> Node<T> {
        Node {
            in_edges: in_edges,
            out_edges: out_edges,
            node_value: node_value,
        }
    }

    pub fn node_value(&self) -> &T {
        &self.node_value
    }

    pub fn add_in_edge(&mut self, edge: Edge) {
        self.in_edges.edges.push(edge);
    }

    pub fn add_out_edge(&mut self, edge: Edge) {
        self.out_edges.edges.push(edge);
    }

    fn degree(&self) -> usize {
        self.in_edges.num_edges() + self.out_edges.num_edges()
    }
}

#[derive(Debug)]
pub struct OwnedGraph<T: Debug + Clone> {
    nodes: Vec<Node<T>>,
}

impl<T: Debug + Clone> OwnedGraph<T> {
    pub fn new(nodes: Vec<Node<T>>) -> OwnedGraph<T> {
        OwnedGraph { nodes: nodes }
    }

    pub fn from_petgraph(pg: &PetGraph<T, EdgeWeight, Directed>) -> OwnedGraph<T> {
        OwnedGraph {
            nodes: pg.node_indices()
                     .map(|i| {
                         Node::new(EdgeList::new(pg.edges_directed(i, EdgeDirection::Incoming)
                                                   .map(|(j, &w)| Edge::new(j.index(), w))
                                                   .collect()),
                                   EdgeList::new(pg.edges_directed(i, EdgeDirection::Outgoing)
                                                   .map(|(j, &w)| Edge::new(j.index(), w))
                                                   .collect()),
                                   pg.node_weight(i).unwrap().clone())
                     })
                     .collect(),
        }
    }

    pub fn len(&self) -> usize {
        self.nodes.len()
    }

    pub fn push_empty_node(&mut self, node_value: T) -> usize {
        let idx = self.nodes.len();
        self.nodes.push(Node::new(EdgeList::new(Vec::new()),
                                  EdgeList::new(Vec::new()),
                                  node_value));
        return idx;
    }
}

impl<T: Debug + Clone> Graph for OwnedGraph<T> {
    type EDGE = EdgeList;
    type NODE = T;
    fn num_nodes(&self) -> usize {
        self.nodes.len()
    }

    #[inline]
    fn node_value(&self, node_idx: usize) -> &Self::NODE {
        self.nodes[node_idx].node_value()
    }

    #[inline]
    fn node_degree(&self, node_idx: usize) -> usize {
        self.nodes[node_idx].degree()
    }

    #[inline]
    fn in_edges_of<'b>(&'b self, node_idx: usize) -> &'b Self::EDGE {
        &&self.nodes[node_idx].in_edges
    }

    #[inline]
    fn out_edges_of<'b>(&'b self, node_idx: usize) -> &'b Self::EDGE {
        &self.nodes[node_idx].out_edges
    }
}

pub struct GraphBuilder<K: Ord, T: Debug + Clone> {
    // maps node_id to index in node_in_edges/node_out_edges.
    node_map: BTreeMap<K, usize>,
    graph: OwnedGraph<T>,
}

impl<K: Ord, T: Debug + Clone> GraphBuilder<K, T> {
    pub fn new() -> GraphBuilder<K, T> {
        GraphBuilder {
            node_map: BTreeMap::new(),
            graph: OwnedGraph::new(Vec::new()),
        }
    }

    pub fn graph(self) -> OwnedGraph<T> {
        self.graph
    }

    /// Panics if `node_id` already exists.
    pub fn add_node(&mut self, node_id: K, node_value: T) -> usize {
        match self.node_map.entry(node_id) {
            Entry::Vacant(e) => {
                let next_id = self.graph.push_empty_node(node_value);
                e.insert(next_id);
                return next_id;
            }
            Entry::Occupied(_) => {
                panic!();
            }
        }
    }

    pub fn add_edge_unweighted(&mut self, source_node_id: K, target_node_id: K) {
        self.add_edge(source_node_id, target_node_id, Closed01::zero());
    }

    pub fn add_edge(&mut self, source_node_id: K, target_node_id: K, weight: EdgeWeight) {
        let source_index = *self.node_map.get(&source_node_id).unwrap();
        let target_index = *self.node_map.get(&target_node_id).unwrap();
        self.graph.nodes[source_index].add_out_edge(Edge::new(target_index, weight));
        self.graph.nodes[target_index].add_in_edge(Edge::new(source_index, weight));
    }
}
<commit_msg>Add OwnedGraph#nodes() accessor<commit_after>use super::traits::{EdgeWeight, Edges, Graph};
use closed01::Closed01;
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use petgraph::{EdgeDirection, Directed};
use petgraph::Graph as PetGraph;
use std::fmt::Debug;

#[derive(Debug)]
pub struct Edge {
    /// Node index type. Our graphs never exceed 4 billion nodes.
    pointing_node: u32,
    weight: EdgeWeight,
}

impl Edge {
    pub fn new_unweighted(node_idx: usize) -> Edge {
        Edge::new(node_idx, Closed01::zero())
    }

    pub fn new(node_idx: usize, weight: EdgeWeight) -> Edge {
        assert!(node_idx <= u32::max_value() as usize);
        Edge {
            pointing_node: node_idx as u32,
            weight: weight,
        }
    }
}

#[derive(Debug)]
pub struct EdgeList {
    edges: Vec<Edge>,
}

impl EdgeList {
    pub fn new(edges: Vec<Edge>) -> EdgeList {
        EdgeList { edges: edges }
    }
}

impl Edges for EdgeList {
    #[inline]
    fn num_edges(&self) -> usize {
        self.edges.len()
    }

    #[inline]
    fn nth_edge(&self, n: usize) -> Option<usize> {
        self.edges.get(n).map(|n| n.pointing_node as usize)
    }

    #[inline]
    fn nth_edge_weight(&self, n: usize) -> Option<EdgeWeight> {
        self.edges.get(n).map(|n| n.weight)
    }
}

#[derive(Debug)]
pub struct Node<T: Debug + Clone> {
    in_edges: EdgeList,
    out_edges: EdgeList,
    node_value: T,
}

impl<T: Debug + Clone> Node<T> {
    pub fn new(in_edges: EdgeList, out_edges: EdgeList, node_value: T) -> Node<T> {
        Node {
            in_edges: in_edges,
            out_edges: out_edges,
            node_value: node_value,
        }
    }

    pub fn node_value(&self) -> &T {
        &self.node_value
    }

    pub fn add_in_edge(&mut self, edge: Edge) {
        self.in_edges.edges.push(edge);
    }

    pub fn add_out_edge(&mut self, edge: Edge) {
        self.out_edges.edges.push(edge);
    }

    fn degree(&self) -> usize {
        self.in_edges.num_edges() + self.out_edges.num_edges()
    }
}

#[derive(Debug)]
pub struct OwnedGraph<T: Debug + Clone> {
    nodes: Vec<Node<T>>,
}

impl<T: Debug + Clone> OwnedGraph<T> {
    pub fn new(nodes: Vec<Node<T>>) -> OwnedGraph<T> {
        OwnedGraph { nodes: nodes }
    }

    pub fn nodes(&self) -> &[Node<T>] {
        &self.nodes
    }

    pub fn from_petgraph(pg: &PetGraph<T, EdgeWeight, Directed>) -> OwnedGraph<T> {
        OwnedGraph {
            nodes: pg.node_indices()
                     .map(|i| {
                         Node::new(EdgeList::new(pg.edges_directed(i, EdgeDirection::Incoming)
                                                   .map(|(j, &w)| Edge::new(j.index(), w))
                                                   .collect()),
                                   EdgeList::new(pg.edges_directed(i, EdgeDirection::Outgoing)
                                                   .map(|(j, &w)| Edge::new(j.index(), w))
                                                   .collect()),
                                   pg.node_weight(i).unwrap().clone())
                     })
                     .collect(),
        }
    }

    pub fn len(&self) -> usize {
        self.nodes.len()
    }

    pub fn push_empty_node(&mut self, node_value: T) -> usize {
        let idx = self.nodes.len();
        self.nodes.push(Node::new(EdgeList::new(Vec::new()),
                                  EdgeList::new(Vec::new()),
                                  node_value));
        return idx;
    }
}

impl<T: Debug + Clone> Graph for OwnedGraph<T> {
    type EDGE = EdgeList;
    type NODE = T;
    fn num_nodes(&self) -> usize {
        self.nodes.len()
    }

    #[inline]
    fn node_value(&self, node_idx: usize) -> &Self::NODE {
        self.nodes[node_idx].node_value()
    }

    #[inline]
    fn node_degree(&self, node_idx: usize) -> usize {
        self.nodes[node_idx].degree()
    }

    #[inline]
    fn in_edges_of<'b>(&'b self, node_idx: usize) -> &'b Self::EDGE {
        &&self.nodes[node_idx].in_edges
    }

    #[inline]
    fn out_edges_of<'b>(&'b self, node_idx: usize) -> &'b Self::EDGE {
        &self.nodes[node_idx].out_edges
    }
}

pub struct GraphBuilder<K: Ord, T: Debug + Clone> {
    // maps node_id to index in node_in_edges/node_out_edges.
    node_map: BTreeMap<K, usize>,
    graph: OwnedGraph<T>,
}

impl<K: Ord, T: Debug + Clone> GraphBuilder<K, T> {
    pub fn new() -> GraphBuilder<K, T> {
        GraphBuilder {
            node_map: BTreeMap::new(),
            graph: OwnedGraph::new(Vec::new()),
        }
    }

    pub fn graph(self) -> OwnedGraph<T> {
        self.graph
    }

    /// Panics if `node_id` already exists.
    pub fn add_node(&mut self, node_id: K, node_value: T) -> usize {
        match self.node_map.entry(node_id) {
            Entry::Vacant(e) => {
                let next_id = self.graph.push_empty_node(node_value);
                e.insert(next_id);
                return next_id;
            }
            Entry::Occupied(_) => {
                panic!();
            }
        }
    }

    pub fn add_edge_unweighted(&mut self, source_node_id: K, target_node_id: K) {
        self.add_edge(source_node_id, target_node_id, Closed01::zero());
    }

    pub fn add_edge(&mut self, source_node_id: K, target_node_id: K, weight: EdgeWeight) {
        let source_index = *self.node_map.get(&source_node_id).unwrap();
        let target_index = *self.node_map.get(&target_node_id).unwrap();
        self.graph.nodes[source_index].add_out_edge(Edge::new(target_index, weight));
        self.graph.nodes[target_index].add_in_edge(Edge::new(source_index, weight));
    }
}
<|endoftext|>


<commit_before>use macros::hashmap;
use std::collections::HashMap;

#[test]
fn test_empty() {
    let expected: HashMap<u32, u32> = HashMap::new();
    let computed: HashMap<u32, u32> = hashmap!();
    assert_eq!(computed, expected);
}

#[test]
#[ignore]
fn test_single() {
    let mut expected = HashMap::new();
    expected.insert(1, "one");
    assert_eq!(hashmap!(1 => "one"), expected);
}

#[test]
#[ignore]
fn test_no_trailing_comma() {
    let mut expected = HashMap::new();
    expected.insert(1, "one");
    expected.insert(2, "two");
    assert_eq!(hashmap!(1 => "one", 2 => "two"), expected);
}

#[test]
#[ignore]
fn test_trailing_comma() {
    let mut expected = HashMap::new();
    expected.insert('h', 89);
    expected.insert('a', 1);
    expected.insert('s', 19);
    expected.insert('h', 8);
    assert_eq!(
        hashmap!(
            'h' => 89,
            'a' => 1,
            's' => 19,
            'h' => 8,
        ),
        expected
    );
}

#[test]
#[ignore]
fn test_nested() {
    let mut expected = HashMap::new();
    expected.insert("non-empty", {
        let mut subhashmap = HashMap::new();
        subhashmap.insert(23, 623);
        subhashmap.insert(34, 21);
        subhashmap
    });
    expected.insert("empty", HashMap::new());
    assert_eq!(
        hashmap!(
            "non-empty" => hashmap!(
                23 => 623,
                34 => 21
            ),
            "empty" => hashmap!()
        ),
        expected
    );
}

mod test {
    #[test]
    #[ignore]
    fn type_not_in_scope() {
        use macros::hashmap;

        let _empty: ::std::collections::HashMap<(), ()> = hashmap!();
        let _expected = hashmap!(23=> 623, 34 => 21);
    }

    #[test]
    #[ignore]
    fn test_macro_out_of_scope() {
        let _expected = macros::hashmap!(23 => 623, 34 => 21,);
    }
}

#[test]
#[ignore]
fn test_type_override() {
    // The macro should always use std::collections::HashMap and ignore crate::std::collections::HashMap
    mod std {
        pub mod collections {
            pub struct HashMap;

            impl HashMap {
                #[allow(dead_code)]
                pub fn new() -> Self {
                    panic!("Do not allow users to override which HashMap is used");
                }

                #[allow(dead_code)]
                pub fn insert<K, V>(&mut self, _key: K, _val: V) {
                    panic!("Do not allow users to override which HashMap is used");
                }
            }
        }
    }

    let _computed = hashmap!(1 => 2, 3 => 4);
}

#[test]
#[ignore]
fn test_compile_fails_comma_sep() {
    simple_trybuild::compile_fail("comma-sep.rs");
}

#[test]
#[ignore]
fn test_compile_fails_double_commas() {
    simple_trybuild::compile_fail("double-commas.rs");
}

#[test]
#[ignore]
fn test_compile_fails_only_comma() {
    simple_trybuild::compile_fail("only-comma.rs");
}

#[test]
#[ignore]
fn test_compile_fails_single_argument() {
    simple_trybuild::compile_fail("single-argument.rs");
}

#[test]
#[ignore]
fn test_compile_fails_triple_arguments() {
    simple_trybuild::compile_fail("triple-arguments.rs");
}

#[test]
#[ignore]
fn test_compile_fails_only_arrow() {
    simple_trybuild::compile_fail("only-arrow.rs");
}

#[test]
#[ignore]
fn test_compile_fails_two_arrows() {
    simple_trybuild::compile_fail("two-arrows.rs");
}

#[test]
#[ignore]
fn test_compile_fails_leading_comma() {
    simple_trybuild::compile_fail("leading-comma.rs");
}

mod simple_trybuild {
    use std::path::PathBuf;
    use std::process::Command;

    pub fn compile_fail(file_name: &str) {
        let invalid_path: PathBuf = ["tests", "invalid"].iter().collect::<PathBuf>();

        let mut file_path = invalid_path.clone();
        file_path.push(file_name);
        assert!(
            file_path.exists(),
            "{:?} does not exist.",
            file_path.into_os_string()
        );

        let test_name = file_name.replace(".", "-");
        let macros_dir = ["..", "..", "target", "tests", "macros"]
            .iter()
            .collect::<PathBuf>();

        let result = Command::new("cargo")
            .current_dir(invalid_path)
            .arg("build")
            .arg("--offline")
            .arg("--target-dir")
            .arg(macros_dir)
            .arg("--bin")
            .arg(test_name)
            .output();

        if let Ok(result) = result {
            assert!(
                !result.status.success(),
                "Expected {:?} to fail to compile, but it succeeded.",
                file_path
            );
        } else {
            panic!("Running subprocess failed.");
        }
    }
}
<commit_msg>macros: Check for additional scoped syntax (#948)<commit_after>use macros::hashmap;
use std::collections::HashMap;

#[test]
fn test_empty() {
    let expected: HashMap<u32, u32> = HashMap::new();
    let computed: HashMap<u32, u32> = hashmap!();
    assert_eq!(computed, expected);
}

#[test]
#[ignore]
fn test_single() {
    let mut expected = HashMap::new();
    expected.insert(1, "one");
    assert_eq!(hashmap!(1 => "one"), expected);
}

#[test]
#[ignore]
fn test_no_trailing_comma() {
    let mut expected = HashMap::new();
    expected.insert(1, "one");
    expected.insert(2, "two");
    assert_eq!(hashmap!(1 => "one", 2 => "two"), expected);
}

#[test]
#[ignore]
fn test_trailing_comma() {
    let mut expected = HashMap::new();
    expected.insert('h', 89);
    expected.insert('a', 1);
    expected.insert('s', 19);
    expected.insert('h', 8);
    assert_eq!(
        hashmap!(
            'h' => 89,
            'a' => 1,
            's' => 19,
            'h' => 8,
        ),
        expected
    );
}

#[test]
#[ignore]
fn test_nested() {
    let mut expected = HashMap::new();
    expected.insert("non-empty", {
        let mut subhashmap = HashMap::new();
        subhashmap.insert(23, 623);
        subhashmap.insert(34, 21);
        subhashmap
    });
    expected.insert("empty", HashMap::new());
    assert_eq!(
        hashmap!(
            "non-empty" => hashmap!(
                23 => 623,
                34 => 21
            ),
            "empty" => hashmap!()
        ),
        expected
    );
}

mod test {
    #[test]
    #[ignore]
    fn type_not_in_scope() {
        use macros::hashmap;

        let _empty: ::std::collections::HashMap<(), ()> = hashmap!();
        let _without_comma = hashmap!(23=> 623, 34 => 21);
        let _with_trailing = hashmap!(23 => 623, 34 => 21,);
    }

    #[test]
    #[ignore]
    fn test_macro_out_of_scope() {
        let _empty: ::std::collections::HashMap<(), ()> = macros::hashmap!();
        let _without_comma = macros::hashmap!(23=> 623, 34 => 21);
        let _with_trailing = macros::hashmap!(23 => 623, 34 => 21,);
    }
}

#[test]
#[ignore]
fn test_type_override() {
    // The macro should always use std::collections::HashMap and ignore crate::std::collections::HashMap
    mod std {
        pub mod collections {
            pub struct HashMap;

            impl HashMap {
                #[allow(dead_code)]
                pub fn new() -> Self {
                    panic!("Do not allow users to override which HashMap is used");
                }

                #[allow(dead_code)]
                pub fn insert<K, V>(&mut self, _key: K, _val: V) {
                    panic!("Do not allow users to override which HashMap is used");
                }
            }
        }
    }

    let _computed = hashmap!(1 => 2, 3 => 4);
}

#[test]
#[ignore]
fn test_compile_fails_comma_sep() {
    simple_trybuild::compile_fail("comma-sep.rs");
}

#[test]
#[ignore]
fn test_compile_fails_double_commas() {
    simple_trybuild::compile_fail("double-commas.rs");
}

#[test]
#[ignore]
fn test_compile_fails_only_comma() {
    simple_trybuild::compile_fail("only-comma.rs");
}

#[test]
#[ignore]
fn test_compile_fails_single_argument() {
    simple_trybuild::compile_fail("single-argument.rs");
}

#[test]
#[ignore]
fn test_compile_fails_triple_arguments() {
    simple_trybuild::compile_fail("triple-arguments.rs");
}

#[test]
#[ignore]
fn test_compile_fails_only_arrow() {
    simple_trybuild::compile_fail("only-arrow.rs");
}

#[test]
#[ignore]
fn test_compile_fails_two_arrows() {
    simple_trybuild::compile_fail("two-arrows.rs");
}

#[test]
#[ignore]
fn test_compile_fails_leading_comma() {
    simple_trybuild::compile_fail("leading-comma.rs");
}

mod simple_trybuild {
    use std::path::PathBuf;
    use std::process::Command;

    pub fn compile_fail(file_name: &str) {
        let invalid_path: PathBuf = ["tests", "invalid"].iter().collect::<PathBuf>();

        let mut file_path = invalid_path.clone();
        file_path.push(file_name);
        assert!(
            file_path.exists(),
            "{:?} does not exist.",
            file_path.into_os_string()
        );

        let test_name = file_name.replace(".", "-");
        let macros_dir = ["..", "..", "target", "tests", "macros"]
            .iter()
            .collect::<PathBuf>();

        let result = Command::new("cargo")
            .current_dir(invalid_path)
            .arg("build")
            .arg("--offline")
            .arg("--target-dir")
            .arg(macros_dir)
            .arg("--bin")
            .arg(test_name)
            .output();

        if let Ok(result) = result {
            assert!(
                !result.status.success(),
                "Expected {:?} to fail to compile, but it succeeded.",
                file_path
            );
        } else {
            panic!("Running subprocess failed.");
        }
    }
}
<|endoftext|>


<commit_before>use nom::{be_u16, be_u32, be_u8, Err, ErrorKind};

use attribute_info::types::StackMapFrame::*;
use attribute_info::*;

pub fn attribute_parser(input: &[u8]) -> Result<(&[u8], AttributeInfo), Err<&[u8]>> {
    do_parse!(
        input,
        attribute_name_index: be_u16
            >> attribute_length: be_u32
            >> info: take!(attribute_length)
            >> (AttributeInfo {
                attribute_name_index: attribute_name_index,
                attribute_length: attribute_length,
                info: info.to_owned(),
            })
    )
}

pub fn exception_entry_parser(input: &[u8]) -> Result<(&[u8], ExceptionEntry), Err<&[u8]>> {
    do_parse!(
        input,
        start_pc: be_u16
            >> end_pc: be_u16
            >> handler_pc: be_u16
            >> catch_type: be_u16
            >> (ExceptionEntry {
                start_pc: start_pc,
                end_pc: end_pc,
                handler_pc: handler_pc,
                catch_type: catch_type,
            })
    )
}

pub fn code_attribute_parser(input: &[u8]) -> Result<(&[u8], CodeAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        max_stack: be_u16
            >> max_locals: be_u16
            >> code_length: be_u32
            >> code: take!(code_length)
            >> exception_table_length: be_u16
            >> exception_table: count!(exception_entry_parser, exception_table_length as usize)
            >> attributes_count: be_u16
            >> attributes: count!(attribute_parser, attributes_count as usize)
            >> (CodeAttribute {
                max_stack: max_stack,
                max_locals: max_locals,
                code_length: code_length,
                code: code.to_owned(),
                exception_table_length: exception_table_length,
                exception_table: exception_table,
                attributes_count: attributes_count,
                attributes: attributes,
            })
    )
}

fn same_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    value!(input, SameFrame { frame_type })
}

fn verification_type(v: u8) -> Option<VerificationTypeInfo> {
    use self::VerificationTypeInfo::*;
    match v {
        0 => Some(Top),
        1 => Some(Integer),
        2 => Some(Float),
        3 => Some(Double),
        4 => Some(Long),
        5 => Some(Null),
        6 => Some(UninitializedThis),
        7 => Some(Object),
        8 => Some(Uninitialized),
        _ => None,
    }
}

fn verification_type_parser(input: &[u8]) -> Result<(&[u8], VerificationTypeInfo), Err<&[u8]>> {
    match verification_type(input[0]) {
        Some(x) => Result::Ok((&input[1..], x)),
        _ => Result::Err(Err::Error(error_position!(input, ErrorKind::Custom(1)))),
    }
}

fn same_locals_1_stack_item_frame_parser(
    input: &[u8],
    frame_type: u8,
) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        stack: verification_type_parser >> (SameLocals1StackItemFrame { frame_type, stack })
    )
}

fn same_locals_1_stack_item_frame_extended_parser(
    input: &[u8],
    frame_type: u8,
) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> stack: verification_type_parser
            >> (SameLocals1StackItemFrameExtended {
                frame_type,
                offset_delta,
                stack
            })
    )
}

fn chop_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> (ChopFrame {
                frame_type,
                offset_delta
            })
    )
}

fn same_frame_extended_parser(
    input: &[u8],
    frame_type: u8,
) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> (SameFrameExtended {
                frame_type,
                offset_delta
            })
    )
}

fn append_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> locals: count!(verification_type_parser, (frame_type - 251) as usize)
            >> (AppendFrame {
                frame_type,
                offset_delta,
                locals
            })
    )
}

fn full_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> number_of_locals: be_u16
            >> locals: count!(verification_type_parser, number_of_locals as usize)
            >> number_of_stack_items: be_u16
            >> stack: count!(verification_type_parser, number_of_stack_items as usize)
            >> (FullFrame {
                frame_type,
                offset_delta,
                number_of_locals,
                locals,
                number_of_stack_items,
                stack,
            })
    )
}

fn stack_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    match frame_type {
        0...63 => same_frame_parser(input, frame_type),
        64...127 => same_locals_1_stack_item_frame_parser(input, frame_type),
        247 => same_locals_1_stack_item_frame_extended_parser(input, frame_type),
        248...250 => chop_frame_parser(input, frame_type),
        251 => same_frame_extended_parser(input, frame_type),
        252...254 => append_frame_parser(input, frame_type),
        255 => full_frame_parser(input, frame_type),
        _ => Result::Err(Err::Error(error_position!(input, ErrorKind::Custom(2)))),
    }
}

fn stack_map_frame_entry_parser(input: &[u8]) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        frame_type: be_u8 >> stack_frame: apply!(stack_frame_parser, frame_type) >> (stack_frame)
    )
}

pub fn stack_map_table_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], StackMapTableAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        number_of_entries: be_u16
            >> entries: count!(stack_map_frame_entry_parser, number_of_entries as usize)
            >> (StackMapTableAttribute {
                number_of_entries,
                entries,
            })
    )
}

pub fn exceptions_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], ExceptionsAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        exception_table_length: be_u16
            >> exception_table: count!(be_u16, exception_table_length as usize)
            >> (ExceptionsAttribute {
                exception_table_length: exception_table_length,
                exception_table: exception_table,
            })
    )
}

pub fn constant_value_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], ConstantValueAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        constant_value_index: be_u16
            >> (ConstantValueAttribute {
                constant_value_index: constant_value_index,
            })
    )
}

fn bootstrap_method_parser(input: &[u8]) -> Result<(&[u8], BootstrapMethod), Err<&[u8]>> {
    do_parse!(
        input,
        bootstrap_method_ref: be_u16
            >> num_bootstrap_arguments: be_u16
            >> bootstrap_arguments: count!(be_u16, num_bootstrap_arguments as usize)
            >> (BootstrapMethod {
                bootstrap_method_ref,
                num_bootstrap_arguments,
                bootstrap_arguments,
            })
    )
}

pub fn bootstrap_methods_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], BootstrapMethodsAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        num_bootstrap_methods: be_u16
            >> bootstrap_methods: count!(bootstrap_method_parser, num_bootstrap_methods as usize)
            >> (BootstrapMethodsAttribute {
                num_bootstrap_methods,
                bootstrap_methods,
            })
    )
}

pub fn sourcefile_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], SourceFileAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        attribute_name_index: be_u16
            >> attribute_length: be_u32
            >> sourcefile_index: be_u16
            >> (SourceFileAttribute {
                attribute_name_index,
                attribute_length,
                sourcefile_index
            })
    )
}
<commit_msg>Prefer `..=` over deprecated `...`<commit_after>use nom::{be_u16, be_u32, be_u8, Err, ErrorKind};

use attribute_info::types::StackMapFrame::*;
use attribute_info::*;

pub fn attribute_parser(input: &[u8]) -> Result<(&[u8], AttributeInfo), Err<&[u8]>> {
    do_parse!(
        input,
        attribute_name_index: be_u16
            >> attribute_length: be_u32
            >> info: take!(attribute_length)
            >> (AttributeInfo {
                attribute_name_index: attribute_name_index,
                attribute_length: attribute_length,
                info: info.to_owned(),
            })
    )
}

pub fn exception_entry_parser(input: &[u8]) -> Result<(&[u8], ExceptionEntry), Err<&[u8]>> {
    do_parse!(
        input,
        start_pc: be_u16
            >> end_pc: be_u16
            >> handler_pc: be_u16
            >> catch_type: be_u16
            >> (ExceptionEntry {
                start_pc: start_pc,
                end_pc: end_pc,
                handler_pc: handler_pc,
                catch_type: catch_type,
            })
    )
}

pub fn code_attribute_parser(input: &[u8]) -> Result<(&[u8], CodeAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        max_stack: be_u16
            >> max_locals: be_u16
            >> code_length: be_u32
            >> code: take!(code_length)
            >> exception_table_length: be_u16
            >> exception_table: count!(exception_entry_parser, exception_table_length as usize)
            >> attributes_count: be_u16
            >> attributes: count!(attribute_parser, attributes_count as usize)
            >> (CodeAttribute {
                max_stack: max_stack,
                max_locals: max_locals,
                code_length: code_length,
                code: code.to_owned(),
                exception_table_length: exception_table_length,
                exception_table: exception_table,
                attributes_count: attributes_count,
                attributes: attributes,
            })
    )
}

fn same_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    value!(input, SameFrame { frame_type })
}

fn verification_type(v: u8) -> Option<VerificationTypeInfo> {
    use self::VerificationTypeInfo::*;
    match v {
        0 => Some(Top),
        1 => Some(Integer),
        2 => Some(Float),
        3 => Some(Double),
        4 => Some(Long),
        5 => Some(Null),
        6 => Some(UninitializedThis),
        7 => Some(Object),
        8 => Some(Uninitialized),
        _ => None,
    }
}

fn verification_type_parser(input: &[u8]) -> Result<(&[u8], VerificationTypeInfo), Err<&[u8]>> {
    match verification_type(input[0]) {
        Some(x) => Result::Ok((&input[1..], x)),
        _ => Result::Err(Err::Error(error_position!(input, ErrorKind::Custom(1)))),
    }
}

fn same_locals_1_stack_item_frame_parser(
    input: &[u8],
    frame_type: u8,
) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        stack: verification_type_parser >> (SameLocals1StackItemFrame { frame_type, stack })
    )
}

fn same_locals_1_stack_item_frame_extended_parser(
    input: &[u8],
    frame_type: u8,
) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> stack: verification_type_parser
            >> (SameLocals1StackItemFrameExtended {
                frame_type,
                offset_delta,
                stack
            })
    )
}

fn chop_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> (ChopFrame {
                frame_type,
                offset_delta
            })
    )
}

fn same_frame_extended_parser(
    input: &[u8],
    frame_type: u8,
) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> (SameFrameExtended {
                frame_type,
                offset_delta
            })
    )
}

fn append_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> locals: count!(verification_type_parser, (frame_type - 251) as usize)
            >> (AppendFrame {
                frame_type,
                offset_delta,
                locals
            })
    )
}

fn full_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        offset_delta: be_u16
            >> number_of_locals: be_u16
            >> locals: count!(verification_type_parser, number_of_locals as usize)
            >> number_of_stack_items: be_u16
            >> stack: count!(verification_type_parser, number_of_stack_items as usize)
            >> (FullFrame {
                frame_type,
                offset_delta,
                number_of_locals,
                locals,
                number_of_stack_items,
                stack,
            })
    )
}

fn stack_frame_parser(input: &[u8], frame_type: u8) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    match frame_type {
        0..=63 => same_frame_parser(input, frame_type),
        64..=127 => same_locals_1_stack_item_frame_parser(input, frame_type),
        247 => same_locals_1_stack_item_frame_extended_parser(input, frame_type),
        248..=250 => chop_frame_parser(input, frame_type),
        251 => same_frame_extended_parser(input, frame_type),
        252..=254 => append_frame_parser(input, frame_type),
        255 => full_frame_parser(input, frame_type),
        _ => Result::Err(Err::Error(error_position!(input, ErrorKind::Custom(2)))),
    }
}

fn stack_map_frame_entry_parser(input: &[u8]) -> Result<(&[u8], StackMapFrame), Err<&[u8]>> {
    do_parse!(
        input,
        frame_type: be_u8 >> stack_frame: apply!(stack_frame_parser, frame_type) >> (stack_frame)
    )
}

pub fn stack_map_table_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], StackMapTableAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        number_of_entries: be_u16
            >> entries: count!(stack_map_frame_entry_parser, number_of_entries as usize)
            >> (StackMapTableAttribute {
                number_of_entries,
                entries,
            })
    )
}

pub fn exceptions_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], ExceptionsAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        exception_table_length: be_u16
            >> exception_table: count!(be_u16, exception_table_length as usize)
            >> (ExceptionsAttribute {
                exception_table_length: exception_table_length,
                exception_table: exception_table,
            })
    )
}

pub fn constant_value_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], ConstantValueAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        constant_value_index: be_u16
            >> (ConstantValueAttribute {
                constant_value_index: constant_value_index,
            })
    )
}

fn bootstrap_method_parser(input: &[u8]) -> Result<(&[u8], BootstrapMethod), Err<&[u8]>> {
    do_parse!(
        input,
        bootstrap_method_ref: be_u16
            >> num_bootstrap_arguments: be_u16
            >> bootstrap_arguments: count!(be_u16, num_bootstrap_arguments as usize)
            >> (BootstrapMethod {
                bootstrap_method_ref,
                num_bootstrap_arguments,
                bootstrap_arguments,
            })
    )
}

pub fn bootstrap_methods_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], BootstrapMethodsAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        num_bootstrap_methods: be_u16
            >> bootstrap_methods: count!(bootstrap_method_parser, num_bootstrap_methods as usize)
            >> (BootstrapMethodsAttribute {
                num_bootstrap_methods,
                bootstrap_methods,
            })
    )
}

pub fn sourcefile_attribute_parser(
    input: &[u8],
) -> Result<(&[u8], SourceFileAttribute), Err<&[u8]>> {
    do_parse!(
        input,
        attribute_name_index: be_u16
            >> attribute_length: be_u32
            >> sourcefile_index: be_u16
            >> (SourceFileAttribute {
                attribute_name_index,
                attribute_length,
                sourcefile_index
            })
    )
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::cell::UnsafeCell;
use std::thread;

const MAX_BUF_SZ: usize = 1_000_000;
const N_BUFS: usize = 8;

struct IOBufs {
    log_offset: Arc<AtomicUsize>,
    bufs: [Arc<UnsafeCell<Vec<u8>>>; N_BUFS],
    headers: [Arc<AtomicUsize>; N_BUFS],
    current_buf: Arc<AtomicUsize>,
    written_bufs: Arc<AtomicUsize>,
}

impl Clone for IOBufs {
    fn clone(&self) -> IOBufs {
        IOBufs {
            log_offset: self.log_offset.clone(),
            bufs: [self.bufs[0].clone(),
                   self.bufs[1].clone(),
                   self.bufs[2].clone(),
                   self.bufs[3].clone(),
                   self.bufs[4].clone(),
                   self.bufs[5].clone(),
                   self.bufs[6].clone(),
                   self.bufs[7].clone()],
            headers: [self.headers[0].clone(),
                      self.headers[1].clone(),
                      self.headers[2].clone(),
                      self.headers[3].clone(),
                      self.headers[4].clone(),
                      self.headers[5].clone(),
                      self.headers[6].clone(),
                      self.headers[7].clone()],
            current_buf: self.current_buf.clone(),
            written_bufs: self.written_bufs.clone(),
        }
    }
}

unsafe impl Send for IOBufs {}

unsafe impl Sync for IOBufs {}

struct Reservation {
    offset: u32,
    len: u32, // this may be different from header, due to concurrent access
    buf: Arc<UnsafeCell<Vec<u8>>>,
    last_hv: u32,
    header: Arc<AtomicUsize>,
    current_buf: Arc<AtomicUsize>,
    written_bufs: Arc<AtomicUsize>,
}

impl Default for IOBufs {
    fn default() -> IOBufs {
        let mut bufs = [Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ]))];
        let headers = [Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0))];
        IOBufs {
            log_offset: Arc::new(AtomicUsize::new(0)),
            bufs: bufs,
            headers: headers,
            current_buf: Arc::new(AtomicUsize::new(0)),
            written_bufs: Arc::new(AtomicUsize::new(0)),
        }
    }
}

impl IOBufs {
    fn reserve(&self, len: u32) -> Reservation {
        loop {
            // load atomic progress counters
            let current_buf = self.current_buf.load(Ordering::SeqCst);
            let written = self.written_bufs.load(Ordering::SeqCst);
            let idx = current_buf % N_BUFS;

            // if written is too far behind, we need to
            // spin while it catches up
            if current_buf - written >= N_BUFS {
                continue;
            }

            // load current header value
            let header = self.headers[idx].clone();
            let mut hv = header.load(Ordering::SeqCst) as u32;

            // skip if already sealed
            if ops::is_sealed(hv) {
                // already sealed, start over and hope cur
                // has already been bumped by sealer.
                continue;
            }

            // try to claim space, seal otherwise
            let offset = ops::offset(hv);
            assert!(len >> 24 == 0);
            if offset + len > MAX_BUF_SZ as u32 {
                // attempt seal once, then start over
                let sealed = ops::mk_sealed(hv);
                if header.compare_and_swap(hv as usize, sealed as usize, Ordering::SeqCst) ==
                   hv as usize {
                    // we succeeded in setting seal, so we get to bump cur
                    self.current_buf.fetch_add(1, Ordering::SeqCst);
                    let n_writers = ops::n_writers(hv);
                    if n_writers == 0 {
                        // nobody else is going to flush this, so we need to
                        let res = self.reservation(offset, len, idx, sealed, header);
                        res.write(vec![]);
                    }
                }
                continue;
            } else {
                // attempt to claim
                let claimed = ops::incr_writers(ops::bump_offset(hv, len));
                if header.compare_and_swap(hv as usize, claimed as usize, Ordering::SeqCst) !=
                   hv as usize {
                    // CAS failed, start over
                    continue;
                }
                hv = claimed;
            }

            let n_writers = ops::n_writers(hv);
            assert!(n_writers != 0);

            return self.reservation(offset, len, idx, hv, header);
        }
    }

    fn reservation(&self,
                   offset: u32,
                   len: u32,
                   idx: usize,
                   last_hv: u32,
                   header: Arc<AtomicUsize>)
                   -> Reservation {
        return Reservation {
            offset: offset,
            len: len,
            buf: self.bufs[idx].clone(),
            last_hv: last_hv,
            header: header,
            current_buf: self.current_buf.clone(),
            written_bufs: self.written_bufs.clone(),
        };
    }

    pub fn write(&self, buf: Vec<u8>) {
        let res = self.reserve(buf.len() as u32);
        res.write(buf);
    }
}

impl Reservation {
    fn abort_tx(&self) {
        // fills lease with a FailedFlush
    }

    fn commit_tx(&self) {}

    fn write(&self, buf: Vec<u8>) {
        let range = (self.offset as usize..(self.offset as usize + buf.len()));
        unsafe {
            let mut out_buf = (*self.buf.get()).as_mut_slice();
            (out_buf)[range].copy_from_slice(&*buf);
        }

        let mut hv = self.last_hv;
        let n_writers = ops::n_writers(hv);
        let sealed = ops::is_sealed(hv);
        if sealed && n_writers == 0 {
            return self.slam_down_pipe();
        }

        // decr writer count, retrying
        loop {
            let n_writers = ops::n_writers(hv);
            let hv2 = ops::decr_writers(hv);
            if self.header.compare_and_swap(hv as usize, hv2 as usize, Ordering::SeqCst) ==
               hv as usize {
                // we succeeded, free to exit
                // TODO cleanup
                let n_writers = ops::n_writers(hv2);
                let sealed = ops::is_sealed(hv2);
                if sealed && n_writers == 0 {
                    self.slam_down_pipe();
                }
                return;
            } else {
                // we failed, reload and retry
                hv = self.header.load(Ordering::SeqCst) as u32;
            }
        }
    }

    fn slam_down_pipe(&self) {
        // put the buf identified by idx on disk
        // TODO

        // reset the header, no need to zero the buf
        self.header.store(0, Ordering::SeqCst);

        // bump self.written by 1
        self.written_bufs.fetch_add(1, Ordering::SeqCst);
    }
}

mod ops {
    pub fn is_sealed(v: u32) -> bool {
        v >> 31 == 1
    }

    pub fn mk_sealed(v: u32) -> u32 {
        v | 1 << 31
    }

    pub fn n_writers(v: u32) -> u32 {
        v << 1 >> 25
    }

    pub fn incr_writers(v: u32) -> u32 {
        assert!(n_writers(v) != 127);
        v + (1 << 24)
    }

    pub fn decr_writers(v: u32) -> u32 {
        assert!(n_writers(v) != 0);
        v - (1 << 24)
    }

    pub fn offset(v: u32) -> u32 {
        v << 8 >> 8
    }

    pub fn bump_offset(v: u32, by: u32) -> u32 {
        assert!(by >> 24 == 0);
        v + by
    }
}

#[test]
fn basic_functionality() {
    let iobs1 = Arc::new(IOBufs::default());
    let iobs2 = iobs1.clone();
    let iobs3 = iobs1.clone();
    let t1 = thread::spawn(move || {
        for i in 0..50_000 {
            let buf = vec![1; 512];
            iobs1.write(buf);
        }
    });
    let t2 = thread::spawn(move || {
        for i in 0..50_000 {
            let buf = vec![2; 512];
            iobs2.write(buf);
        }
    });
    let t3 = thread::spawn(move || {
        for i in 0..50_000 {
            let buf = vec![3; 512];
            iobs3.write(buf);
        }
    });
    t1.join();
    t2.join();
    t3.join();
}
<commit_msg>make test a little more intense<commit_after>use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::cell::UnsafeCell;
use std::thread;

const MAX_BUF_SZ: usize = 1_000_000;
const N_BUFS: usize = 8;

struct IOBufs {
    log_offset: Arc<AtomicUsize>,
    bufs: [Arc<UnsafeCell<Vec<u8>>>; N_BUFS],
    headers: [Arc<AtomicUsize>; N_BUFS],
    current_buf: Arc<AtomicUsize>,
    written_bufs: Arc<AtomicUsize>,
}

impl Clone for IOBufs {
    fn clone(&self) -> IOBufs {
        IOBufs {
            log_offset: self.log_offset.clone(),
            bufs: [self.bufs[0].clone(),
                   self.bufs[1].clone(),
                   self.bufs[2].clone(),
                   self.bufs[3].clone(),
                   self.bufs[4].clone(),
                   self.bufs[5].clone(),
                   self.bufs[6].clone(),
                   self.bufs[7].clone()],
            headers: [self.headers[0].clone(),
                      self.headers[1].clone(),
                      self.headers[2].clone(),
                      self.headers[3].clone(),
                      self.headers[4].clone(),
                      self.headers[5].clone(),
                      self.headers[6].clone(),
                      self.headers[7].clone()],
            current_buf: self.current_buf.clone(),
            written_bufs: self.written_bufs.clone(),
        }
    }
}

unsafe impl Send for IOBufs {}

unsafe impl Sync for IOBufs {}

struct Reservation {
    offset: u32,
    len: u32, // this may be different from header, due to concurrent access
    buf: Arc<UnsafeCell<Vec<u8>>>,
    last_hv: u32,
    header: Arc<AtomicUsize>,
    current_buf: Arc<AtomicUsize>,
    written_bufs: Arc<AtomicUsize>,
}

impl Default for IOBufs {
    fn default() -> IOBufs {
        let mut bufs = [Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ])),
                        Arc::new(UnsafeCell::new(vec![0; MAX_BUF_SZ]))];
        let headers = [Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0)),
                       Arc::new(AtomicUsize::new(0))];
        IOBufs {
            log_offset: Arc::new(AtomicUsize::new(0)),
            bufs: bufs,
            headers: headers,
            current_buf: Arc::new(AtomicUsize::new(0)),
            written_bufs: Arc::new(AtomicUsize::new(0)),
        }
    }
}

impl IOBufs {
    fn reserve(&self, len: u32) -> Reservation {
        loop {
            // load atomic progress counters
            let current_buf = self.current_buf.load(Ordering::SeqCst);
            let written = self.written_bufs.load(Ordering::SeqCst);
            let idx = current_buf % N_BUFS;

            // if written is too far behind, we need to
            // spin while it catches up
            if current_buf - written >= N_BUFS {
                continue;
            }

            // load current header value
            let header = self.headers[idx].clone();
            let mut hv = header.load(Ordering::SeqCst) as u32;

            // skip if already sealed
            if ops::is_sealed(hv) {
                // already sealed, start over and hope cur
                // has already been bumped by sealer.
                continue;
            }

            // try to claim space, seal otherwise
            let offset = ops::offset(hv);
            assert!(len >> 24 == 0);
            if offset + len > MAX_BUF_SZ as u32 {
                // attempt seal once, then start over
                let sealed = ops::mk_sealed(hv);
                if header.compare_and_swap(hv as usize, sealed as usize, Ordering::SeqCst) ==
                   hv as usize {
                    // we succeeded in setting seal, so we get to bump cur
                    self.current_buf.fetch_add(1, Ordering::SeqCst);
                    let n_writers = ops::n_writers(hv);
                    if n_writers == 0 {
                        // nobody else is going to flush this, so we need to
                        let res = self.reservation(offset, len, idx, sealed, header);
                        res.write(vec![]);
                    }
                }
                continue;
            } else {
                // attempt to claim
                let claimed = ops::incr_writers(ops::bump_offset(hv, len));
                if header.compare_and_swap(hv as usize, claimed as usize, Ordering::SeqCst) !=
                   hv as usize {
                    // CAS failed, start over
                    continue;
                }
                hv = claimed;
            }

            let n_writers = ops::n_writers(hv);
            assert!(n_writers != 0);

            return self.reservation(offset, len, idx, hv, header);
        }
    }

    fn reservation(&self,
                   offset: u32,
                   len: u32,
                   idx: usize,
                   last_hv: u32,
                   header: Arc<AtomicUsize>)
                   -> Reservation {
        return Reservation {
            offset: offset,
            len: len,
            buf: self.bufs[idx].clone(),
            last_hv: last_hv,
            header: header,
            current_buf: self.current_buf.clone(),
            written_bufs: self.written_bufs.clone(),
        };
    }

    pub fn write(&self, buf: Vec<u8>) {
        let res = self.reserve(buf.len() as u32);
        res.write(buf);
    }
}

impl Reservation {
    fn abort_tx(&self) {
        // fills lease with a FailedFlush
    }

    fn commit_tx(&self) {}

    fn write(&self, buf: Vec<u8>) {
        let range = (self.offset as usize..(self.offset as usize + buf.len()));
        unsafe {
            let mut out_buf = (*self.buf.get()).as_mut_slice();
            (out_buf)[range].copy_from_slice(&*buf);
        }

        let mut hv = self.last_hv;
        let n_writers = ops::n_writers(hv);
        let sealed = ops::is_sealed(hv);
        if sealed && n_writers == 0 {
            return self.slam_down_pipe();
        }

        // decr writer count, retrying
        loop {
            let n_writers = ops::n_writers(hv);
            let hv2 = ops::decr_writers(hv);
            if self.header.compare_and_swap(hv as usize, hv2 as usize, Ordering::SeqCst) ==
               hv as usize {
                // we succeeded, free to exit
                // TODO cleanup
                let n_writers = ops::n_writers(hv2);
                let sealed = ops::is_sealed(hv2);
                if sealed && n_writers == 0 {
                    self.slam_down_pipe();
                }
                return;
            } else {
                // we failed, reload and retry
                hv = self.header.load(Ordering::SeqCst) as u32;
            }
        }
    }

    fn slam_down_pipe(&self) {
        // put the buf identified by idx on disk
        // TODO

        // reset the header, no need to zero the buf
        self.header.store(0, Ordering::SeqCst);

        // bump self.written by 1
        self.written_bufs.fetch_add(1, Ordering::SeqCst);
    }
}

mod ops {
    pub fn is_sealed(v: u32) -> bool {
        v >> 31 == 1
    }

    pub fn mk_sealed(v: u32) -> u32 {
        v | 1 << 31
    }

    pub fn n_writers(v: u32) -> u32 {
        v << 1 >> 25
    }

    pub fn incr_writers(v: u32) -> u32 {
        assert!(n_writers(v) != 127);
        v + (1 << 24)
    }

    pub fn decr_writers(v: u32) -> u32 {
        assert!(n_writers(v) != 0);
        v - (1 << 24)
    }

    pub fn offset(v: u32) -> u32 {
        v << 8 >> 8
    }

    pub fn bump_offset(v: u32, by: u32) -> u32 {
        assert!(by >> 24 == 0);
        v + by
    }
}

#[test]
fn basic_functionality() {
    let iobs1 = Arc::new(IOBufs::default());
    let iobs2 = iobs1.clone();
    let iobs3 = iobs1.clone();
    let iobs4 = iobs1.clone();
    let t1 = thread::spawn(move || {
        for i in 0..50_000 {
            let buf = vec![1; i % 8192];
            iobs1.write(buf);
        }
    });
    let t2 = thread::spawn(move || {
        for i in 0..50_000 {
            let buf = vec![2; i % 8192];
            iobs2.write(buf);
        }
    });
    let t3 = thread::spawn(move || {
        for i in 0..50_000 {
            let buf = vec![3; i % 8192];
            iobs3.write(buf);
        }
    });
    let t4 = thread::spawn(move || {
        for i in 0..50_000 {
            let buf = vec![4; i % 8192];
            iobs4.write(buf);
        }
    });
    t1.join();
    t2.join();
    t3.join();
    t4.join();
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use combine::{between, choice, many, many1, optional, parser, satisfy, satisfy_map, sep_by, try};
use combine::{Parser, Stream, ParseError, ParseResult};
use combine::char::{alpha_num, digit, char, letter, spaces, string};

use token::{Literal, Token};

pub fn lex<'a>(line: &'a str) -> Result<(Vec<Token>, &'a str), ParseError<&'a str>> {
    spaces().with(parser(token_stream))
        .parse(line)
}

fn literal<I>(input: I) -> ParseResult<Literal, I>
    where I: Stream<Item=char>
{
    let digits = many1::<String, _>(digit());
    let integer = optional(char('-'))
        .and(digits.clone())
        .map(|(sign, s)| {
            let magnitude = s.parse::<i64>().unwrap();
            if sign.is_some() { -magnitude } else { magnitude }
        })
        .map(Literal::from);

    let float = optional(char('-'))
        .and((digits.clone(), char('.'), digits.clone())
            .map(|(prefix, _, suffix)| format!("{}.{}", prefix, suffix)))
        .map(|(sign, s)| {
            let magnitude = s.parse::<f64>().unwrap();
            if sign.is_some() { -magnitude } else { magnitude }
        })
        .map(Literal::from);

    let num = try(float).or(try(integer));

    let boolean = char('#')
        .with(satisfy_map(|c| {
            match c {
                't' => Some(true),
                'f' => Some(false),
                _ => None,
            }
        }))
        .map(Literal::from);

    let non_quote = satisfy(|c| c != '"');

    let string = between(char('"'), char('"'), many::<String, _>(non_quote))
        .map(Literal::from);

    boolean.or(string).or(num)
        .parse_stream(input)
}

fn symbol<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item=char>
{
    let first = letter().or(char('_'));
    let rest = many::<String, _>(alpha_num().or(char('_')));
    first.and(rest)
        .map(|(f, mut r)| { r.insert(0, f); r })
        .map(Token::Symbol)
        .parse_stream(input)
}

fn punctuation<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item=char>
{
    let single_char_tokens = satisfy_map(|c| {
        match c {
            '(' => Some(Token::LParen),
            ')' => Some(Token::RParen),
            '[' => Some(Token::LBracket),
            ']' => Some(Token::RBracket),
            '+' => Some(Token::Plus),
            '-' => Some(Token::Minus),
            '*' => Some(Token::Star),
            '/' => Some(Token::Slash),
            '=' => Some(Token::Equal),
            '<' => Some(Token::Less),
            '>' => Some(Token::Greater),
            _ => None
        }
    });

    let two_char_tokens = choice([
        string("<="),
        string(">="),
    ]).map(|s| match s {
        "<=" => Token::LessEqual,
        ">=" => Token::GreaterEqual,
        _ => unreachable!(),
    });

    // Maximal munch: attempt parsing two-char tokens before one-char tokens
    two_char_tokens.or(single_char_tokens).parse_stream(input)
}

fn token<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item=char>
{
    parser(symbol)
        .or(parser(literal).map(Token::Literal))
        .or(parser(symbol))
        .or(parser(punctuation))
        .parse_stream(input)
}

fn token_stream<I>(input: I) -> ParseResult<Vec<Token>, I>
    where I: Stream<Item=char>
{
    sep_by(parser(token), spaces()).parse_stream(input)
}

#[cfg(test)]
mod test {
    use super::*;
    use float_cmp::ApproxEqUlps;
    use quickcheck::TestResult;

    #[test]
    fn parse_bool_literal() {
        assert_eq!(Ok((Literal::Bool(true), "")), parser(literal).parse("#t"));
        assert_eq!(Ok((Literal::Bool(false), "")), parser(literal).parse("#f"));
    }

    #[test]
    fn parse_zero_literal() {
        // Integer case
        assert_eq!(Ok((Literal::Int(0i64), "")), parser(literal).parse("0"));

        // Float case
        match parser(literal).parse("0.0") {
            Ok((Literal::Flt(flt), _)) => assert!(flt.approx_eq_ulps(&0.0f64, 4)),
            Ok(x) => assert!(false, format!("0.0 parsed as {}", x.0)),
            Err(e) => assert!(false, format!("0.0 parsed as {}", e)),
        };
    }

    #[test]
    fn parse_empty() {
        assert_eq!(Ok((Vec::new(), "")), parser(token_stream).parse(""));
    }

    quickcheck!{
        fn parse_int_literal(x: i64) -> bool {
            match parser(literal).parse(&*x.to_string()) {
                Ok((Literal::Int(y), _)) => x == y,
                _ => false,
            }
        }

        fn parse_float_literal(x: f64) -> bool {
            let mut string = x.to_string();
            if x.trunc() == x {
                string.push_str(".0");
            }

            if let Ok((Literal::Flt(y), _)) = parser(literal).parse(&*string) {
                x.approx_eq_ulps(&y, 4)
            } else {
                false
            }
        }

        fn parse_str_literal(x: String) -> TestResult {
            let string = format!("\"{}\"", x);
            if x.contains('\"') {
                return TestResult::discard()
            }
            match parser(literal).parse(&*string) {
                Ok((Literal::Str(result), _)) => TestResult::from_bool(result == x),
                _ => TestResult::failed(),
            }
        }

        fn parse_symbol(x: String) -> TestResult {
            if x.is_empty() {
                return TestResult::discard()
            }

            if !x.chars().next().unwrap().is_alphabetic() {
                return TestResult::discard()
            }

            // Test only valid symbols
            for c in x.chars() {
                if !(c.is_alphanumeric() || c == '_') {
                    return TestResult::discard()
                }
            }

            match parser(symbol).parse(&*x) {
                Ok((Token::Symbol(result), _)) => TestResult::from_bool(result == x),
                _ => TestResult::failed(),
            }
        }
    }
}
<commit_msg>Re-enable dead code lint<commit_after>use combine::{between, choice, many, many1, optional, parser, satisfy, satisfy_map, sep_by, try};
use combine::{Parser, Stream, ParseError, ParseResult};
use combine::char::{alpha_num, digit, char, letter, spaces, string};

use token::{Literal, Token};

pub fn lex<'a>(line: &'a str) -> Result<(Vec<Token>, &'a str), ParseError<&'a str>> {
    spaces().with(parser(token_stream))
        .parse(line)
}

fn literal<I>(input: I) -> ParseResult<Literal, I>
    where I: Stream<Item=char>
{
    let digits = many1::<String, _>(digit());
    let integer = optional(char('-'))
        .and(digits.clone())
        .map(|(sign, s)| {
            let magnitude = s.parse::<i64>().unwrap();
            if sign.is_some() { -magnitude } else { magnitude }
        })
        .map(Literal::from);

    let float = optional(char('-'))
        .and((digits.clone(), char('.'), digits.clone())
            .map(|(prefix, _, suffix)| format!("{}.{}", prefix, suffix)))
        .map(|(sign, s)| {
            let magnitude = s.parse::<f64>().unwrap();
            if sign.is_some() { -magnitude } else { magnitude }
        })
        .map(Literal::from);

    let num = try(float).or(try(integer));

    let boolean = char('#')
        .with(satisfy_map(|c| {
            match c {
                't' => Some(true),
                'f' => Some(false),
                _ => None,
            }
        }))
        .map(Literal::from);

    let non_quote = satisfy(|c| c != '"');

    let string = between(char('"'), char('"'), many::<String, _>(non_quote))
        .map(Literal::from);

    boolean.or(string).or(num)
        .parse_stream(input)
}

fn symbol<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item=char>
{
    let first = letter().or(char('_'));
    let rest = many::<String, _>(alpha_num().or(char('_')));
    first.and(rest)
        .map(|(f, mut r)| { r.insert(0, f); r })
        .map(Token::Symbol)
        .parse_stream(input)
}

fn punctuation<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item=char>
{
    let single_char_tokens = satisfy_map(|c| {
        match c {
            '(' => Some(Token::LParen),
            ')' => Some(Token::RParen),
            '[' => Some(Token::LBracket),
            ']' => Some(Token::RBracket),
            '+' => Some(Token::Plus),
            '-' => Some(Token::Minus),
            '*' => Some(Token::Star),
            '/' => Some(Token::Slash),
            '=' => Some(Token::Equal),
            '<' => Some(Token::Less),
            '>' => Some(Token::Greater),
            _ => None
        }
    });

    let two_char_tokens = choice([
        string("<="),
        string(">="),
    ]).map(|s| match s {
        "<=" => Token::LessEqual,
        ">=" => Token::GreaterEqual,
        _ => unreachable!(),
    });

    // Maximal munch: attempt parsing two-char tokens before one-char tokens
    two_char_tokens.or(single_char_tokens).parse_stream(input)
}

fn token<I>(input: I) -> ParseResult<Token, I>
    where I: Stream<Item=char>
{
    parser(symbol)
        .or(parser(literal).map(Token::Literal))
        .or(parser(symbol))
        .or(parser(punctuation))
        .parse_stream(input)
}

fn token_stream<I>(input: I) -> ParseResult<Vec<Token>, I>
    where I: Stream<Item=char>
{
    sep_by(parser(token), spaces()).parse_stream(input)
}

#[cfg(test)]
mod test {
    use super::*;
    use float_cmp::ApproxEqUlps;
    use quickcheck::TestResult;

    #[test]
    fn parse_bool_literal() {
        assert_eq!(Ok((Literal::Bool(true), "")), parser(literal).parse("#t"));
        assert_eq!(Ok((Literal::Bool(false), "")), parser(literal).parse("#f"));
    }

    #[test]
    fn parse_zero_literal() {
        // Integer case
        assert_eq!(Ok((Literal::Int(0i64), "")), parser(literal).parse("0"));

        // Float case
        match parser(literal).parse("0.0") {
            Ok((Literal::Flt(flt), _)) => assert!(flt.approx_eq_ulps(&0.0f64, 4)),
            Ok(x) => assert!(false, format!("0.0 parsed as {}", x.0)),
            Err(e) => assert!(false, format!("0.0 parsed as {}", e)),
        };
    }

    #[test]
    fn parse_empty() {
        assert_eq!(Ok((Vec::new(), "")), parser(token_stream).parse(""));
    }

    quickcheck!{
        fn parse_int_literal(x: i64) -> bool {
            match parser(literal).parse(&*x.to_string()) {
                Ok((Literal::Int(y), _)) => x == y,
                _ => false,
            }
        }

        fn parse_float_literal(x: f64) -> bool {
            let mut string = x.to_string();
            if x.trunc() == x {
                string.push_str(".0");
            }

            if let Ok((Literal::Flt(y), _)) = parser(literal).parse(&*string) {
                x.approx_eq_ulps(&y, 4)
            } else {
                false
            }
        }

        fn parse_str_literal(x: String) -> TestResult {
            let string = format!("\"{}\"", x);
            if x.contains('\"') {
                return TestResult::discard()
            }
            match parser(literal).parse(&*string) {
                Ok((Literal::Str(result), _)) => TestResult::from_bool(result == x),
                _ => TestResult::failed(),
            }
        }

        fn parse_symbol(x: String) -> TestResult {
            if x.is_empty() {
                return TestResult::discard()
            }

            if !x.chars().next().unwrap().is_alphabetic() {
                return TestResult::discard()
            }

            // Test only valid symbols
            for c in x.chars() {
                if !(c.is_alphanumeric() || c == '_') {
                    return TestResult::discard()
                }
            }

            match parser(symbol).parse(&*x) {
                Ok((Token::Symbol(result), _)) => TestResult::from_bool(result == x),
                _ => TestResult::failed(),
            }
        }
    }
}
<|endoftext|>


<commit_before>use websocket::{client,Client,stream,Message, Sender, Receiver};

use hyper::Url;

use value::Value;
use server::Event;
use relation::Change;

use rustc_serialize::json::*;

pub fn open_websocket(url_string: &str) -> Result<(client::sender::Sender<stream::WebSocketStream>,::std::thread::JoinGuard<()>),String> { //Result<(client::sender::Sender<stream::WebSocketStream>,client::receiver::Receiver<stream::WebSocketStream>),String> { //Result<(::std::thread::JoinGuard<()>,::std::thread::JoinGuard<()>),String> {

	//let mut context = SslContext::new(SslMethod::Tlsv1).unwrap();
	//let _ = context.set_certificate_file(&(Path::new("server.crt")), X509FileType::PEM);
	//let _ = context.set_private_key_file(&(Path::new("server.key")), X509FileType::PEM);
	let url = Url::parse(url_string).unwrap();
	println!("Connecting to {}", url);
	let request = match Client::connect(url) {
		Ok(t) => t,
		Err(e) => {
			return Err(format!("{}", e).to_string());
		}
	};

	let response = match request.send() {
		Ok(t) => t,
		Err(e) => {
			return Err(format!("{}", e).to_string());
		}
	};

	match response.validate() {
		Ok(_) => println!("Response valid. Start sending/receiving..."),
		Err(e) => {
			return Err(format!("{}", e).to_string());
		}
	};

	let (sender, receiver) = response.begin().split();
	//let (tx, _) = ::std::sync::mpsc::channel();

	let receive_thread = ::std::thread::scoped(move || { receive_handler(receiver) } );

	Ok((sender,receive_thread))

	// Send an initial ping to the server
	//sender.send_message(Message::Ping(vec![0])).unwrap();

	//let send_thread = ::std::thread::scoped(move || { send_handler(sender,&rx) } );

	//Ok((send_thread,receive_thread))

}

/*
fn send_handler(ref mut sender: client::sender::Sender<stream::WebSocketStream>, rx: &::std::sync::mpsc::Receiver<Message>) {

	loop {

		let message = match rx.recv() {
			Ok(m) => m,
			Err(e) => {
				println!("Send Message Error: {:?}", e);
				return;
			}
		};

		match message {
			Message::Close(_) => {
				println!("Sending a close connection message");
				sender.send_message(message).unwrap();
				return;
			}
			_ => (),
		}

		match sender.send_message(message) {
			Ok(()) => {
				println!("Sending a message");
				()
			},
			Err(e) => {
				println!("Cannot send message, sending close connection instead: {:?}", e);
				sender.send_message(Message::Close(None)).unwrap();
				return;
			}
		}
	}
}*/

//fn receive_handler(ref mut receiver: client::receiver::Receiver<stream::WebSocketStream>, tx: &::std::sync::mpsc::Sender<Message>) {
	fn receive_handler(ref mut receiver: client::receiver::Receiver<stream::WebSocketStream>) {

	// Receive loop
	for message in receiver.incoming_messages() {

		let message = match message {
			Ok(m) => m,
			Err(e) => {
				println!("Receive Loop Error: {:?}", e);
				//tx.send(Message::Close(None)).unwrap();
				return;
			}
		};

		match message {
			Message::Close(_) => {
				println!("Received Close Message");
				//tx.send(Message::Close(None)).unwrap();
				return;
			},
			Message::Text(_) => {
				println!("Received Text");

				/*
				// Create an eveuser table
				let table_name = "eveuser";
				let table_fields = vec!["id","username"];

				// First we create the eveuser table
				if response_count == 0 {
					let json_event = create_table(&table_name,&table_fields).to_json();
					tx.send(Message::Text(json_event.to_string())).unwrap();
					response_count = response_count + 1;
				// We get back a response from the server, now insert the user
				} else if response_count == 1 {
					let json_event = insert_fact(&table_name,&table_fields,&data).to_json();
					tx.send(Message::Text(json_event.to_string())).unwrap();
					response_count = response_count + 1;
				// We get back a response again, so we've done our job. Close the connection
				} else {
					tx.send(Message::Close(None)).unwrap();
					return;
				}*/
			},
			_ => println!("Unhandled message type"),
		}
	}
}

pub fn send_event(event: &Event,sender: &mut client::sender::Sender<stream::WebSocketStream>) {

	sender.send_message(Message::Text(event.to_json().to_string())).unwrap();

}

pub fn create_table(table_name: &&str, table_fields: &Vec<&str>) -> Event {

	let table_string = Value::String(table_name.to_string());

	// Creates a vector of names of the form: "table_name: field_name"
	let concat_field_names: Vec<Value> = table_fields.iter()
											.map(|field_name| Value::String(table_name.to_string() + ": " + field_name))
											.collect();

	// Concats a vector of display names of the form: (display name: id, display name: name)
	let display_name_fields: Vec<Vec<Value>> = concat_field_names.iter()
												.zip(table_fields.iter())
												.map(|(concat_name,field_name)| vec![concat_name.clone(),Value::String(field_name.to_string())])
												.collect();

	// Creates the display name insert
	let display_name_inserts = vec![vec![table_string.clone(),table_string.clone()]];
	display_name_inserts.iter().chain(display_name_fields.iter()).collect::<Vec<_>>();

	let display_name = ("display name".to_string(),Change {
												fields: vec!["display name: id".to_string(),"display name: name".to_string()],
												insert: display_name_inserts,
												remove: vec![],
											}
						);

	let view = ("view".to_string(),Change   {
												fields: vec!["view: view".to_string(),"view: kind".to_string()],
												insert: vec![
																vec![table_string.clone(),Value::String("table".to_string())],
															],
												remove: vec![],
											}
				);

	// Create field insert vector of the from: field: view, field: field, "output"
	let field_inserts = concat_field_names.iter()
										  .map(|concat_field| vec![table_string.clone(), concat_field.clone(), Value::String("output".to_string())])
										  .collect::<Vec<_>>();

	let field = ("field".to_string(),Change {
												fields: vec!["field: view".to_string(),"field: field".to_string(),"field: kind".to_string()],
												insert: field_inserts,
												remove: vec![],
											}
				);

	Event{changes: vec![display_name,view,field] }

}

// TODO make sure table exists before trying to insert a fact into it
pub fn insert_fact(table_name: &&str, table_fields: &Vec<&str>, row_data: &Vec<Value>) -> Event {

	assert_eq!(table_fields.len(),row_data.len());

	// Creates a vector of names of the form: "table_name: field_name"
	let concat_field_names: Vec<String> = table_fields.iter()
											.map(|field_name| table_name.to_string() + ": " + field_name)
											.collect();

	Event{changes: vec![("eveuser".to_string(),Change {
														fields: concat_field_names,
												    	insert: vec![row_data.clone()],
												    	remove: vec![],
												      }
						)]
		 }
}<commit_msg>Fixed an oversight in client.rs<commit_after>use websocket::{client,Client,stream,Message, Sender, Receiver};

use hyper::Url;

use value::Value;
use server::Event;
use relation::Change;

use rustc_serialize::json::*;

pub fn open_websocket(url_string: &str) -> Result<(client::sender::Sender<stream::WebSocketStream>,::std::thread::JoinGuard<()>),String> { //Result<(client::sender::Sender<stream::WebSocketStream>,client::receiver::Receiver<stream::WebSocketStream>),String> { //Result<(::std::thread::JoinGuard<()>,::std::thread::JoinGuard<()>),String> {

	//let mut context = SslContext::new(SslMethod::Tlsv1).unwrap();
	//let _ = context.set_certificate_file(&(Path::new("server.crt")), X509FileType::PEM);
	//let _ = context.set_private_key_file(&(Path::new("server.key")), X509FileType::PEM);
	let url = Url::parse(url_string).unwrap();
	println!("Connecting to {}", url);
	let request = match Client::connect(url) {
		Ok(t) => t,
		Err(e) => {
			return Err(format!("{}", e).to_string());
		}
	};

	let response = match request.send() {
		Ok(t) => t,
		Err(e) => {
			return Err(format!("{}", e).to_string());
		}
	};

	match response.validate() {
		Ok(_) => println!("Response valid. Start sending/receiving..."),
		Err(e) => {
			return Err(format!("{}", e).to_string());
		}
	};

	let (sender, receiver) = response.begin().split();
	//let (tx, _) = ::std::sync::mpsc::channel();

	let receive_thread = ::std::thread::scoped(move || { receive_handler(receiver) } );

	Ok((sender,receive_thread))

	// Send an initial ping to the server
	//sender.send_message(Message::Ping(vec![0])).unwrap();

	//let send_thread = ::std::thread::scoped(move || { send_handler(sender,&rx) } );

	//Ok((send_thread,receive_thread))

}

/*
fn send_handler(ref mut sender: client::sender::Sender<stream::WebSocketStream>, rx: &::std::sync::mpsc::Receiver<Message>) {

	loop {

		let message = match rx.recv() {
			Ok(m) => m,
			Err(e) => {
				println!("Send Message Error: {:?}", e);
				return;
			}
		};

		match message {
			Message::Close(_) => {
				println!("Sending a close connection message");
				sender.send_message(message).unwrap();
				return;
			}
			_ => (),
		}

		match sender.send_message(message) {
			Ok(()) => {
				println!("Sending a message");
				()
			},
			Err(e) => {
				println!("Cannot send message, sending close connection instead: {:?}", e);
				sender.send_message(Message::Close(None)).unwrap();
				return;
			}
		}
	}
}*/

//fn receive_handler(ref mut receiver: client::receiver::Receiver<stream::WebSocketStream>, tx: &::std::sync::mpsc::Sender<Message>) {
	fn receive_handler(ref mut receiver: client::receiver::Receiver<stream::WebSocketStream>) {

	// Receive loop
	for message in receiver.incoming_messages() {

		let message = match message {
			Ok(m) => m,
			Err(e) => {
				println!("Receive Loop Error: {:?}", e);
				//tx.send(Message::Close(None)).unwrap();
				return;
			}
		};

		match message {
			Message::Close(_) => {
				println!("Received Close Message");
				//tx.send(Message::Close(None)).unwrap();
				return;
			},
			Message::Text(_) => {
				println!("Received Text");

				/*
				// Create an eveuser table
				let table_name = "eveuser";
				let table_fields = vec!["id","username"];

				// First we create the eveuser table
				if response_count == 0 {
					let json_event = create_table(&table_name,&table_fields).to_json();
					tx.send(Message::Text(json_event.to_string())).unwrap();
					response_count = response_count + 1;
				// We get back a response from the server, now insert the user
				} else if response_count == 1 {
					let json_event = insert_fact(&table_name,&table_fields,&data).to_json();
					tx.send(Message::Text(json_event.to_string())).unwrap();
					response_count = response_count + 1;
				// We get back a response again, so we've done our job. Close the connection
				} else {
					tx.send(Message::Close(None)).unwrap();
					return;
				}*/
			},
			_ => println!("Unhandled message type"),
		}
	}
}

pub fn send_event(event: &Event,sender: &mut client::sender::Sender<stream::WebSocketStream>) {

	sender.send_message(Message::Text(event.to_json().to_string())).unwrap();

}

pub fn create_table(table_name: &&str, table_fields: &Vec<&str>) -> Event {

	let table_string = Value::String(table_name.to_string());

	// Creates a vector of names of the form: "table_name: field_name"
	let concat_field_names: Vec<Value> = table_fields.iter()
											.map(|field_name| Value::String(table_name.to_string() + ": " + field_name))
											.collect();

	// Concats a vector of display names of the form: (display name: id, display name: name)
	let display_name_fields: Vec<Vec<Value>> = concat_field_names.iter()
												.zip(table_fields.iter())
												.map(|(concat_name,field_name)| vec![concat_name.clone(),Value::String(field_name.to_string())])
												.collect();

	// Creates the display name insert
	let display_name_inserts = vec![vec![table_string.clone(),table_string.clone()]];
	display_name_inserts.iter().chain(display_name_fields.iter()).collect::<Vec<_>>();

	let display_name = ("display name".to_string(),Change {
												fields: vec!["display name: id".to_string(),"display name: name".to_string()],
												insert: display_name_inserts,
												remove: vec![],
											}
						);

	let view = ("view".to_string(),Change   {
												fields: vec!["view: view".to_string(),"view: kind".to_string()],
												insert: vec![
																vec![table_string.clone(),Value::String("table".to_string())],
															],
												remove: vec![],
											}
				);

	// Create field insert vector of the from: field: view, field: field, "output"
	let field_inserts = concat_field_names.iter()
										  .map(|concat_field| vec![table_string.clone(), concat_field.clone(), Value::String("output".to_string())])
										  .collect::<Vec<_>>();

	let field = ("field".to_string(),Change {
												fields: vec!["field: view".to_string(),"field: field".to_string(),"field: kind".to_string()],
												insert: field_inserts,
												remove: vec![],
											}
				);

	Event{changes: vec![display_name,view,field] }

}

// TODO make sure table exists before trying to insert a fact into it
pub fn insert_fact(table_name: &&str, table_fields: &Vec<&str>, row_data: &Vec<Value>) -> Event {

	assert_eq!(table_fields.len(),row_data.len());

	// Creates a vector of names of the form: "table_name: field_name"
	let concat_field_names: Vec<String> = table_fields.iter()
											.map(|field_name| table_name.to_string() + ": " + field_name)
											.collect();

	Event{changes: vec![(table_name.to_string(),Change {
														fields: concat_field_names,
												    	insert: vec![row_data.clone()],
												    	remove: vec![],
												      }
						)]
		 }
}<|endoftext|>