<commit_before>//! Call rank and take command of [Slack](https://slack.com/) with rust at your helm

#[macro_use]
extern crate log;
extern crate hyper;
extern crate url;
extern crate regex;
extern crate serde;
extern crate serde_json;

mod response;

use hyper::Client;
use hyper::header::ContentType;
use hyper::server::{Handler as HyperHandler, Request, Response as HyperResponse};
use regex::{Captures as RegexCaptures, Regex};
pub use response::{Attachment, Field, Response};
use std::collections::HashMap;
use std::io::Read;

const DEFAULT_RESPONSE: &'static [u8] = b"ok";

fn params<R: Read>(read: &mut R) -> HashMap<String, String> {
    let mut buffer = String::new();
    read.read_to_string(&mut buffer).unwrap();
    let mut params = HashMap::new();
    for (k, v) in url::form_urlencoded::parse(buffer.as_bytes()) {
        params.insert(k.into_owned(), v.into_owned());
    }
    params
}

/// Results for regex matchers that collect captures
pub type Captures<'a> = RegexCaptures<'a>;

/// Deferred response interface
pub trait Responder: Sync + Send {
    /// Calling respond should update
    /// the channel or reply to the user
    /// that issued the original command
    fn respond(&self, response: Response) -> ();
}

#[doc(hidden)]
pub struct DefaultResponder {
    response_url: String,
}

impl DefaultResponder {
    pub fn new<U>(response_url: U) -> DefaultResponder
        where U: Into<String>
    {
        DefaultResponder { response_url: response_url.into() }
    }
}

impl Responder for DefaultResponder {
    fn respond(&self, response: Response) {
        let client = Client::new();
        let _ = client.post(&self.response_url[..])
            .header(ContentType::json())
            .body(serde_json::to_string(&response).unwrap().as_bytes())
            .send();
    }
}

/// Command handling interface
/// Implementation for Fn
pub trait Handler: Sync + Send {
    /// handles Slack commands. Optional captures resulting
    /// from matching are provided along with an interface
    /// for deferred responses
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response>;

    /// provides a mean explicit coersion for
    /// disambiguating cases where a fn named `handle` is
    /// already defined in another trait for which another
    /// impl exists for the same type
    fn as_handler(&self) -> &Handler;
}

impl<F> Handler for F
    where F: Fn(&Command, &Option<Captures>, Box<Responder>) -> Option<Response>,
          F: Send + Sync
{
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        self(cmd, caps, responder)
    }

    fn as_handler(&self) -> &Handler {
        self
    }
}

#[doc(hidden)]
pub struct TokenValidator<H: Handler + 'static> {
    handler: H,
    token: String,
}

impl<H: Handler + 'static> Handler for TokenValidator<H> {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        if cmd.token == self.token {
            self.handler.handle(cmd, caps, responder)
        } else {
            error!("cmd token ${:?} did not match handler token ${:?}",
                   cmd.token,
                   self.token);
            None
        }
    }

    fn as_handler(&self) -> &Handler {
        self
    }
}

/// Command matching interface
pub trait Matcher: Send + Sync {
    /// returns of tuple of optional captures and an indicator for
    /// whether or not the provided command is matched
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool);
}

impl<F> Matcher for F
    where F: Fn(&Command) -> (Option<Captures>, bool),
          F: Send + Sync
{
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        self(cmd)
    }
}

/// A direct command matcher
pub struct MatchCommand(pub String);

impl Matcher for MatchCommand {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        (None, cmd.command == self.0)
    }
}

/// A matcher that assumes any text starting with
/// the provided string is a subcommand. i.e. /cmd help
pub struct MatchSubCommand(pub String);

impl Matcher for MatchSubCommand {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        if cmd.text.starts_with(&self.0) {
            (None, true)
        } else {
            debug!("regex {:?} did not match cmd {:?}", self.0, cmd.command);
            (None, false)
        }
    }
}

/// A regex pattern matcher for command text.
/// Regex captures will be provided to the matched Handler
pub struct MatchText(pub Regex);

impl Matcher for MatchText {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        if self.0.is_match(cmd.text.as_ref()) {
            (self.0.captures(cmd.text.as_ref()), true)
        } else {
            debug!("regex {:?} did not match cmd {:?}", self.0, cmd.command);
            (None, false)
        }
    }
}

#[doc(hidden)]
pub struct Route {
    handler: Box<Handler>,
    matcher: Box<Matcher>,
}

/// A command de-multiplexor
#[derive(Default)]
pub struct Mux {
    routes: Vec<Box<Route>>,
}

impl Mux {
    pub fn new() -> Mux {
        Mux { ..Default::default() }
    }

    /// Install routing for a Slack command, secret token, and target Handler
    pub fn command<C, T, H>(&mut self, cmd: C, token: T, handler: H)
        where C: Into<String>,
              T: Into<String>,
              H: Handler + 'static
    {
        self.matching(MatchCommand(cmd.into()),
                      TokenValidator {
                          handler: handler,
                          token: token.into(),
                      })
    }

    /// Install routing for a Slack command matcher and target Handler
    pub fn matching<M, H>(&mut self, matcher: M, handler: H)
        where M: Matcher + 'static,
              H: Handler + 'static
    {
        let route = Route {
            handler: Box::new(handler),
            matcher: Box::new(matcher),
        };
        self.route(route)
    }

    /// Install a command routing
    pub fn route(&mut self, route: Route) {
        self.routes.push(Box::new(route));
    }

    /// Attempts to return the first match result for a target Handler
    pub fn handler<'a>(&self, cmd: &'a Command) -> Option<(Option<Captures<'a>>, &Box<Handler>)> {
        for r in self.routes.iter() {
            if let (captures, true) = r.matcher.matches(cmd) {
                return Some((captures, &r.handler));
            }
        }
        None
    }
}

impl Handler for Mux {
    fn handle(&self,
              cmd: &Command,
              _: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        if let &Some((ref captures, handler)) = &self.handler(&cmd) {
            debug!("cmd matched. attempting to handle cmd {:#?}", cmd);
            handler.handle(&cmd, &captures, responder)
        } else {
            debug!("no matching handlers for {:#?}", cmd);
            None
        }
    }

    fn as_handler(&self) -> &Handler {
        self
    }
}

/// A struct representation of a Slack Command
/// and the context from which it was triggered
#[derive(Default, Debug, PartialEq)]
pub struct Command {
    pub token: String,
    pub team_id: String,
    pub team_domain: String,
    pub channel_id: String,
    pub channel_name: String,
    pub user_id: String,
    pub user_name: String,
    pub command: String,
    pub text: String,
    pub response_url: String,
}

impl Command {
    pub fn from_params(params: HashMap<String, String>) -> Option<Command> {
        if let (Some(token),
                Some(team_id),
                Some(team_domain),
                Some(channel_id),
                Some(channel_name),
                Some(user_id),
                Some(user_name),
                Some(command),
                Some(text),
                Some(response_url)) = (params.get("token"),
                                       params.get("team_id"),
                                       params.get("team_domain"),
                                       params.get("channel_id"),
                                       params.get("channel_name"),
                                       params.get("user_id"),
                                       params.get("user_name"),
                                       params.get("command"),
                                       params.get("text"),
                                       params.get("response_url")) {
            Some(Command {
                token: token.clone(),
                team_id: team_id.clone(),
                team_domain: team_domain.clone(),
                channel_id: channel_id.clone(),
                channel_name: channel_name.clone(),
                user_id: user_id.clone(),
                user_name: user_name.clone(),
                command: command.clone(),
                text: text.clone(),
                response_url: response_url.clone(),
            })
        } else {
            None
        }
    }
}

impl HyperHandler for Mux {
    // https://api.slack.com/slash-commands
    fn handle(&self, req: Request, mut res: HyperResponse) {
        let (_, _, _, _, _, mut body) = req.deconstruct();

        // parse params
        let params = params(&mut body);
        // parse cmd
        if let Some(cmd) = Command::from_params(params) {
            debug!("rec cmd {:?}", cmd);
            let write = |bytes: &[u8], content_type: ContentType| {
                res.headers_mut().set(content_type);
                let _ = res.send(bytes);
            };
            let responder = DefaultResponder::new(cmd.response_url.clone());
            if let Some(resp) = self.as_handler().handle(&cmd, &None, Box::new(responder)) {
                match serde_json::to_string(&resp) {
                    Ok(payload) => write(payload.as_bytes(), ContentType::json()),
                    _ => write(DEFAULT_RESPONSE, ContentType::plaintext()),
                };
            } else {
                write(DEFAULT_RESPONSE, ContentType::plaintext())
            };
        } else {
            error!("rec invalid cmd");
            let _ = res.send(DEFAULT_RESPONSE);
        }
        ()
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use super::*;
    use super::regex::Regex;

    #[test]
    fn matches_commands() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (_, matched) = MatchCommand("/test".to_owned()).matches(&cmd);
        assert!(matched, "cmd did not match")
    }

    #[test]
    fn matches_text() {
        let cmd = Command { text: "/test hello world".to_owned(), ..Default::default() };
        let (captures, matched) =
            MatchText(Regex::new(r"(?P<greeting>\S+?) (?P<name>\S+?)$").unwrap()).matches(&cmd);
        assert!(matched, "cmd did not match");
        match captures {
            Some(caps) => {
                assert_eq!(caps.name("greeting"), Some("hello"));
                assert_eq!(caps.name("name"), Some("world"));
            }
            _ => assert!(false, "expected captures"),
        }
    }

    #[test]
    fn extracts_commands() {
        let mut params = HashMap::new();
        params.insert("token".to_owned(), "test_token".to_owned());
        params.insert("team_id".to_owned(), "test_team".to_owned());
        params.insert("team_domain".to_owned(), "test_team_domain".to_owned());
        params.insert("channel_id".to_owned(), "test_channel_id".to_owned());
        params.insert("channel_name".to_owned(), "test_channel_name".to_owned());
        params.insert("user_id".to_owned(), "test_user_id".to_owned());
        params.insert("user_name".to_owned(), "test_user_name".to_owned());
        params.insert("command".to_owned(), "test_command".to_owned());
        params.insert("text".to_owned(), "test_text".to_owned());
        params.insert("response_url".to_owned(), "test_response_url".to_owned());
        match Command::from_params(params) {
            Some(cmd) => {
                assert_eq!(cmd,
                           Command {
                               token: "test_token".to_owned(),
                               team_id: "test_team".to_owned(),
                               team_domain: "test_team_domain".to_owned(),
                               channel_id: "test_channel_id".to_owned(),
                               channel_name: "test_channel_name".to_owned(),
                               user_id: "test_user_id".to_owned(),
                               user_name: "test_user_name".to_owned(),
                               command: "test_command".to_owned(),
                               text: "test_text".to_owned(),
                               response_url: "test_response_url".to_owned(),
                           })
            }
            _ => assert!(false, "failed to extract command"),
        }
    }
}
<commit_msg>order imports<commit_after>//! Call rank and take command of [Slack](https://slack.com/) with rust at your helm

#[macro_use]
extern crate log;
extern crate hyper;
extern crate url;
extern crate regex;
extern crate serde;
extern crate serde_json;

use std::collections::HashMap;
use std::io::Read;

use hyper::Client;
use hyper::header::ContentType;
use hyper::server::{Handler as HyperHandler, Request, Response as HyperResponse};
use regex::{Captures as RegexCaptures, Regex};

mod response;
pub use response::{Attachment, Field, Response};

const DEFAULT_RESPONSE: &'static [u8] = b"ok";

fn params<R: Read>(read: &mut R) -> HashMap<String, String> {
    let mut buffer = String::new();
    read.read_to_string(&mut buffer).unwrap();
    let mut params = HashMap::new();
    for (k, v) in url::form_urlencoded::parse(buffer.as_bytes()) {
        params.insert(k.into_owned(), v.into_owned());
    }
    params
}

/// Results for regex matchers that collect captures
pub type Captures<'a> = RegexCaptures<'a>;

/// Deferred response interface
pub trait Responder: Sync + Send {
    /// Calling respond should update
    /// the channel or reply to the user
    /// that issued the original command
    fn respond(&self, response: Response) -> ();
}

#[doc(hidden)]
pub struct DefaultResponder {
    response_url: String,
}

impl DefaultResponder {
    pub fn new<U>(response_url: U) -> DefaultResponder
        where U: Into<String>
    {
        DefaultResponder { response_url: response_url.into() }
    }
}

impl Responder for DefaultResponder {
    fn respond(&self, response: Response) {
        let client = Client::new();
        let _ = client.post(&self.response_url[..])
            .header(ContentType::json())
            .body(serde_json::to_string(&response).unwrap().as_bytes())
            .send();
    }
}

/// Command handling interface
/// Implementation for Fn
pub trait Handler: Sync + Send {
    /// handles Slack commands. Optional captures resulting
    /// from matching are provided along with an interface
    /// for deferred responses
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response>;

    /// provides a mean explicit coersion for
    /// disambiguating cases where a fn named `handle` is
    /// already defined in another trait for which another
    /// impl exists for the same type
    fn as_handler(&self) -> &Handler;
}

impl<F> Handler for F
    where F: Fn(&Command, &Option<Captures>, Box<Responder>) -> Option<Response>,
          F: Send + Sync
{
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        self(cmd, caps, responder)
    }

    fn as_handler(&self) -> &Handler {
        self
    }
}

#[doc(hidden)]
pub struct TokenValidator<H: Handler + 'static> {
    handler: H,
    token: String,
}

impl<H: Handler + 'static> Handler for TokenValidator<H> {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        if cmd.token == self.token {
            self.handler.handle(cmd, caps, responder)
        } else {
            error!("cmd token ${:?} did not match handler token ${:?}",
                   cmd.token,
                   self.token);
            None
        }
    }

    fn as_handler(&self) -> &Handler {
        self
    }
}

/// Command matching interface
pub trait Matcher: Send + Sync {
    /// returns of tuple of optional captures and an indicator for
    /// whether or not the provided command is matched
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool);
}

impl<F> Matcher for F
    where F: Fn(&Command) -> (Option<Captures>, bool),
          F: Send + Sync
{
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        self(cmd)
    }
}

/// A direct command matcher
pub struct MatchCommand(pub String);

impl Matcher for MatchCommand {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        (None, cmd.command == self.0)
    }
}

/// A matcher that assumes any text starting with
/// the provided string is a subcommand. i.e. /cmd help
pub struct MatchSubCommand(pub String);

impl Matcher for MatchSubCommand {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        if cmd.text.starts_with(&self.0) {
            (None, true)
        } else {
            debug!("regex {:?} did not match cmd {:?}", self.0, cmd.command);
            (None, false)
        }
    }
}

/// A regex pattern matcher for command text.
/// Regex captures will be provided to the matched Handler
pub struct MatchText(pub Regex);

impl Matcher for MatchText {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        if self.0.is_match(cmd.text.as_ref()) {
            (self.0.captures(cmd.text.as_ref()), true)
        } else {
            debug!("regex {:?} did not match cmd {:?}", self.0, cmd.command);
            (None, false)
        }
    }
}

#[doc(hidden)]
pub struct Route {
    handler: Box<Handler>,
    matcher: Box<Matcher>,
}

/// A command de-multiplexor
#[derive(Default)]
pub struct Mux {
    routes: Vec<Box<Route>>,
}

impl Mux {
    pub fn new() -> Mux {
        Mux { ..Default::default() }
    }

    /// Install routing for a Slack command, secret token, and target Handler
    pub fn command<C, T, H>(&mut self, cmd: C, token: T, handler: H)
        where C: Into<String>,
              T: Into<String>,
              H: Handler + 'static
    {
        self.matching(MatchCommand(cmd.into()),
                      TokenValidator {
                          handler: handler,
                          token: token.into(),
                      })
    }

    /// Install routing for a Slack command matcher and target Handler
    pub fn matching<M, H>(&mut self, matcher: M, handler: H)
        where M: Matcher + 'static,
              H: Handler + 'static
    {
        let route = Route {
            handler: Box::new(handler),
            matcher: Box::new(matcher),
        };
        self.route(route)
    }

    /// Install a command routing
    pub fn route(&mut self, route: Route) {
        self.routes.push(Box::new(route));
    }

    /// Attempts to return the first match result for a target Handler
    pub fn handler<'a>(&self, cmd: &'a Command) -> Option<(Option<Captures<'a>>, &Box<Handler>)> {
        for r in self.routes.iter() {
            if let (captures, true) = r.matcher.matches(cmd) {
                return Some((captures, &r.handler));
            }
        }
        None
    }
}

impl Handler for Mux {
    fn handle(&self,
              cmd: &Command,
              _: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        if let &Some((ref captures, handler)) = &self.handler(&cmd) {
            debug!("cmd matched. attempting to handle cmd {:#?}", cmd);
            handler.handle(&cmd, &captures, responder)
        } else {
            debug!("no matching handlers for {:#?}", cmd);
            None
        }
    }

    fn as_handler(&self) -> &Handler {
        self
    }
}

/// A struct representation of a Slack Command
/// and the context from which it was triggered
#[derive(Default, Debug, PartialEq)]
pub struct Command {
    pub token: String,
    pub team_id: String,
    pub team_domain: String,
    pub channel_id: String,
    pub channel_name: String,
    pub user_id: String,
    pub user_name: String,
    pub command: String,
    pub text: String,
    pub response_url: String,
}

impl Command {
    pub fn from_params(params: HashMap<String, String>) -> Option<Command> {
        if let (Some(token),
                Some(team_id),
                Some(team_domain),
                Some(channel_id),
                Some(channel_name),
                Some(user_id),
                Some(user_name),
                Some(command),
                Some(text),
                Some(response_url)) = (params.get("token"),
                                       params.get("team_id"),
                                       params.get("team_domain"),
                                       params.get("channel_id"),
                                       params.get("channel_name"),
                                       params.get("user_id"),
                                       params.get("user_name"),
                                       params.get("command"),
                                       params.get("text"),
                                       params.get("response_url")) {
            Some(Command {
                token: token.clone(),
                team_id: team_id.clone(),
                team_domain: team_domain.clone(),
                channel_id: channel_id.clone(),
                channel_name: channel_name.clone(),
                user_id: user_id.clone(),
                user_name: user_name.clone(),
                command: command.clone(),
                text: text.clone(),
                response_url: response_url.clone(),
            })
        } else {
            None
        }
    }
}

impl HyperHandler for Mux {
    // https://api.slack.com/slash-commands
    fn handle(&self, req: Request, mut res: HyperResponse) {
        let (_, _, _, _, _, mut body) = req.deconstruct();

        // parse params
        let params = params(&mut body);
        // parse cmd
        if let Some(cmd) = Command::from_params(params) {
            debug!("rec cmd {:?}", cmd);
            let write = |bytes: &[u8], content_type: ContentType| {
                res.headers_mut().set(content_type);
                let _ = res.send(bytes);
            };
            let responder = DefaultResponder::new(cmd.response_url.clone());
            if let Some(resp) = self.as_handler().handle(&cmd, &None, Box::new(responder)) {
                match serde_json::to_string(&resp) {
                    Ok(payload) => write(payload.as_bytes(), ContentType::json()),
                    _ => write(DEFAULT_RESPONSE, ContentType::plaintext()),
                };
            } else {
                write(DEFAULT_RESPONSE, ContentType::plaintext())
            };
        } else {
            error!("rec invalid cmd");
            let _ = res.send(DEFAULT_RESPONSE);
        }
        ()
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use super::*;
    use super::regex::Regex;

    #[test]
    fn matches_commands() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (_, matched) = MatchCommand("/test".to_owned()).matches(&cmd);
        assert!(matched, "cmd did not match")
    }

    #[test]
    fn matches_text() {
        let cmd = Command { text: "/test hello world".to_owned(), ..Default::default() };
        let (captures, matched) =
            MatchText(Regex::new(r"(?P<greeting>\S+?) (?P<name>\S+?)$").unwrap()).matches(&cmd);
        assert!(matched, "cmd did not match");
        match captures {
            Some(caps) => {
                assert_eq!(caps.name("greeting"), Some("hello"));
                assert_eq!(caps.name("name"), Some("world"));
            }
            _ => assert!(false, "expected captures"),
        }
    }

    #[test]
    fn extracts_commands() {
        let mut params = HashMap::new();
        params.insert("token".to_owned(), "test_token".to_owned());
        params.insert("team_id".to_owned(), "test_team".to_owned());
        params.insert("team_domain".to_owned(), "test_team_domain".to_owned());
        params.insert("channel_id".to_owned(), "test_channel_id".to_owned());
        params.insert("channel_name".to_owned(), "test_channel_name".to_owned());
        params.insert("user_id".to_owned(), "test_user_id".to_owned());
        params.insert("user_name".to_owned(), "test_user_name".to_owned());
        params.insert("command".to_owned(), "test_command".to_owned());
        params.insert("text".to_owned(), "test_text".to_owned());
        params.insert("response_url".to_owned(), "test_response_url".to_owned());
        match Command::from_params(params) {
            Some(cmd) => {
                assert_eq!(cmd,
                           Command {
                               token: "test_token".to_owned(),
                               team_id: "test_team".to_owned(),
                               team_domain: "test_team_domain".to_owned(),
                               channel_id: "test_channel_id".to_owned(),
                               channel_name: "test_channel_name".to_owned(),
                               user_id: "test_user_id".to_owned(),
                               user_name: "test_user_name".to_owned(),
                               command: "test_command".to_owned(),
                               text: "test_text".to_owned(),
                               response_url: "test_response_url".to_owned(),
                           })
            }
            _ => assert!(false, "failed to extract command"),
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "r6"]

//! r6.rs is an attempt to implement R6RS Scheme in Rust language

#![feature(plugin)]
#![feature(slicing_syntax)]
#![feature(box_syntax)]
//TODO: Allow unstable items until Rust hits 1.0
#![allow(unstable)]

#[plugin]
extern crate phf_mac;
extern crate phf;
extern crate unicode;
extern crate num;

macro_rules! list{
    ($($x:expr),*) => (
        vec![$($x),*].into_iter().collect()
    )
}

macro_rules! sym{
    ($e:expr) => (
        Datum::Sym(Cow::Borrowed($e))
    )
}

macro_rules! num{
    ($e:expr) => (
        Datum::Num(Number::new_int($e, 0))
    )
}

macro_rules! nil{
    () => (
        Datum::Nil
    )
}

/// Error values returned from parser, compiler or runtime
pub mod error;
/// Basic datum types
pub mod datum;
pub mod parser;
pub mod lexer;
/// Virtual machine running the bytecode
pub mod runtime;
/// Primitive functions
pub mod primitive;
/// Compiles datum into a bytecode
pub mod compiler;
/// R6RS `base` library
pub mod base;
/// Real part of the numerical tower
pub mod real;
/// Numerical tower
pub mod number;
<commit_msg>Rust changes: Mark unstable import libraries<commit_after>#![crate_name = "r6"]

//! r6.rs is an attempt to implement R6RS Scheme in Rust language

#![feature(plugin)]
#![feature(slicing_syntax)]
#![feature(box_syntax)]

#![feature(core)]
#![feature(std_misc)]
#![feature(io)]
#![feature(collections)]
#![feature(unicode)]

#[plugin]
extern crate phf_mac;
extern crate phf;
extern crate unicode;
extern crate num;

macro_rules! list{
    ($($x:expr),*) => (
        vec![$($x),*].into_iter().collect()
    )
}

macro_rules! sym{
    ($e:expr) => (
        Datum::Sym(Cow::Borrowed($e))
    )
}

macro_rules! num{
    ($e:expr) => (
        Datum::Num(Number::new_int($e, 0))
    )
}

macro_rules! nil{
    () => (
        Datum::Nil
    )
}

/// Error values returned from parser, compiler or runtime
pub mod error;
/// Basic datum types
pub mod datum;
pub mod parser;
pub mod lexer;
/// Virtual machine running the bytecode
pub mod runtime;
/// Primitive functions
pub mod primitive;
/// Compiles datum into a bytecode
pub mod compiler;
/// R6RS `base` library
pub mod base;
/// Real part of the numerical tower
pub mod real;
/// Numerical tower
pub mod number;
<|endoftext|>


<commit_before>#![crate_name = "sidekiq"]

extern crate redis;
extern crate rustc_serialize;
extern crate time;
extern crate rand;
extern crate r2d2;
extern crate r2d2_redis;

mod sidekiq;
pub use sidekiq::{Job, JobOpts, Client, ClientOpts, RedisPool, create_redis_pool};
<commit_msg>Expose RedisPooledConnection<commit_after>#![crate_name = "sidekiq"]

extern crate redis;
extern crate rustc_serialize;
extern crate time;
extern crate rand;
extern crate r2d2;
extern crate r2d2_redis;

mod sidekiq;
pub use sidekiq::{Job, JobOpts, Client, ClientOpts, RedisPool, RedisPooledConnection,
                  create_redis_pool};
<|endoftext|>


<commit_before>use crate::exception::Exception;
use crate::rust_str::RustStr;
use std::fmt::Display;
use std::mem;
use std::ptr;
use std::result::Result as StdResult;
use std::slice;
use std::str;

#[repr(C)]
pub union Result {
    err: RustStr,
    ok: *const u8, // null
}

pub unsafe fn r#try<T, E>(ret: *mut T, result: StdResult<T, E>) -> Result
where
    E: Display,
{
    match result {
        Ok(ok) => {
            ptr::write(ret, ok);
            Result { ok: ptr::null() }
        }
        Err(err) => to_c_error(err.to_string()),
    }
}

unsafe fn to_c_error(msg: String) -> Result {
    let mut msg = msg;
    msg.as_mut_vec().push(b'\0');
    let ptr = msg.as_ptr();
    let len = msg.len();

    extern "C" {
        #[link_name = "cxxbridge02$error"]
        fn error(ptr: *const u8, len: usize) -> *const u8;
    }

    let copy = error(ptr, len);
    let slice = slice::from_raw_parts(copy, len);
    let string = str::from_utf8_unchecked(slice);
    let err = RustStr::from(string);
    Result { err }
}

impl Result {
    pub unsafe fn exception(self) -> StdResult<(), Exception> {
        if self.ok.is_null() {
            Ok(())
        } else {
            let err = self.err;
            let slice = slice::from_raw_parts(err.ptr.as_ptr(), err.len);
            let s = str::from_utf8_unchecked(slice);
            Err(Exception {
                what: mem::transmute::<*const str, Box<str>>(s),
            })
        }
    }
}
<commit_msg>Eliminate use of transmute in Result::exception<commit_after>use crate::exception::Exception;
use crate::rust_str::RustStr;
use std::fmt::Display;
use std::ptr;
use std::result::Result as StdResult;
use std::slice;
use std::str;

#[repr(C)]
pub union Result {
    err: RustStr,
    ok: *const u8, // null
}

pub unsafe fn r#try<T, E>(ret: *mut T, result: StdResult<T, E>) -> Result
where
    E: Display,
{
    match result {
        Ok(ok) => {
            ptr::write(ret, ok);
            Result { ok: ptr::null() }
        }
        Err(err) => to_c_error(err.to_string()),
    }
}

unsafe fn to_c_error(msg: String) -> Result {
    let mut msg = msg;
    msg.as_mut_vec().push(b'\0');
    let ptr = msg.as_ptr();
    let len = msg.len();

    extern "C" {
        #[link_name = "cxxbridge02$error"]
        fn error(ptr: *const u8, len: usize) -> *const u8;
    }

    let copy = error(ptr, len);
    let slice = slice::from_raw_parts(copy, len);
    let string = str::from_utf8_unchecked(slice);
    let err = RustStr::from(string);
    Result { err }
}

impl Result {
    pub unsafe fn exception(self) -> StdResult<(), Exception> {
        if self.ok.is_null() {
            Ok(())
        } else {
            let err = self.err;
            let slice = slice::from_raw_parts_mut(err.ptr.as_ptr(), err.len);
            let s = str::from_utf8_unchecked_mut(slice);
            Err(Exception {
                what: Box::from_raw(s),
            })
        }
    }
}
<|endoftext|>


<commit_before>//! This library provides [`anyhow::Error`][Error], a trait object based error
//! type for easy idiomatic error handling in Rust applications.
//!
//!

//!
//! # Details
//!
//! - Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as
//!   the return type of any fallible function.
//!
//!   Within the function, use `?` to easily propagate any error that implements
//!   the `std::error::Error` trait.
//!
//!   ```
//!   # pub trait Deserialize {}
//!   #
//!   # mod serde_json {
//!   #     use super::Deserialize;
//!   #     use std::io;
//!   #
//!   #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # struct ClusterMap;
//!   #
//!   # impl Deserialize for ClusterMap {}
//!   #
//!   use anyhow::Result;
//!
//!   fn get_cluster_info() -> Result<ClusterMap> {
//!       let config = std::fs::read_to_string("cluster.json")?;
//!       let map: ClusterMap = serde_json::from_str(&config)?;
//!       Ok(map)
//!   }
//!   #
//!   # fn main() {}
//!   ```
//!
//! - Attach context to help the person troubleshooting the error understand
//!   where things went wrong. A low-level error like "No such file or
//!   directory" can be annoying to debug without more context about what higher
//!   level step the application was in the middle of.
//!
//!   ```
//!   # struct It;
//!   #
//!   # impl It {
//!   #     fn detach(&self) -> Result<()> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   use anyhow::{Context, Result};
//!
//!   fn main() -> Result<()> {
//!       # return Ok(());
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # let it = It;
//!       # let path = "./path/to/instrs.jsox";
//!       #
//!       it.detach().context("failed to detach the important thing")?;
//!
//!       let content = std::fs::read(path)
//!           .with_context(|| format!("failed to read instrs from {}", path))?;
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # Ok(())
//!   }
//!   ```
//!
//!   ```console
//!   Error: failed to read instrs from ./path/to/instrs.jsox
//!
//!   Caused by:
//!       No such file or directory (os error 2)
//!   ```
//!
//! - Downcasting is supported and can be by value, by shared reference, or by
//!   mutable reference as needed.
//!
//!   ```
//!   # use anyhow::anyhow;
//!   # use std::fmt::{self, Display};
//!   # use std::task::Poll;
//!   #
//!   # #[derive(Debug)]
//!   # enum DataStoreError {
//!   #     Censored(()),
//!   # }
//!   #
//!   # impl Display for DataStoreError {
//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # impl std::error::Error for DataStoreError {}
//!   #
//!   # const REDACTED_CONTENT: () = ();
//!   #
//!   # let error = anyhow!("...");
//!   # let root_cause = &error;
//!   #
//!   # let ret =
//!   // If the error was caused by redaction, then return a
//!   // tombstone instead of the content.
//!   match root_cause.downcast_ref::<DataStoreError>() {
//!       Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
//!       None => Err(error),
//!   }
//!   # ;
//!   ```
//!
//! - A backtrace is captured and printed with the error if the underlying error
//!   type does not already provide its own. In order to see backtraces, the
//!   `RUST_LIB_BACKTRACE=1` environment variable must be defined.
//!
//! - Anyhow works with any error type that has an impl of `std::error::Error`,
//!   including ones defined in your crate. We do not bundle a `derive(Error)`
//!   macro but you can write the impls yourself or use a standalone macro like
//!   [thiserror].
//!
//!   [thiserror]: https://github.com/dtolnay/thiserror
//!
//!   ```
//!   use thiserror::Error;
//!
//!   #[derive(Error, Debug)]
//!   pub enum FormatError {
//!       #[error("invalid header (expected {expected:?}, got {found:?})")]
//!       InvalidHeader {
//!           expected: String,
//!           found: String,
//!       },
//!       #[error("missing attribute: {0}")]
//!       MissingAttribute(String),
//!   }
//!   ```
//!
//! - One-off error messages can be constructed using the `anyhow!` macro, which
//!   supports string interpolation and produces an `anyhow::Error`.
//!
//!   ```
//!   # use anyhow::{anyhow, Result};
//!   #
//!   # fn demo() -> Result<()> {
//!   #     let missing = "...";
//!   return Err(anyhow!("missing attribute: {}", missing));
//!   #     Ok(())
//!   # }
//!   ```

#![doc(html_root_url = "https://docs.rs/anyhow/1.0.19")]
#![cfg_attr(backtrace, feature(backtrace))]
#![allow(
    clippy::needless_doctest_main,
    clippy::new_ret_no_self,
    clippy::wrong_self_convention
)]

#[macro_use]
mod backtrace;
mod context;
mod error;
mod kind;
mod macros;

#[cfg(not(feature = "std"))]
compile_error!("no_std support is not implemented yet");

use crate::error::ErrorImpl;
use std::error::Error as StdError;
use std::fmt::Display;
use std::mem::ManuallyDrop;

pub use anyhow as format_err;

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`.
/// - `Error` guarantees that a backtrace is available, even if the underlying
///   error type does not provide one.
/// - `Error` is represented as a narrow pointer — exactly one word in
///   size instead of two.
pub struct Error {
    inner: ManuallyDrop<Box<ErrorImpl<()>>>,
}

/// Iterator of a chain of source errors.
///
/// This type is the iterator returned by [`Error::chain`].
///
/// # Example
///
/// ```
/// use anyhow::Error;
/// use std::io;
///
/// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
///     for cause in error.chain() {
///         if let Some(io_error) = cause.downcast_ref::<io::Error>() {
///             return Some(io_error.kind());
///         }
///     }
///     None
/// }
/// ```
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

/// `Result<T, Error>`
///
/// This is a reasonable return type to use throughout your application but also
/// for `fn main`; if you do, failures will be printed along with any
/// [context][Context] and a backtrace if one was captured.
///
/// `anyhow::Result` may be used with one *or* two type parameters.
///
/// ```rust
/// use anyhow::Result;
///
/// # const IGNORE: &str = stringify! {
/// fn demo1() -> Result<T> {...}
///            // ^ equivalent to std::result::Result<T, anyhow::Error>
///
/// fn demo2() -> Result<T, OtherError> {...}
///            // ^ equivalent to std::result::Result<T, OtherError>
/// # };
/// ```
///
/// # Example
///
/// ```
/// # pub trait Deserialize {}
/// #
/// # mod serde_json {
/// #     use super::Deserialize;
/// #     use std::io;
/// #
/// #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
/// #         unimplemented!()
/// #     }
/// # }
/// #
/// # #[derive(Debug)]
/// # struct ClusterMap;
/// #
/// # impl Deserialize for ClusterMap {}
/// #
/// use anyhow::Result;
///
/// fn main() -> Result<()> {
///     # return Ok(());
///     let config = std::fs::read_to_string("cluster.json")?;
///     let map: ClusterMap = serde_json::from_str(&config)?;
///     println!("cluster info: {:#?}", map);
///     Ok(())
/// }
/// ```
pub type Result<T, E = Error> = std::result::Result<T, E>;

/// Provides the `context` method for `Result`.
///
/// This trait is sealed and cannot be implemented for types outside of
/// `anyhow`.
///
///

///
/// # Example
///
/// ```
/// use anyhow::{Context, Result};
/// use std::fs;
/// use std::path::PathBuf;
///
/// pub struct ImportantThing {
///     path: PathBuf,
/// }
///
/// impl ImportantThing {
///     # const IGNORE: &'static str = stringify! {
///     pub fn detach(&mut self) -> Result<()> {...}
///     # };
///     # fn detach(&mut self) -> Result<()> {
///     #     unimplemented!()
///     # }
/// }
///
/// pub fn do_it(mut it: ImportantThing) -> Result<Vec<u8>> {
///     it.detach().context("failed to detach the important thing")?;
///
///     let path = &it.path;
///     let content = fs::read(path)
///         .with_context(|| format!("failed to read instrs from {}", path.display()))?;
///
///     Ok(content)
/// }
/// ```
///
/// When printed, the outermost context would be printed first and the lower
/// level underlying causes would be enumerated below.
///
/// ```console
/// Error: failed to read instrs from ./path/to/instrs.jsox
///
/// Caused by:
///     No such file or directory (os error 2)
/// ```
///
///

///
/// # Effect on downcasting
///
/// After attaching context of type `C` onto an error of type `E`, the resulting
/// `anyhow::Error` may be downcast to `C` **or** to `E`.
///
/// That is, in codebases that rely on downcasting, Anyhow's context supports
/// both of the following use cases:
///
///   - **Attaching context whose type is insignificant onto errors whose type
///     is used in downcasts.**
///
///     In other error libraries whose context is not designed this way, it can
///     be risky to introduce context to existing code because new context might
///     break existing working downcasts. In Anyhow, any downcast that worked
///     before adding context will continue to work after you add a context, so
///     you should freely add human-readable context to errors wherever it would
///     be helpful.
///
///     ```
///     # use anyhow::bail;
///     # use thiserror::Error;
///     #
///     # #[derive(Error, Debug)]
///     # #[error("???")]
///     # struct SuspiciousError;
///     #
///     # fn helper() -> Result<()> {
///     #     bail!(SuspiciousError);
///     # }
///     #
///     use anyhow::{Context, Result};
///
///     fn do_it() -> Result<()> {
///         helper().context("failed to complete the work")?;
///         # const IGNORE: &str = stringify! {
///         ...
///         # };
///         # unreachable!()
///     }
///
///     fn main() {
///         let err = do_it().unwrap_err();
///         if let Some(e) = err.downcast_ref::<SuspiciousError>() {
///             // If helper() returned SuspiciousError, this downcast will
///             // correctly succeed even with the context in between.
///             # return;
///         }
///         # panic!("expected downcast to succeed");
///     }
///     ```
///
///   - **Attaching context whose type is used in downcasts onto errors whose
///     type is insignificant.**
///
///     Some codebases prefer to use machine-readable context to categorize
///     lower level errors in a way that will be actionable to higher levels of
///     the application.
///
///     ```
///     # use anyhow::bail;
///     # use thiserror::Error;
///     #
///     # #[derive(Error, Debug)]
///     # #[error("???")]
///     # struct HelperFailed;
///     #
///     # fn helper() -> Result<()> {
///     #     bail!("no such file or directory");
///     # }
///     #
///     use anyhow::{Context, Result};
///
///     fn do_it() -> Result<()> {
///         helper().context(HelperFailed)?;
///         # const IGNORE: &str = stringify! {
///         ...
///         # };
///         # unreachable!()
///     }
///
///     fn main() {
///         let err = do_it().unwrap_err();
///         if let Some(e) = err.downcast_ref::<HelperFailed>() {
///             // If helper failed, this downcast will succeed because
///             // HelperFailed is the context that has been attached to
///             // that error.
///             # return;
///         }
///         # panic!("expected downcast to succeed");
///     }
///     ```
pub trait Context<T, E>: context::private::Sealed {
    /// Wrap the error value with additional context.
    fn context<C>(self, context: C) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static;

    /// Wrap the error value with additional context that is evaluated lazily
    /// only once an error does occur.
    fn with_context<C, F>(self, f: F) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
        F: FnOnce() -> C;
}

// Not public API. Referenced by macro-generated code.
#[doc(hidden)]
pub mod private {
    use crate::Error;
    use std::fmt::{Debug, Display};

    #[cfg(backtrace)]
    use std::backtrace::Backtrace;

    pub use crate::kind::{AdhocKind, TraitKind};

    pub fn new_adhoc<M>(message: M) -> Error
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::from_adhoc(message, backtrace!())
    }
}
<commit_msg>Add Clone impl for anyhow::Chain<commit_after>//! This library provides [`anyhow::Error`][Error], a trait object based error
//! type for easy idiomatic error handling in Rust applications.
//!
//!

//!
//! # Details
//!
//! - Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as
//!   the return type of any fallible function.
//!
//!   Within the function, use `?` to easily propagate any error that implements
//!   the `std::error::Error` trait.
//!
//!   ```
//!   # pub trait Deserialize {}
//!   #
//!   # mod serde_json {
//!   #     use super::Deserialize;
//!   #     use std::io;
//!   #
//!   #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # struct ClusterMap;
//!   #
//!   # impl Deserialize for ClusterMap {}
//!   #
//!   use anyhow::Result;
//!
//!   fn get_cluster_info() -> Result<ClusterMap> {
//!       let config = std::fs::read_to_string("cluster.json")?;
//!       let map: ClusterMap = serde_json::from_str(&config)?;
//!       Ok(map)
//!   }
//!   #
//!   # fn main() {}
//!   ```
//!
//! - Attach context to help the person troubleshooting the error understand
//!   where things went wrong. A low-level error like "No such file or
//!   directory" can be annoying to debug without more context about what higher
//!   level step the application was in the middle of.
//!
//!   ```
//!   # struct It;
//!   #
//!   # impl It {
//!   #     fn detach(&self) -> Result<()> {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   use anyhow::{Context, Result};
//!
//!   fn main() -> Result<()> {
//!       # return Ok(());
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # let it = It;
//!       # let path = "./path/to/instrs.jsox";
//!       #
//!       it.detach().context("failed to detach the important thing")?;
//!
//!       let content = std::fs::read(path)
//!           .with_context(|| format!("failed to read instrs from {}", path))?;
//!       #
//!       # const _: &str = stringify! {
//!       ...
//!       # };
//!       #
//!       # Ok(())
//!   }
//!   ```
//!
//!   ```console
//!   Error: failed to read instrs from ./path/to/instrs.jsox
//!
//!   Caused by:
//!       No such file or directory (os error 2)
//!   ```
//!
//! - Downcasting is supported and can be by value, by shared reference, or by
//!   mutable reference as needed.
//!
//!   ```
//!   # use anyhow::anyhow;
//!   # use std::fmt::{self, Display};
//!   # use std::task::Poll;
//!   #
//!   # #[derive(Debug)]
//!   # enum DataStoreError {
//!   #     Censored(()),
//!   # }
//!   #
//!   # impl Display for DataStoreError {
//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   #
//!   # impl std::error::Error for DataStoreError {}
//!   #
//!   # const REDACTED_CONTENT: () = ();
//!   #
//!   # let error = anyhow!("...");
//!   # let root_cause = &error;
//!   #
//!   # let ret =
//!   // If the error was caused by redaction, then return a
//!   // tombstone instead of the content.
//!   match root_cause.downcast_ref::<DataStoreError>() {
//!       Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
//!       None => Err(error),
//!   }
//!   # ;
//!   ```
//!
//! - A backtrace is captured and printed with the error if the underlying error
//!   type does not already provide its own. In order to see backtraces, the
//!   `RUST_LIB_BACKTRACE=1` environment variable must be defined.
//!
//! - Anyhow works with any error type that has an impl of `std::error::Error`,
//!   including ones defined in your crate. We do not bundle a `derive(Error)`
//!   macro but you can write the impls yourself or use a standalone macro like
//!   [thiserror].
//!
//!   [thiserror]: https://github.com/dtolnay/thiserror
//!
//!   ```
//!   use thiserror::Error;
//!
//!   #[derive(Error, Debug)]
//!   pub enum FormatError {
//!       #[error("invalid header (expected {expected:?}, got {found:?})")]
//!       InvalidHeader {
//!           expected: String,
//!           found: String,
//!       },
//!       #[error("missing attribute: {0}")]
//!       MissingAttribute(String),
//!   }
//!   ```
//!
//! - One-off error messages can be constructed using the `anyhow!` macro, which
//!   supports string interpolation and produces an `anyhow::Error`.
//!
//!   ```
//!   # use anyhow::{anyhow, Result};
//!   #
//!   # fn demo() -> Result<()> {
//!   #     let missing = "...";
//!   return Err(anyhow!("missing attribute: {}", missing));
//!   #     Ok(())
//!   # }
//!   ```

#![doc(html_root_url = "https://docs.rs/anyhow/1.0.19")]
#![cfg_attr(backtrace, feature(backtrace))]
#![allow(
    clippy::needless_doctest_main,
    clippy::new_ret_no_self,
    clippy::wrong_self_convention
)]

#[macro_use]
mod backtrace;
mod context;
mod error;
mod kind;
mod macros;

#[cfg(not(feature = "std"))]
compile_error!("no_std support is not implemented yet");

use crate::error::ErrorImpl;
use std::error::Error as StdError;
use std::fmt::Display;
use std::mem::ManuallyDrop;

pub use anyhow as format_err;

/// The `Error` type, a wrapper around a dynamic error type.
///
/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these
/// differences:
///
/// - `Error` requires that the error is `Send`, `Sync`, and `'static`.
/// - `Error` guarantees that a backtrace is available, even if the underlying
///   error type does not provide one.
/// - `Error` is represented as a narrow pointer — exactly one word in
///   size instead of two.
pub struct Error {
    inner: ManuallyDrop<Box<ErrorImpl<()>>>,
}

/// Iterator of a chain of source errors.
///
/// This type is the iterator returned by [`Error::chain`].
///
/// # Example
///
/// ```
/// use anyhow::Error;
/// use std::io;
///
/// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
///     for cause in error.chain() {
///         if let Some(io_error) = cause.downcast_ref::<io::Error>() {
///             return Some(io_error.kind());
///         }
///     }
///     None
/// }
/// ```
#[derive(Clone)]
pub struct Chain<'a> {
    next: Option<&'a (dyn StdError + 'static)>,
}

/// `Result<T, Error>`
///
/// This is a reasonable return type to use throughout your application but also
/// for `fn main`; if you do, failures will be printed along with any
/// [context][Context] and a backtrace if one was captured.
///
/// `anyhow::Result` may be used with one *or* two type parameters.
///
/// ```rust
/// use anyhow::Result;
///
/// # const IGNORE: &str = stringify! {
/// fn demo1() -> Result<T> {...}
///            // ^ equivalent to std::result::Result<T, anyhow::Error>
///
/// fn demo2() -> Result<T, OtherError> {...}
///            // ^ equivalent to std::result::Result<T, OtherError>
/// # };
/// ```
///
/// # Example
///
/// ```
/// # pub trait Deserialize {}
/// #
/// # mod serde_json {
/// #     use super::Deserialize;
/// #     use std::io;
/// #
/// #     pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
/// #         unimplemented!()
/// #     }
/// # }
/// #
/// # #[derive(Debug)]
/// # struct ClusterMap;
/// #
/// # impl Deserialize for ClusterMap {}
/// #
/// use anyhow::Result;
///
/// fn main() -> Result<()> {
///     # return Ok(());
///     let config = std::fs::read_to_string("cluster.json")?;
///     let map: ClusterMap = serde_json::from_str(&config)?;
///     println!("cluster info: {:#?}", map);
///     Ok(())
/// }
/// ```
pub type Result<T, E = Error> = std::result::Result<T, E>;

/// Provides the `context` method for `Result`.
///
/// This trait is sealed and cannot be implemented for types outside of
/// `anyhow`.
///
///

///
/// # Example
///
/// ```
/// use anyhow::{Context, Result};
/// use std::fs;
/// use std::path::PathBuf;
///
/// pub struct ImportantThing {
///     path: PathBuf,
/// }
///
/// impl ImportantThing {
///     # const IGNORE: &'static str = stringify! {
///     pub fn detach(&mut self) -> Result<()> {...}
///     # };
///     # fn detach(&mut self) -> Result<()> {
///     #     unimplemented!()
///     # }
/// }
///
/// pub fn do_it(mut it: ImportantThing) -> Result<Vec<u8>> {
///     it.detach().context("failed to detach the important thing")?;
///
///     let path = &it.path;
///     let content = fs::read(path)
///         .with_context(|| format!("failed to read instrs from {}", path.display()))?;
///
///     Ok(content)
/// }
/// ```
///
/// When printed, the outermost context would be printed first and the lower
/// level underlying causes would be enumerated below.
///
/// ```console
/// Error: failed to read instrs from ./path/to/instrs.jsox
///
/// Caused by:
///     No such file or directory (os error 2)
/// ```
///
///

///
/// # Effect on downcasting
///
/// After attaching context of type `C` onto an error of type `E`, the resulting
/// `anyhow::Error` may be downcast to `C` **or** to `E`.
///
/// That is, in codebases that rely on downcasting, Anyhow's context supports
/// both of the following use cases:
///
///   - **Attaching context whose type is insignificant onto errors whose type
///     is used in downcasts.**
///
///     In other error libraries whose context is not designed this way, it can
///     be risky to introduce context to existing code because new context might
///     break existing working downcasts. In Anyhow, any downcast that worked
///     before adding context will continue to work after you add a context, so
///     you should freely add human-readable context to errors wherever it would
///     be helpful.
///
///     ```
///     # use anyhow::bail;
///     # use thiserror::Error;
///     #
///     # #[derive(Error, Debug)]
///     # #[error("???")]
///     # struct SuspiciousError;
///     #
///     # fn helper() -> Result<()> {
///     #     bail!(SuspiciousError);
///     # }
///     #
///     use anyhow::{Context, Result};
///
///     fn do_it() -> Result<()> {
///         helper().context("failed to complete the work")?;
///         # const IGNORE: &str = stringify! {
///         ...
///         # };
///         # unreachable!()
///     }
///
///     fn main() {
///         let err = do_it().unwrap_err();
///         if let Some(e) = err.downcast_ref::<SuspiciousError>() {
///             // If helper() returned SuspiciousError, this downcast will
///             // correctly succeed even with the context in between.
///             # return;
///         }
///         # panic!("expected downcast to succeed");
///     }
///     ```
///
///   - **Attaching context whose type is used in downcasts onto errors whose
///     type is insignificant.**
///
///     Some codebases prefer to use machine-readable context to categorize
///     lower level errors in a way that will be actionable to higher levels of
///     the application.
///
///     ```
///     # use anyhow::bail;
///     # use thiserror::Error;
///     #
///     # #[derive(Error, Debug)]
///     # #[error("???")]
///     # struct HelperFailed;
///     #
///     # fn helper() -> Result<()> {
///     #     bail!("no such file or directory");
///     # }
///     #
///     use anyhow::{Context, Result};
///
///     fn do_it() -> Result<()> {
///         helper().context(HelperFailed)?;
///         # const IGNORE: &str = stringify! {
///         ...
///         # };
///         # unreachable!()
///     }
///
///     fn main() {
///         let err = do_it().unwrap_err();
///         if let Some(e) = err.downcast_ref::<HelperFailed>() {
///             // If helper failed, this downcast will succeed because
///             // HelperFailed is the context that has been attached to
///             // that error.
///             # return;
///         }
///         # panic!("expected downcast to succeed");
///     }
///     ```
pub trait Context<T, E>: context::private::Sealed {
    /// Wrap the error value with additional context.
    fn context<C>(self, context: C) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static;

    /// Wrap the error value with additional context that is evaluated lazily
    /// only once an error does occur.
    fn with_context<C, F>(self, f: F) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
        F: FnOnce() -> C;
}

// Not public API. Referenced by macro-generated code.
#[doc(hidden)]
pub mod private {
    use crate::Error;
    use std::fmt::{Debug, Display};

    #[cfg(backtrace)]
    use std::backtrace::Backtrace;

    pub use crate::kind::{AdhocKind, TraitKind};

    pub fn new_adhoc<M>(message: M) -> Error
    where
        M: Display + Debug + Send + Sync + 'static,
    {
        Error::from_adhoc(message, backtrace!())
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::{c_char, c_int, c_uint, c_void};
use std::sync::Arc;
use ffi::{QVariant, QrsEngine, QObject};
use std::path::Path;
use std::convert::AsRef;

/* Re-exports */

pub use variant::{Variant, FromQVariant, ToQVariant};
pub use ffi::QVariant as OpaqueQVariant;

/* Submodules */

#[allow(dead_code)]
mod ffi;
mod macros;
mod variant;

pub trait Object {
    fn qt_metaobject(&self) -> MetaObject;
    fn qt_metacall(&mut self, slot: i32, args: *const *const OpaqueQVariant);
}

pub fn __qobject_emit<T: Object>(obj: &T, id: u32) {
    unsafe {
        ffi::qmlrs_object_emit_signal(get_qobject(obj), id as c_uint);
    }
}

/* This is unsafe in case the user copies the data. Might need to figure out something different. */
fn get_qobject<T: Object>(ptr: &T) -> *mut QObject {
    unsafe {
        let t_addr: usize = std::mem::transmute(ptr);
        let hdr: &PropHdr<T> = std::mem::transmute(t_addr - std::mem::size_of::<*mut QObject>());
        hdr.qobj
    }
}

struct EngineInternal {
    p: *mut QrsEngine,
}

/* Hack to get invoke working. Need to figure out better way for invokes anyway.. */
unsafe impl Send for EngineInternal { }
unsafe impl Sync for EngineInternal { }

impl Drop for EngineInternal {
    fn drop(&mut self) {
        unsafe { ffi::qmlrs_destroy_engine(self.p); }
    }
}

pub struct Engine {
    i: Arc<EngineInternal>,
}

#[packed]
struct PropHdr<T: Object> {
    qobj: *mut QObject,
    obj: T
}

extern "C" fn slot_handler<T: Object>(data: *mut c_void, slot: c_int,
                                      args: *const *const ffi::QVariant)
{
    unsafe {
        let hdr: &mut PropHdr<T> = std::mem::transmute(data);
        hdr.obj.qt_metacall(slot as i32, args);
    }
}

impl Engine {
    pub fn new() -> Engine {
        let p = unsafe { ffi::qmlrs_create_engine() };
        assert!(!p.is_null());

        let i = Arc::new(EngineInternal {
            p: p,
        });

        Engine {
            i: i
        }
    }

    pub fn new_headless() -> Engine {
        let p = unsafe { ffi::qmlrs_create_engine_headless() };
        assert!(!p.is_null());

        let i = Arc::new(EngineInternal {
            p: p,
        });

        Engine {
            i: i
        }
    }

    pub fn load_url(&mut self, path: &str) {
        unsafe {
            ffi::qmlrs_engine_load_url(self.i.p, path.as_ptr() as *const c_char,
                                       path.len() as c_uint);
        }
    }

    pub fn load_local_file<P: AsRef<Path>>(&mut self, name: P) {
        let path_raw = std::env::current_dir().unwrap().join(name);
        let path
            = if cfg!(windows) {
                format!("/{}",path_raw.display())
            } else {
                format!("{}",path_raw.display())
            } ;
        self.load_url(&path);
    }

    pub fn exec(self) {
        unsafe { ffi::qmlrs_app_exec(); }
    }

    /*
    pub fn handle(&self) -> Handle {
        Handle { i: self.i.downgrade() }
    }
    */

    pub fn set_property<T: Object>(&mut self, name: &str, obj: T) {
        unsafe {
            let mo = obj.qt_metaobject().p;
            let mut boxed = Box::new(PropHdr { qobj: std::ptr::null_mut(), obj: obj });
            let qobj = ffi::qmlrs_metaobject_instantiate(
                mo, slot_handler::<T>, &mut *boxed as *mut PropHdr<T> as *mut c_void);

            boxed.qobj = qobj;

            ffi::qmlrs_engine_set_property(self.i.p, name.as_ptr() as *const c_char,
                                           name.len() as c_uint, qobj);

            std::mem::forget(boxed);
        }
    }
}

/* MetaObjects currently leak. Once a cache system is implemented, this should be fine. */

#[allow(missing_copy_implementations)]
pub struct MetaObject {
    p: *mut ffi::QrsMetaObject
}

impl MetaObject {
    pub fn new() -> MetaObject {
        let p = unsafe { ffi::qmlrs_metaobject_create() };
        assert!(!p.is_null());

        MetaObject { p: p }
    }

    pub fn slot(self, name: &str, argc: u8) -> MetaObject {
        unsafe {
            ffi::qmlrs_metaobject_add_slot(self.p, name.as_ptr() as *const c_char,
                                           name.len() as c_uint, argc as c_uint);
        }
        self
    }

    pub fn signal(self, name: &str, argc: u8) -> MetaObject {
        unsafe {
            ffi::qmlrs_metaobject_add_signal(self.p, name.as_ptr() as *const c_char,
                                             name.len() as c_uint, argc as c_uint);
        }
        self
    }
}

/*
pub struct Handle {
    i: Weak<EngineInternal>
}

impl Handle {
    pub fn invoke(&self, method: &str, args: &[Variant]) -> Result<Option<Variant>, &'static str> {
        unsafe {
            let cstr = method.to_c_str();

            let c_args = ffi::qmlrs_varlist_create();
            assert!(!c_args.is_null());
            for arg in args.iter() {
                let c_arg = ffi::qmlrs_varlist_push(c_args);
                assert!(!c_arg.is_null());
                arg.to_qvariant(c_arg);
            }

            let result = ffi::qmlrs_variant_create();
            assert!(!result.is_null());

            match self.i.upgrade() {
                Some(i) => ffi::qmlrs_engine_invoke(i.p, cstr.as_ptr(), result,
                                               c_args as *const QVariantList),
                None    => {
                    ffi::qmlrs_variant_destroy(result);
                    ffi::qmlrs_varlist_destroy(c_args);
                    return Err("View has been freed")
                }
            }

            ffi::qmlrs_varlist_destroy(c_args);

            let ret = FromQVariant::from_qvariant(result as *const QVariant);
            ffi::qmlrs_variant_destroy(result);

            Ok(ret)
        }
    }
}
*/

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

    #[test]
    fn test_create_engine() {
        Engine::new_headless();
    }
}
<commit_msg>Fix last commit.<commit_after>extern crate libc;

use libc::{c_char, c_int, c_uint, c_void};
use std::sync::Arc;
use ffi::{QVariant, QrsEngine, QObject};
use std::path::Path;
use std::convert::AsRef;

/* Re-exports */

pub use variant::{Variant, FromQVariant, ToQVariant};
pub use ffi::QVariant as OpaqueQVariant;

/* Submodules */

#[allow(dead_code)]
mod ffi;
mod macros;
mod variant;

pub trait Object {
    fn qt_metaobject(&self) -> MetaObject;
    fn qt_metacall(&mut self, slot: i32, args: *const *const OpaqueQVariant);
}

pub fn __qobject_emit<T: Object>(obj: &T, id: u32) {
    unsafe {
        ffi::qmlrs_object_emit_signal(get_qobject(obj), id as c_uint);
    }
}

/* This is unsafe in case the user copies the data. Might need to figure out something different. */
fn get_qobject<T: Object>(ptr: &T) -> *mut QObject {
    unsafe {
        let t_addr: usize = std::mem::transmute(ptr);
        let hdr: &PropHdr<T> = std::mem::transmute(t_addr - std::mem::size_of::<*mut QObject>());
        hdr.qobj
    }
}

struct EngineInternal {
    p: *mut QrsEngine,
}

/* Hack to get invoke working. Need to figure out better way for invokes anyway.. */
unsafe impl Send for EngineInternal { }
unsafe impl Sync for EngineInternal { }

impl Drop for EngineInternal {
    fn drop(&mut self) {
        unsafe { ffi::qmlrs_destroy_engine(self.p); }
    }
}

pub struct Engine {
    i: Arc<EngineInternal>,
}

#[packed]
struct PropHdr<T: Object> {
    qobj: *mut QObject,
    obj: T
}

extern "C" fn slot_handler<T: Object>(data: *mut c_void, slot: c_int,
                                      args: *const *const ffi::QVariant)
{
    unsafe {
        let hdr: &mut PropHdr<T> = std::mem::transmute(data);
        hdr.obj.qt_metacall(slot as i32, args);
    }
}

impl Engine {
    pub fn new() -> Engine {
        let p = unsafe { ffi::qmlrs_create_engine() };
        assert!(!p.is_null());

        let i = Arc::new(EngineInternal {
            p: p,
        });

        Engine {
            i: i
        }
    }

    pub fn new_headless() -> Engine {
        let p = unsafe { ffi::qmlrs_create_engine_headless() };
        assert!(!p.is_null());

        let i = Arc::new(EngineInternal {
            p: p,
        });

        Engine {
            i: i
        }
    }

    pub fn load_url(&mut self, path: &str) {
        unsafe {
            ffi::qmlrs_engine_load_url(self.i.p, path.as_ptr() as *const c_char,
                                       path.len() as c_uint);
        }
    }

    pub fn load_local_file<P: AsRef<Path>>(&mut self, name: P) {
        let path_raw = std::env::current_dir().unwrap().join(name);
        let path
            = if cfg!(windows) {
                format!("file:///{}",path_raw.display())
            } else {
                format!("file://{}",path_raw.display())
            } ;
        self.load_url(&path);
    }

    pub fn exec(self) {
        unsafe { ffi::qmlrs_app_exec(); }
    }

    /*
    pub fn handle(&self) -> Handle {
        Handle { i: self.i.downgrade() }
    }
    */

    pub fn set_property<T: Object>(&mut self, name: &str, obj: T) {
        unsafe {
            let mo = obj.qt_metaobject().p;
            let mut boxed = Box::new(PropHdr { qobj: std::ptr::null_mut(), obj: obj });
            let qobj = ffi::qmlrs_metaobject_instantiate(
                mo, slot_handler::<T>, &mut *boxed as *mut PropHdr<T> as *mut c_void);

            boxed.qobj = qobj;

            ffi::qmlrs_engine_set_property(self.i.p, name.as_ptr() as *const c_char,
                                           name.len() as c_uint, qobj);

            std::mem::forget(boxed);
        }
    }
}

/* MetaObjects currently leak. Once a cache system is implemented, this should be fine. */

#[allow(missing_copy_implementations)]
pub struct MetaObject {
    p: *mut ffi::QrsMetaObject
}

impl MetaObject {
    pub fn new() -> MetaObject {
        let p = unsafe { ffi::qmlrs_metaobject_create() };
        assert!(!p.is_null());

        MetaObject { p: p }
    }

    pub fn slot(self, name: &str, argc: u8) -> MetaObject {
        unsafe {
            ffi::qmlrs_metaobject_add_slot(self.p, name.as_ptr() as *const c_char,
                                           name.len() as c_uint, argc as c_uint);
        }
        self
    }

    pub fn signal(self, name: &str, argc: u8) -> MetaObject {
        unsafe {
            ffi::qmlrs_metaobject_add_signal(self.p, name.as_ptr() as *const c_char,
                                             name.len() as c_uint, argc as c_uint);
        }
        self
    }
}

/*
pub struct Handle {
    i: Weak<EngineInternal>
}

impl Handle {
    pub fn invoke(&self, method: &str, args: &[Variant]) -> Result<Option<Variant>, &'static str> {
        unsafe {
            let cstr = method.to_c_str();

            let c_args = ffi::qmlrs_varlist_create();
            assert!(!c_args.is_null());
            for arg in args.iter() {
                let c_arg = ffi::qmlrs_varlist_push(c_args);
                assert!(!c_arg.is_null());
                arg.to_qvariant(c_arg);
            }

            let result = ffi::qmlrs_variant_create();
            assert!(!result.is_null());

            match self.i.upgrade() {
                Some(i) => ffi::qmlrs_engine_invoke(i.p, cstr.as_ptr(), result,
                                               c_args as *const QVariantList),
                None    => {
                    ffi::qmlrs_variant_destroy(result);
                    ffi::qmlrs_varlist_destroy(c_args);
                    return Err("View has been freed")
                }
            }

            ffi::qmlrs_varlist_destroy(c_args);

            let ret = FromQVariant::from_qvariant(result as *const QVariant);
            ffi::qmlrs_variant_destroy(result);

            Ok(ret)
        }
    }
}
*/

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

    #[test]
    fn test_create_engine() {
        Engine::new_headless();
    }
}
<|endoftext|>


<commit_before>//! Providing the features between "full" and "derive" of syn.
//!
//! This crate provides the following two unique data structures.
//!
//! * [`syn_mid::ItemFn`] -- A function whose body is not parsed.
//!
//!   ```text
//!   fn process(n: usize) -> Result<()> { ... }
//!   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^     ^
//!   ```
//!
//! * [`syn_mid::Block`] -- A block whose body is not parsed.
//!
//!   ```text
//!   { ... }
//!   ^     ^
//!   ```
//!
//! Other data structures are the same as data structures of [syn]. These are defined in this crate
//! because they cannot be used in [syn] without "full" feature.
//!
//! ## Optional features
//!
//! syn-mid in the default features aims to provide the features between "full"
//! and "derive" of [syn].
//!
//! * **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
//!   types.
//!
//! [`syn_mid::ItemFn`]: struct.ItemFn.html
//! [`syn_mid::Block`]: struct.Block.html
//! [syn]: https://github.com/dtolnay/syn
//!

#![doc(html_root_url = "https://docs.rs/syn-mid/0.2.0")]
#![deny(unsafe_code)]
#![deny(bare_trait_objects, elided_lifetimes_in_paths)]
#![deny(unreachable_pub)]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(renamed_and_removed_lints, large_enum_variant)
)]

// Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.

extern crate proc_macro2;
extern crate quote;
extern crate syn;

#[macro_use]
mod macros;

mod arg;
mod pat;
mod path;

pub use self::arg::*;
pub use self::pat::*;

use proc_macro2::TokenStream;
use syn::{
    punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, ReturnType, Token, Visibility,
};

ast_struct! {
    /// A braced block containing Rust statements.
    pub struct Block {
        pub brace_token: token::Brace,
        /// Statements in a block
        pub stmts: TokenStream,
    }
}

ast_struct! {
    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
    /// }`.
    pub struct ItemFn {
        pub attrs: Vec<Attribute>,
        pub vis: Visibility,
        pub constness: Option<Token![const]>,
        pub unsafety: Option<Token![unsafe]>,
        pub asyncness: Option<Token![async]>,
        pub abi: Option<Abi>,
        pub ident: Ident,
        pub fn_token: Token![fn],
        pub generics: Generics,
        pub paren_token: token::Paren,
        pub inputs: Punctuated<FnArg, Token![,]>,
        pub output: ReturnType,
        pub block: Block,
    }
}

mod parsing {
    use syn::{
        braced, parenthesized,
        parse::{Parse, ParseStream, Result},
        Abi, Attribute, Generics, Ident, ReturnType, Token, Visibility, WhereClause,
    };

    use super::{Block, FnArg, ItemFn};

    impl Parse for Block {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let content;
            Ok(Block {
                brace_token: braced!(content in input),
                stmts: content.parse()?,
            })
        }
    }

    impl Parse for ItemFn {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let outer_attrs = input.call(Attribute::parse_outer)?;
            let vis: Visibility = input.parse()?;
            let constness: Option<Token![const]> = input.parse()?;
            let unsafety: Option<Token![unsafe]> = input.parse()?;
            let asyncness: Option<Token![async]> = input.parse()?;
            let abi: Option<Abi> = input.parse()?;
            let fn_token: Token![fn] = input.parse()?;
            let ident: Ident = input.parse()?;
            let generics: Generics = input.parse()?;

            let content;
            let paren_token = parenthesized!(content in input);
            let inputs = content.parse_terminated(FnArg::parse)?;

            let output: ReturnType = input.parse()?;
            let where_clause: Option<WhereClause> = input.parse()?;

            let block = input.parse()?;

            Ok(ItemFn {
                attrs: outer_attrs,
                vis,
                constness,
                unsafety,
                asyncness,
                abi,
                ident,
                fn_token,
                paren_token,
                inputs,
                output,
                generics: Generics {
                    where_clause,
                    ..generics
                },
                block,
            })
        }
    }
}

mod printing {
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};

    use super::{Block, ItemFn};

    impl ToTokens for Block {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.stmts.clone());
            });
        }
    }

    impl ToTokens for ItemFn {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            self.constness.to_tokens(tokens);
            self.unsafety.to_tokens(tokens);
            self.asyncness.to_tokens(tokens);
            self.abi.to_tokens(tokens);
            self.fn_token.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                self.inputs.to_tokens(tokens);
            });
            self.output.to_tokens(tokens);
            self.generics.where_clause.to_tokens(tokens);
            self.block.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.block.stmts.clone());
            });
        }
    }
}
<commit_msg>Allow clippy::eval_order_dependence<commit_after>//! Providing the features between "full" and "derive" of syn.
//!
//! This crate provides the following two unique data structures.
//!
//! * [`syn_mid::ItemFn`] -- A function whose body is not parsed.
//!
//!   ```text
//!   fn process(n: usize) -> Result<()> { ... }
//!   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^     ^
//!   ```
//!
//! * [`syn_mid::Block`] -- A block whose body is not parsed.
//!
//!   ```text
//!   { ... }
//!   ^     ^
//!   ```
//!
//! Other data structures are the same as data structures of [syn]. These are defined in this crate
//! because they cannot be used in [syn] without "full" feature.
//!
//! ## Optional features
//!
//! syn-mid in the default features aims to provide the features between "full"
//! and "derive" of [syn].
//!
//! * **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
//!   types.
//!
//! [`syn_mid::ItemFn`]: struct.ItemFn.html
//! [`syn_mid::Block`]: struct.Block.html
//! [syn]: https://github.com/dtolnay/syn
//!

#![doc(html_root_url = "https://docs.rs/syn-mid/0.2.0")]
#![deny(unsafe_code)]
#![deny(bare_trait_objects, elided_lifetimes_in_paths)]
#![deny(unreachable_pub)]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(renamed_and_removed_lints, eval_order_dependence, large_enum_variant)
)]

// Many of the code contained in this crate are copies from https://github.com/dtolnay/syn.

extern crate proc_macro2;
extern crate quote;
extern crate syn;

#[macro_use]
mod macros;

mod arg;
mod pat;
mod path;

pub use self::arg::*;
pub use self::pat::*;

use proc_macro2::TokenStream;
use syn::{
    punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, ReturnType, Token, Visibility,
};

ast_struct! {
    /// A braced block containing Rust statements.
    pub struct Block {
        pub brace_token: token::Brace,
        /// Statements in a block
        pub stmts: TokenStream,
    }
}

ast_struct! {
    /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
    /// }`.
    pub struct ItemFn {
        pub attrs: Vec<Attribute>,
        pub vis: Visibility,
        pub constness: Option<Token![const]>,
        pub unsafety: Option<Token![unsafe]>,
        pub asyncness: Option<Token![async]>,
        pub abi: Option<Abi>,
        pub ident: Ident,
        pub fn_token: Token![fn],
        pub generics: Generics,
        pub paren_token: token::Paren,
        pub inputs: Punctuated<FnArg, Token![,]>,
        pub output: ReturnType,
        pub block: Block,
    }
}

mod parsing {
    use syn::{
        braced, parenthesized,
        parse::{Parse, ParseStream, Result},
        Abi, Attribute, Generics, Ident, ReturnType, Token, Visibility, WhereClause,
    };

    use super::{Block, FnArg, ItemFn};

    impl Parse for Block {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let content;
            Ok(Block {
                brace_token: braced!(content in input),
                stmts: content.parse()?,
            })
        }
    }

    impl Parse for ItemFn {
        fn parse(input: ParseStream<'_>) -> Result<Self> {
            let outer_attrs = input.call(Attribute::parse_outer)?;
            let vis: Visibility = input.parse()?;
            let constness: Option<Token![const]> = input.parse()?;
            let unsafety: Option<Token![unsafe]> = input.parse()?;
            let asyncness: Option<Token![async]> = input.parse()?;
            let abi: Option<Abi> = input.parse()?;
            let fn_token: Token![fn] = input.parse()?;
            let ident: Ident = input.parse()?;
            let generics: Generics = input.parse()?;

            let content;
            let paren_token = parenthesized!(content in input);
            let inputs = content.parse_terminated(FnArg::parse)?;

            let output: ReturnType = input.parse()?;
            let where_clause: Option<WhereClause> = input.parse()?;

            let block = input.parse()?;

            Ok(ItemFn {
                attrs: outer_attrs,
                vis,
                constness,
                unsafety,
                asyncness,
                abi,
                ident,
                fn_token,
                paren_token,
                inputs,
                output,
                generics: Generics {
                    where_clause,
                    ..generics
                },
                block,
            })
        }
    }
}

mod printing {
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};

    use super::{Block, ItemFn};

    impl ToTokens for Block {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.stmts.clone());
            });
        }
    }

    impl ToTokens for ItemFn {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            self.constness.to_tokens(tokens);
            self.unsafety.to_tokens(tokens);
            self.asyncness.to_tokens(tokens);
            self.abi.to_tokens(tokens);
            self.fn_token.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                self.inputs.to_tokens(tokens);
            });
            self.output.to_tokens(tokens);
            self.generics.where_clause.to_tokens(tokens);
            self.block.brace_token.surround(tokens, |tokens| {
                tokens.append_all(self.block.stmts.clone());
            });
        }
    }
}
<|endoftext|>


<commit_before>//! bnf, a library for parsing Backus–Naur form context-free grammars
//!
//! Inspired by the JavaScript library [prettybnf](https://github.com/dhconnelly/prettybnf)
//!
//!
//! The code is available on [Github](https://github.com/snewt/bnf)
//!
//! ## What does a parsable BNF grammar look like?
//!
//! The following grammar from the [Wikipedia page on Backus-Naur form](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form#Example)
//! exemplifies a compatible grammar after adding ';' characters to indicate the end of a producion.
//!
//! ```text
//! <postal-address> ::= <name-part> <street-address> <zip-part>;
//!
//!         <name-part> ::= <personal-part> <last-name> <opt-suffix-part> <EOL>
//!                     | <personal-part> <name-part>;
//!
//!     <personal-part> ::= <initial> "." | <first-name>;
//!
//!     <street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL>;
//!
//!         <zip-part> ::= <town-name> "," <state-code> <ZIP-code> <EOL>;
//!
//! <opt-suffix-part> ::= "Sr." | "Jr." | <roman-numeral> | "";
//!     <opt-apt-num> ::= <apt-num> | "";
//! ```
//!
//! ## Output
//! Take the following grammar to be input to this library's `parse` function:
//!
//! ```text
//! <A> ::= <B> | "C";
//! <B> ::= "D" | "E";
//! ```
//!
//! The output is a `Grammar` object representing a tree that looks like this:
//!
//! ```text
//! Grammar {
//!     productions: [
//!         Production {
//!             lhs: Nonterminal(
//!                 "A"
//!             ),
//!             rhs: [
//!                 Expression {
//!                     terms: [
//!                         Nonterminal(
//!                             "B"
//!                         )
//!                     ]
//!                 },
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "C"
//!                         )
//!                     ]
//!                 }
//!             ]
//!         },
//!         Production {
//!             lhs: Nonterminal(
//!                 "B"
//!             ),
//!             rhs: [
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "D"
//!                         )
//!                     ]
//!                 },
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "E"
//!                         )
//!                     ]
//!                 }
//!             ]
//!         }
//!     ]
//! }
//! ```
//!
//! ## Example
//!
//! ```rust
//! extern crate bnf;
//!
//! fn main() {
//!     let input =
//!         "<postal-address> ::= <name-part> <street-address> <zip-part>;
//!
//!               <name-part> ::= <personal-part> <last-name> <opt-suffix-part> <EOL>
//!                             | <personal-part> <name-part>;
//!
//!           <personal-part> ::= <initial> \".\" | <first-name>;
//!
//!          <street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL>;
//!
//!                <zip-part> ::= <town-name> \",\" <state-code> <ZIP-code> <EOL>;
//!
//!         <opt-suffix-part> ::= \"Sr.\" | \"Jr.\" | <roman-numeral> | \"\";
//!             <opt-apt-num> ::= <apt-num> | \"\";";
//!
//!     let grammar = bnf::parse(input);
//!     println!("{:#?}", grammar);
//! }
//! ```
//!

#[macro_use] extern crate nom;
mod parsers;
mod reports;
pub mod node;
use node::{Grammar};
use nom::{IResult};

/// Parse a BNF grammer
pub fn parse(input: &str) -> Grammar {
    match parsers::grammar(input.as_bytes()) {
        IResult::Done(_,o) => return o,
        IResult::Error(e) => {
            reports::report_error(e);
        }
        IResult::Incomplete(n) => reports::report_incomplete(n, input.len()),
    }

    Grammar::new()
}
<commit_msg>propigate previous commit's README changes to lib.rs documentation<commit_after>//! bnf, a library for parsing Backus–Naur form context-free grammars
//!
//! Inspired by the JavaScript library [prettybnf](https://github.com/dhconnelly/prettybnf)
//!
//!
//! The code is available on [Github](https://github.com/snewt/bnf)
//!
//! ## What does a parsable BNF grammar look like?
//!
//! The following grammar from the [Wikipedia page on Backus-Naur form](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form#Example)
//! exemplifies a compatible grammar after adding ';' characters to indicate the end of each producion.
//!
//! ```text
//! <postal-address> ::= <name-part> <street-address> <zip-part>;
//!
//!         <name-part> ::= <personal-part> <last-name> <opt-suffix-part> <EOL>
//!                     | <personal-part> <name-part>;
//!
//!     <personal-part> ::= <initial> "." | <first-name>;
//!
//!     <street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL>;
//!
//!         <zip-part> ::= <town-name> "," <state-code> <ZIP-code> <EOL>;
//!
//! <opt-suffix-part> ::= "Sr." | "Jr." | <roman-numeral> | "";
//!     <opt-apt-num> ::= <apt-num> | "";
//! ```
//!
//! ## Output
//! Take the following grammar to be input to this library's `parse` function:
//!
//! ```text
//! <A> ::= <B> | "C";
//! <B> ::= "D" | "E";
//! ```
//!
//! The output is a `Grammar` object representing a tree that looks like this:
//!
//! ```text
//! Grammar {
//!     productions: [
//!         Production {
//!             lhs: Nonterminal(
//!                 "A"
//!             ),
//!             rhs: [
//!                 Expression {
//!                     terms: [
//!                         Nonterminal(
//!                             "B"
//!                         )
//!                     ]
//!                 },
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "C"
//!                         )
//!                     ]
//!                 }
//!             ]
//!         },
//!         Production {
//!             lhs: Nonterminal(
//!                 "B"
//!             ),
//!             rhs: [
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "D"
//!                         )
//!                     ]
//!                 },
//!                 Expression {
//!                     terms: [
//!                         Terminal(
//!                             "E"
//!                         )
//!                     ]
//!                 }
//!             ]
//!         }
//!     ]
//! }
//! ```
//!
//! ## Example
//!
//! ```rust
//! extern crate bnf;
//!
//! fn main() {
//!     let input =
//!         "<postal-address> ::= <name-part> <street-address> <zip-part>;
//!
//!               <name-part> ::= <personal-part> <last-name> <opt-suffix-part> <EOL>
//!                             | <personal-part> <name-part>;
//!
//!           <personal-part> ::= <initial> \".\" | <first-name>;
//!
//!          <street-address> ::= <house-num> <street-name> <opt-apt-num> <EOL>;
//!
//!                <zip-part> ::= <town-name> \",\" <state-code> <ZIP-code> <EOL>;
//!
//!         <opt-suffix-part> ::= \"Sr.\" | \"Jr.\" | <roman-numeral> | \"\";
//!             <opt-apt-num> ::= <apt-num> | \"\";";
//!
//!     let grammar = bnf::parse(input);
//!     println!("{:#?}", grammar);
//! }
//! ```
//!

#[macro_use] extern crate nom;
mod parsers;
mod reports;
pub mod node;
use node::{Grammar};
use nom::{IResult};

/// Parse a BNF grammer
pub fn parse(input: &str) -> Grammar {
    match parsers::grammar(input.as_bytes()) {
        IResult::Done(_,o) => return o,
        IResult::Error(e) => {
            reports::report_error(e);
        }
        IResult::Incomplete(n) => reports::report_incomplete(n, input.len()),
    }

    Grammar::new()
}
<|endoftext|>