<commit_before>use futures::Stream;
use futures::future::Future;
use futures::sync::oneshot;
use hyper;
use hyper::{Body, Request};
use hyper::header::USER_AGENT;
use hyper_rustls::HttpsConnector;
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
use serde_json;
use std::collections::HashMap;
use tokio;

use errors;
use errors::*;

pub use hyper::Method;

pub struct HTTPClient {
    api_base: String,
    headers: HashMap<&'static str, String>,
}

struct InternalResp {
    data: hyper::Chunk,
    headers: hyper::HeaderMap,
    status: hyper::StatusCode,
}

pub struct HTTPResponse<T> {
    pub item: T,
    pub headers: hyper::HeaderMap,
    pub status: hyper::StatusCode,
}

type InternalResponseResult = Result<InternalResp>;
type FutureInternalResponse = oneshot::Receiver<InternalResponseResult>;

impl HTTPClient {
    pub fn new(api_base: &str) -> HTTPClient {
        HTTPClient {
            api_base: api_base.into(),
            headers: HashMap::new(),
        }
    }

    pub fn with_headers(self, headers: HashMap<&'static str, String>) -> HTTPClient {
        let mut c = self;
        c.headers = headers;
        c
    }

    pub fn get<T>(&self, path: &str) -> Result<T>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de::<T, ()>(Method::GET, path, None).map(|res| res.item)
    }

    pub fn get_async<T>(&self, path: &str) -> impl Future<Item = HTTPResponse<T>, Error = errors::Error>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de_async::<T, ()>(Method::GET, path, None)
    }

    pub fn post<T, U: Serialize>(&self, path: &str, body: &U) -> Result<T>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de::<T, U>(Method::POST, path, Some(body)).map(|res| res.item)
    }

    pub fn post_async<T, U: Serialize>(
        &self,
        path: &str,
        body: &U,
    ) -> impl Future<Item = HTTPResponse<T>, Error = errors::Error>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de_async::<T, U>(Method::POST, path, Some(body))
    }

    pub fn post_void<U: Serialize>(&self, path: &str, body: &U) -> Result<()> {
        self.request_void::<U>(Method::POST, path, Some(body)).map(|_| ())
    }

    pub fn post_void_async<U: Serialize>(
        &self,
        path: &str,
        body: &U,
    ) -> impl Future<Item = HTTPResponse<()>, Error = errors::Error> {
        self.request_void_async::<U>(Method::POST, path, Some(body))
    }

    pub fn put<T, U: Serialize>(&self, path: &str, body: &U) -> Result<T>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de::<T, U>(Method::PUT, path, Some(body)).map(|res| res.item)
    }

    pub fn put_async<T, U: Serialize>(
        &self,
        path: &str,
        body: &U,
    ) -> impl Future<Item = HTTPResponse<T>, Error = errors::Error>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de_async::<T, U>(Method::PUT, path, Some(body))
    }

    pub fn put_void<U: Serialize>(&self, path: &str, body: &U) -> Result<()> {
        self.request_void::<U>(Method::PUT, path, Some(body)).map(|_| ())
    }

    pub fn put_void_async<U: Serialize>(
        &self,
        path: &str,
        body: &U,
    ) -> impl Future<Item = HTTPResponse<()>, Error = errors::Error> {
        self.request_void_async::<U>(Method::PUT, path, Some(body))
    }

    pub fn delete_void(&self, path: &str) -> Result<()> {
        self.request_void::<()>(Method::DELETE, path, None).map(|_| ())
    }

    pub fn delete_void_async(&self, path: &str) -> impl Future<Item = HTTPResponse<()>, Error = errors::Error> {
        self.request_void_async::<()>(Method::DELETE, path, None)
    }

    pub fn request_de<T, U: Serialize>(&self, method: Method, path: &str, body: Option<&U>) -> Result<HTTPResponse<T>>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de_async(method, path, body).wait().map_err(|e| {
            Error::from(format!("Error waiting for HTTP response: {}", e))
        })
    }

    pub fn request_raw<U: Serialize>(
        &self,
        method: Method,
        path: &str,
        body: Option<&U>,
    ) -> Result<HTTPResponse<Vec<u8>>> {
        self.request_raw_async(method, path, body).wait().map_err(|e| {
            Error::from(format!("Error waiting for HTTP response: {}", e))
        })
    }

    pub fn request_void<U: Serialize>(&self, method: Method, path: &str, body: Option<&U>) -> Result<HTTPResponse<()>> {
        self.request_void_async(method, path, body).wait().map_err(|e| {
            Error::from(format!("Error waiting for HTTP response: {}", e))
        })
    }

    pub fn request_de_async<T, U: Serialize>(
        &self,
        method: Method,
        path: &str,
        body: Option<&U>,
    ) -> impl Future<Item = HTTPResponse<T>, Error = errors::Error>
    where
        T: DeserializeOwned + Send + 'static,
    {
        let path = path.to_string();
        self.request_async(method, &path, body)
            .or_else(|_| Err("HTTP Request was cancelled".into()))
            .and_then(move |res| {
                res.and_then(|res| {
                    if res.status.is_redirection() {
                        warn!(
                            "Received redirection when expected to receive data to deserialize. \
                                 Request: {}; Headers: {:?}",
                            path,
                            res.headers
                        );
                    }

                    serde_json::from_slice::<T>(&res.data)
                        .map_err(|e| {
                            format!("Error parsing response: {}\n---\n{}\n---", e, String::from_utf8_lossy(&res.data))
                                .into()
                        })
                        .map(|obj| {
                            HTTPResponse {
                                item: obj,
                                headers: res.headers,
                                status: res.status,
                            }
                        })
                })
            })
    }

    pub fn request_void_async<U: Serialize>(
        &self,
        method: Method,
        path: &str,
        body: Option<&U>,
    ) -> impl Future<Item = HTTPResponse<()>, Error = errors::Error> {
        self.request_async(method, path, body)
            .or_else(|_| Err("HTTP Request was cancelled".into()))
            .and_then(|res| {
                res.map(|r| {
                    HTTPResponse {
                        item: (),
                        headers: r.headers,
                        status: r.status,
                    }
                })
            })
    }

    pub fn request_raw_async<U: Serialize>(
        &self,
        method: Method,
        path: &str,
        body: Option<&U>,
    ) -> impl Future<Item = HTTPResponse<Vec<u8>>, Error = errors::Error> {
        self.request_async(method, path, body)
            .or_else(|_| Err("HTTP Request was cancelled".into()))
            .and_then(|res| {
                res.map(|r| {
                    HTTPResponse {
                        item: r.data.to_vec(),
                        headers: r.headers,
                        status: r.status,
                    }
                })
            })
    }

    fn request_async<U: Serialize>(&self, method: Method, path: &str, body: Option<&U>) -> FutureInternalResponse {
        let (tx, rx) = oneshot::channel::<InternalResponseResult>();

        let send_future = |it| if let Err(_) = tx.send(it) {
            error!("Error sending on future channel");
        };

        let url;
        if path.is_empty() {
            url = self.api_base.clone();
        } else if path.starts_with("http://") || path.starts_with("https://") {
            url = path.to_string();
        } else if path.starts_with("/") {
            url = self.api_base.clone() + path;
        } else {
            url = self.api_base.clone() + "/" + path;
        }
        let url: hyper::Uri = match url.parse() {
            Ok(u) => u,
            Err(e) => {
                send_future(Err(format!("Error parsing url: {}: {}", url, e).into()));
                return rx;
            }
        };

        let headers = self.headers.clone();

        let mut req = Request::builder();
        req.method(method).uri(url).header(USER_AGENT, "octobot");

        for (k, v) in &headers {
            match v.parse::<hyper::header::HeaderValue>() {
                Ok(v) => {
                    req.header(k.clone(), v);
                }
                Err(e) => {
                    error!("Skipping invalid header: {} => {}: {}", k, v, e);
                }

            }
        }

        let req = match body {
            Some(body) => {
                match serde_json::to_string(&body) {
                    Ok(j) => req.body(Body::from(j)),
                    Err(e) => {
                        send_future(Err(format!("Error json-encoding body: {}", e).into()));
                        return rx;
                    }
                }
            }
            None => req.body(Body::empty()),
        };
        let req = match req {
            Ok(r) => r,
            Err(e) => {
                send_future(Err(format!("Error building HTTP request: {}", e).into()));
                return rx;
            }
        };

        let path = path.to_string();

        // TODO: I wonder if these objects are expensive to create and we should be sharing them across requests?
        let client = hyper::Client::builder().build(HttpsConnector::new(4));

        tokio::spawn(
            client
                .request(req)
                .map_err(|e| {
                    error!("Error in HTTP request: {}", e);
                })
                .and_then(|res| {
                    let status = res.status();
                    let headers = res.headers().clone();
                    res.into_body()
                        .concat2()
                        .map_err(|e| {
                            error!("Error in HTTP request: {}", e);
                        })
                        .map(move |buffer| {
                            debug!("Response: HTTP {}\n---\n{}\n---", status, String::from_utf8_lossy(&buffer));
                            if !status.is_success() && !status.is_redirection() {
                                send_future(Err(
                                    format!(
                                        "Failed request to {}: HTTP {}\n---\n{}\n---",
                                        path,
                                        status,
                                        String::from_utf8_lossy(&buffer)
                                    ).into(),
                                ));
                            } else {
                                send_future(Ok(InternalResp {
                                    data: buffer,
                                    headers: headers,
                                    status: status,
                                }));
                            }
                        })
                }),
        );

        rx
    }
}
<commit_msg>Remove future::sync::oneshot use (#215)<commit_after>use futures::future::{self, Future};
use futures::Stream;
use hyper;
use hyper::header::USER_AGENT;
use hyper::{Body, Request};
use hyper_rustls::HttpsConnector;
use serde::de::DeserializeOwned;
use serde::ser::Serialize;
use serde_json;
use std::collections::HashMap;

use errors;
use errors::*;

pub use hyper::Method;

pub struct HTTPClient {
    api_base: String,
    headers: HashMap<&'static str, String>,
}

struct InternalResp {
    data: hyper::Chunk,
    headers: hyper::HeaderMap,
    status: hyper::StatusCode,
}

pub struct HTTPResponse<T> {
    pub item: T,
    pub headers: hyper::HeaderMap,
    pub status: hyper::StatusCode,
}

impl HTTPClient {
    pub fn new(api_base: &str) -> HTTPClient {
        HTTPClient {
            api_base: api_base.into(),
            headers: HashMap::new(),
        }
    }

    pub fn with_headers(self, headers: HashMap<&'static str, String>) -> HTTPClient {
        let mut c = self;
        c.headers = headers;
        c
    }

    pub fn get<T>(&self, path: &str) -> Result<T>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de::<T, ()>(Method::GET, path, None).map(|res| res.item)
    }

    pub fn get_async<T>(&self, path: &str) -> impl Future<Item = HTTPResponse<T>, Error = errors::Error> + Send
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de_async::<T, ()>(Method::GET, path, None)
    }

    pub fn post<T, U: Serialize>(&self, path: &str, body: &U) -> Result<T>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de::<T, U>(Method::POST, path, Some(body))
            .map(|res| res.item)
    }

    pub fn post_async<T, U: Serialize>(
        &self,
        path: &str,
        body: &U,
    ) -> impl Future<Item = HTTPResponse<T>, Error = errors::Error> + Send
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de_async::<T, U>(Method::POST, path, Some(body))
    }

    pub fn post_void<U: Serialize>(&self, path: &str, body: &U) -> Result<()> {
        self.request_void::<U>(Method::POST, path, Some(body)).map(|_| ())
    }

    pub fn post_void_async<U: Serialize>(
        &self,
        path: &str,
        body: &U,
    ) -> impl Future<Item = HTTPResponse<()>, Error = errors::Error> + Send {
        self.request_void_async::<U>(Method::POST, path, Some(body))
    }

    pub fn put<T, U: Serialize>(&self, path: &str, body: &U) -> Result<T>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de::<T, U>(Method::PUT, path, Some(body))
            .map(|res| res.item)
    }

    pub fn put_async<T, U: Serialize>(
        &self,
        path: &str,
        body: &U,
    ) -> impl Future<Item = HTTPResponse<T>, Error = errors::Error> + Send
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de_async::<T, U>(Method::PUT, path, Some(body))
    }

    pub fn put_void<U: Serialize>(&self, path: &str, body: &U) -> Result<()> {
        self.request_void::<U>(Method::PUT, path, Some(body)).map(|_| ())
    }

    pub fn put_void_async<U: Serialize>(
        &self,
        path: &str,
        body: &U,
    ) -> impl Future<Item = HTTPResponse<()>, Error = errors::Error> + Send {
        self.request_void_async::<U>(Method::PUT, path, Some(body))
    }

    pub fn delete_void(&self, path: &str) -> Result<()> {
        self.request_void::<()>(Method::DELETE, path, None).map(|_| ())
    }

    pub fn delete_void_async(&self, path: &str) -> impl Future<Item = HTTPResponse<()>, Error = errors::Error> + Send {
        self.request_void_async::<()>(Method::DELETE, path, None)
    }

    pub fn request_de<T, U: Serialize>(&self, method: Method, path: &str, body: Option<&U>) -> Result<HTTPResponse<T>>
    where
        T: DeserializeOwned + Send + 'static,
    {
        self.request_de_async(method, path, body)
            .wait()
            .map_err(|e| Error::from(format!("Error waiting for HTTP response: {}", e)))
    }

    pub fn request_raw<U: Serialize>(
        &self,
        method: Method,
        path: &str,
        body: Option<&U>,
    ) -> Result<HTTPResponse<Vec<u8>>> {
        self.request_raw_async(method, path, body)
            .wait()
            .map_err(|e| Error::from(format!("Error waiting for HTTP response: {}", e)))
    }

    pub fn request_void<U: Serialize>(&self, method: Method, path: &str, body: Option<&U>) -> Result<HTTPResponse<()>> {
        self.request_void_async(method, path, body)
            .wait()
            .map_err(|e| Error::from(format!("Error waiting for HTTP response: {}", e)))
    }

    pub fn request_de_async<T, U: Serialize>(
        &self,
        method: Method,
        path: &str,
        body: Option<&U>,
    ) -> impl Future<Item = HTTPResponse<T>, Error = errors::Error> + Send
    where
        T: DeserializeOwned + Send + 'static,
    {
        let path = path.to_string();
        self.request_async(method, &path, body)
            .or_else(|_| Err("HTTP Request was cancelled".into()))
            .and_then(move |res| {
                if res.status.is_redirection() {
                    warn!(
                        "Received redirection when expected to receive data to deserialize. \
                         Request: {}; Headers: {:?}",
                        path, res.headers
                    );
                }

                serde_json::from_slice::<T>(&res.data)
                    .map_err(|e| {
                        format!(
                            "Error parsing response: {}\n---\n{}\n---",
                            e,
                            String::from_utf8_lossy(&res.data)
                        ).into()
                    }).map(|obj| HTTPResponse {
                        item: obj,
                        headers: res.headers,
                        status: res.status,
                    })
            })
    }

    pub fn request_void_async<U: Serialize>(
        &self,
        method: Method,
        path: &str,
        body: Option<&U>,
    ) -> impl Future<Item = HTTPResponse<()>, Error = errors::Error> + Send {
        self.request_async(method, path, body)
            .or_else(|_| Err("HTTP Request was cancelled".into()))
            .map(|res| HTTPResponse {
                item: (),
                headers: res.headers,
                status: res.status,
            })
    }

    pub fn request_raw_async<U: Serialize>(
        &self,
        method: Method,
        path: &str,
        body: Option<&U>,
    ) -> impl Future<Item = HTTPResponse<Vec<u8>>, Error = errors::Error> + Send {
        self.request_async(method, path, body)
            .or_else(|_| Err("HTTP Request was cancelled".into()))
            .map(|res| HTTPResponse {
                item: res.data.to_vec(),
                headers: res.headers,
                status: res.status,
            })
    }

    fn request_async<U: Serialize>(
        &self,
        method: Method,
        path: &str,
        body: Option<&U>,
    ) -> Box<Future<Item = InternalResp, Error = errors::Error> + Send> {
        let url;
        if path.is_empty() {
            url = self.api_base.clone();
        } else if path.starts_with("http://") || path.starts_with("https://") {
            url = path.to_string();
        } else if path.starts_with("/") {
            url = self.api_base.clone() + path;
        } else {
            url = self.api_base.clone() + "/" + path;
        }
        let url: hyper::Uri = match url.parse() {
            Ok(u) => u,
            Err(e) => {
                return Box::new(future::err(format!("Error parsing url: {}: {}", url, e).into()));
            }
        };

        let headers = self.headers.clone();

        let mut req = Request::builder();
        req.method(method).uri(url).header(USER_AGENT, "octobot");

        for (k, v) in &headers {
            match v.parse::<hyper::header::HeaderValue>() {
                Ok(v) => {
                    req.header(k.clone(), v);
                }
                Err(e) => {
                    error!("Skipping invalid header: {} => {}: {}", k, v, e);
                }
            }
        }

        let req = match body {
            Some(body) => match serde_json::to_string(&body) {
                Ok(j) => req.body(Body::from(j)),
                Err(e) => {
                    return Box::new(future::err(format!("Error json-encoding body: {}", e).into()));
                }
            },
            None => req.body(Body::empty()),
        };
        let req = match req {
            Ok(r) => r,
            Err(e) => {
                return Box::new(future::err(format!("Error building HTTP request: {}", e).into()));
            }
        };

        let path = path.to_string();

        // TODO: I wonder if these objects are expensive to create and we should be sharing them across requests?
        let client = hyper::Client::builder().build(HttpsConnector::new(4));

        Box::new(
            client
                .request(req)
                .and_then(|res| {
                    let status = res.status();
                    let headers = res.headers().clone();
                    res.into_body().concat2().map(move |buffer| (status, headers, buffer))
                }).map_err(|e| {
                    let msg = format!("Error in HTTP request: {}", e);
                    error!("{}", msg);
                    msg.into()
                }).and_then(move |(status, headers, buffer)| {
                    debug!(
                        "Response: HTTP {}\n---\n{}\n---",
                        status,
                        String::from_utf8_lossy(&buffer)
                    );
                    if !status.is_success() && !status.is_redirection() {
                        future::err(
                            format!(
                                "Failed request to {}: HTTP {}\n---\n{}\n---",
                                path,
                                status,
                                String::from_utf8_lossy(&buffer)
                            ).into(),
                        )
                    } else {
                        future::ok(InternalResp {
                            data: buffer,
                            headers: headers,
                            status: status,
                        })
                    }
                }),
        )
    }
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Maciej Dziardziel <fiedzia@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE file
//  * that was distributed with this source code.

// spell-checker:ignore (ToDO) signalname pids

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use libc::{c_int, pid_t};
use std::io::Error;
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError};
use uucore::signals::ALL_SIGNALS;
use uucore::InvalidEncodingHandling;

static ABOUT: &str = "Send signal to processes or list information about signals.";

pub mod options {
    pub static PIDS_OR_SIGNALS: &str = "pids_of_signals";
    pub static LIST: &str = "list";
    pub static TABLE: &str = "table";
    pub static TABLE_OLD: &str = "table_old";
    pub static SIGNAL: &str = "signal";
}

#[derive(Clone, Copy)]
pub enum Mode {
    Kill,
    Table,
    List,
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let args = args
        .collect_str(InvalidEncodingHandling::Ignore)
        .accept_any();
    let (args, obs_signal) = handle_obsolete(args);

    let usage = format!("{} [OPTIONS]... PID...", uucore::execution_phrase());
    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    let mode = if matches.is_present(options::TABLE) || matches.is_present(options::TABLE_OLD) {
        Mode::Table
    } else if matches.is_present(options::LIST) {
        Mode::List
    } else {
        Mode::Kill
    };

    let pids_or_signals: Vec<String> = matches
        .values_of(options::PIDS_OR_SIGNALS)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    match mode {
        Mode::Kill => {
            let sig = match (obs_signal, matches.value_of(options::SIGNAL)) {
                (Some(s), Some(_)) => s, // -s takes precedence
                (Some(s), None) => s,
                (None, Some(s)) => s.to_owned(),
                (None, None) => "TERM".to_owned(),
            };
            kill(&sig, &pids_or_signals)
        }
        Mode::Table => {
            table();
            Ok(())
        }
        Mode::List => list(pids_or_signals.get(0).cloned()),
    }
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .arg(
            Arg::with_name(options::LIST)
                .short("l")
                .long(options::LIST)
                .help("Lists signals")
                .conflicts_with(options::TABLE)
                .conflicts_with(options::TABLE_OLD),
        )
        .arg(
            Arg::with_name(options::TABLE)
                .short("t")
                .long(options::TABLE)
                .help("Lists table of signals"),
        )
        .arg(Arg::with_name(options::TABLE_OLD).short("L").hidden(true))
        .arg(
            Arg::with_name(options::SIGNAL)
                .short("s")
                .long(options::SIGNAL)
                .help("Sends given signal")
                .takes_value(true),
        )
        .arg(
            Arg::with_name(options::PIDS_OR_SIGNALS)
                .hidden(true)
                .multiple(true),
        )
}

fn handle_obsolete(mut args: Vec<String>) -> (Vec<String>, Option<String>) {
    let mut i = 0;
    while i < args.len() {
        // this is safe because slice is valid when it is referenced
        let slice = &args[i].clone();
        if slice.starts_with('-') && slice.chars().nth(1).map_or(false, |c| c.is_digit(10)) {
            let val = &slice[1..];
            match val.parse() {
                Ok(num) => {
                    if uucore::signals::is_signal(num) {
                        args.remove(i);
                        return (args, Some(val.to_owned()));
                    }
                }
                Err(_) => break, /* getopts will error out for us */
            }
        }
        i += 1;
    }
    (args, None)
}

fn table() {
    let name_width = ALL_SIGNALS.iter().map(|n| n.len()).max().unwrap();

    for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
        print!("{0: >#2} {1: <#2$}", idx, signal, name_width + 2);
        if (idx + 1) % 7 == 0 {
            println!();
        }
    }
    println!();
}

fn print_signal(signal_name_or_value: &str) -> UResult<()> {
    for (value, &signal) in ALL_SIGNALS.iter().enumerate() {
        if signal == signal_name_or_value || (format!("SIG{}", signal)) == signal_name_or_value {
            println!("{}", value);
            return Ok(());
        } else if signal_name_or_value == value.to_string() {
            println!("{}", signal);
            return Ok(());
        }
    }
    Err(USimpleError::new(
        1,
        format!("unknown signal name {}", signal_name_or_value.quote()),
    ))
}

fn print_signals() {
    let mut pos = 0;
    for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
        pos += signal.len();
        print!("{}", signal);
        if idx > 0 && pos > 73 {
            println!();
            pos = 0;
        } else {
            pos += 1;
            print!(" ");
        }
    }
}

fn list(arg: Option<String>) -> UResult<()> {
    match arg {
        Some(ref x) => print_signal(x),
        None => {
            print_signals();
            Ok(())
        }
    }
}

fn kill(signalname: &str, pids: &[String]) -> UResult<()> {
    let optional_signal_value = uucore::signals::signal_by_name_or_value(signalname);
    let signal_value = match optional_signal_value {
        Some(x) => x,
        None => {
            return Err(USimpleError::new(
                1,
                format!("unknown signal name {}", signalname.quote()),
            ));
        }
    };
    for pid in pids {
        match pid.parse::<usize>() {
            Ok(x) => {
                if unsafe { libc::kill(x as pid_t, signal_value as c_int) } != 0 {
                    show!(USimpleError::new(1, format!("{}", Error::last_os_error())));
                }
            }
            Err(e) => {
                return Err(USimpleError::new(
                    1,
                    format!("failed to parse argument {}: {}", pid.quote(), e),
                ));
            }
        };
    }
    Ok(())
}
<commit_msg>kill: kill old form with signal name<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Maciej Dziardziel <fiedzia@gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE file
//  * that was distributed with this source code.

// spell-checker:ignore (ToDO) signalname pids

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use libc::{c_int, pid_t};
use std::io::Error;
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError};
use uucore::signals::{signal_by_name_or_value, ALL_SIGNALS};
use uucore::InvalidEncodingHandling;

static ABOUT: &str = "Send signal to processes or list information about signals.";

pub mod options {
    pub static PIDS_OR_SIGNALS: &str = "pids_of_signals";
    pub static LIST: &str = "list";
    pub static TABLE: &str = "table";
    pub static TABLE_OLD: &str = "table_old";
    pub static SIGNAL: &str = "signal";
}

#[derive(Clone, Copy)]
pub enum Mode {
    Kill,
    Table,
    List,
}

#[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let mut args = args
        .collect_str(InvalidEncodingHandling::Ignore)
        .accept_any();
    let obs_signal = handle_obsolete(&mut args);

    let usage = format!("{} [OPTIONS]... PID...", uucore::execution_phrase());
    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    let mode = if matches.is_present(options::TABLE) || matches.is_present(options::TABLE_OLD) {
        Mode::Table
    } else if matches.is_present(options::LIST) {
        Mode::List
    } else {
        Mode::Kill
    };

    let pids_or_signals: Vec<String> = matches
        .values_of(options::PIDS_OR_SIGNALS)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    match mode {
        Mode::Kill => {
            let sig = if let Some(signal) = obs_signal {
                signal
            } else if let Some(signal) = matches.value_of(options::SIGNAL) {
                parse_signal_value(signal)?
            } else {
                15_usize //SIGTERM
            };
            let pids = parse_pids(&pids_or_signals)?;
            kill(sig, &pids)
        }
        Mode::Table => {
            table();
            Ok(())
        }
        Mode::List => list(pids_or_signals.get(0).cloned()),
    }
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .arg(
            Arg::with_name(options::LIST)
                .short("l")
                .long(options::LIST)
                .help("Lists signals")
                .conflicts_with(options::TABLE)
                .conflicts_with(options::TABLE_OLD),
        )
        .arg(
            Arg::with_name(options::TABLE)
                .short("t")
                .long(options::TABLE)
                .help("Lists table of signals"),
        )
        .arg(Arg::with_name(options::TABLE_OLD).short("L").hidden(true))
        .arg(
            Arg::with_name(options::SIGNAL)
                .short("s")
                .long(options::SIGNAL)
                .help("Sends given signal")
                .takes_value(true),
        )
        .arg(
            Arg::with_name(options::PIDS_OR_SIGNALS)
                .hidden(true)
                .multiple(true),
        )
}

fn handle_obsolete(args: &mut Vec<String>) -> Option<usize> {
    // Sanity check
    if args.len() > 2 {
        // Old signal can only be in the first argument position
        let slice = args[1].as_str();
        if let Some(signal) = slice.strip_prefix('-') {
            // Check if it is a valid signal
            let opt_signal = signal_by_name_or_value(signal);
            if opt_signal.is_some() {
                // remove the signal before return
                args.remove(1);
                return opt_signal;
            }
        }
    }
    None
}

fn table() {
    let name_width = ALL_SIGNALS.iter().map(|n| n.len()).max().unwrap();

    for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
        print!("{0: >#2} {1: <#2$}", idx, signal, name_width + 2);
        if (idx + 1) % 7 == 0 {
            println!();
        }
    }
    println!();
}

fn print_signal(signal_name_or_value: &str) -> UResult<()> {
    for (value, &signal) in ALL_SIGNALS.iter().enumerate() {
        if signal == signal_name_or_value || (format!("SIG{}", signal)) == signal_name_or_value {
            println!("{}", value);
            return Ok(());
        } else if signal_name_or_value == value.to_string() {
            println!("{}", signal);
            return Ok(());
        }
    }
    Err(USimpleError::new(
        1,
        format!("unknown signal name {}", signal_name_or_value.quote()),
    ))
}

fn print_signals() {
    let mut pos = 0;
    for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
        pos += signal.len();
        print!("{}", signal);
        if idx > 0 && pos > 73 {
            println!();
            pos = 0;
        } else {
            pos += 1;
            print!(" ");
        }
    }
}

fn list(arg: Option<String>) -> UResult<()> {
    match arg {
        Some(ref x) => print_signal(x),
        None => {
            print_signals();
            Ok(())
        }
    }
}

fn parse_signal_value(signal_name: &str) -> UResult<usize> {
    let optional_signal_value = signal_by_name_or_value(signal_name);
    match optional_signal_value {
        Some(x) => Ok(x),
        None => Err(USimpleError::new(
            1,
            format!("unknown signal name {}", signal_name.quote()),
        )),
    }
}

fn parse_pids(pids: &[String]) -> UResult<Vec<usize>> {
    pids.iter()
        .map(|x| {
            x.parse::<usize>().map_err(|e| {
                USimpleError::new(1, format!("failed to parse argument {}: {}", x.quote(), e))
            })
        })
        .collect()
}

fn kill(signal_value: usize, pids: &[usize]) -> UResult<()> {
    for &pid in pids {
        if unsafe { libc::kill(pid as pid_t, signal_value as c_int) } != 0 {
            show!(USimpleError::new(1, format!("{}", Error::last_os_error())));
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use parser::parser::{parse};
use expr::Expr;
use expr::Expr::*;
use expr::Val::*;
use expr::UnOp::*;
use expr::BinOp::*;
use expr::Dec::*;
use state::State;
use runtime_error::RuntimeError;
use std::result;
use std::mem;

pub type Result<T> = result::Result<T, RuntimeError>;

pub struct Interpreter {
  pub state: State,
}

impl Interpreter {
  pub fn new() -> Interpreter {
    Interpreter {
      state: State::new(),
    }
  }

  pub fn step(&mut self, e: Expr) -> Result<Expr> {
    debug!("step(e) : {:?}", e);
    debug!("step(self.state) : {:?}", self.state.mem);

    let e1 = match e {
      Var(x) => {
        match self.state.get(x.clone()) {
          Some(e) => e,
          None => return Err(RuntimeError::VariableNotFound(x)),
        }
      },
      /**
       * Values are ineligible for step
       */
      Val(_) => {
        debug!("stepping on a value {:?}", e);
        return Err(RuntimeError::SteppingOnValue(e));
      },
      /**
       * Base cases
       */
      Uop(Not, box Val(Bool(b))) => {
        Val(Bool(!b))
      },
      Uop(Neg, box Val(Int(n))) => {
        Val(Int(-1 * n))
      },
      Bop(And, box Val(Bool(b1)), box Val(Bool(b2))) => {
        Val(Bool(b1 && b2))
      },
      Bop(Or, box Val(Bool(b1)), box Val(Bool(b2))) => {
        Val(Bool(b1 || b2))
      },
      Bop(Eq, box Val(v1), box Val(v2)) => {
        Val(Bool(v1 == v2))
      },
      Bop(Ne, box Val(v1), box Val(v2)) => {
        Val(Bool(v1 != v2))
      },
      Bop(Mod, box Val(Int(n1)), box Val(Int(n2))) => {
        // rust % gives the remainder, not modulus
        // let result = ((n1 % n2) + n2) % n2;
        let result = n1.checked_rem(n2)
          .ok_or(RuntimeError::IntegerUnderflow)?
          .checked_add(n2)
          .ok_or(RuntimeError::IntegerOverflow)?
          .checked_rem(n2)
          .ok_or(RuntimeError::IntegerUnderflow)?;

        Val(Int(result))
      },
      Bop(Lt, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 < n2))
      },
      Bop(Gt, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 > n2))
      },
      Bop(Leq, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 <= n2))
      },
      Bop(Geq, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 >= n2))
      },
      Bop(Plus, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_add(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerOverflow),
        }
      },
      Bop(Minus, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_sub(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerUnderflow),
        }
      },
      Bop(Times, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_mul(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerOverflow),
        }
      },
      Bop(Div, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_div(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerUnderflow),
        }
      },
      Bop(Seq, box Val(_), box e1) => {
        e1
      },
      Bop(Assign, box Var(x), box v @ Val(_)) => {
        self.state.assign(x, v.clone())?;
        debug!("done assigning {:?}", self.state.mem);
        v
      },
      Ternary(box Val(Bool(b)), box e1, box e2) => {
        match b {
          true => e1,
          false => e2,
        }
      },
      Decl(DConst, box Var(x), box v1 @ Val(_), box e1) => {
        self.state.alloc_const(x, v1)?;
        e1
      },
      Decl(DVar, box Var(x), box v1 @ Val(_), box e1) => {
        debug!("allocing {:?}", v1);
        self.state.alloc(x, v1)?;
        e1
      },
      // lambda lift so we can use iter() in guard
      // https://github.com/rust-lang/rfcs/issues/1006
      FnCall(
        box Val(Func(ref name, ref e1, ref xs)),
        ref es
      ) if (|| es.iter().all(|v| if let Val(_) = *v { true } else { false }))() => {
        self.state.begin_scope();

        // alloc the params
        for (xn, en) in xs.iter().zip(es.iter()) {
          if let &Var(ref x) = xn {
            self.state.alloc(x.clone(), en.clone())?;
          } else {
            return Err(RuntimeError::InvalidTypeConversion("var".to_string(), xn.clone()));
          }
        }

        // alloc the fn body for named functions
        if let Some(box Var(ref s)) = *name {
          self.state.alloc(s.clone(), Val(Func(name.clone(), e1.clone(), xs.clone())))?;
        }

        Scope(e1.clone())
      },
      Scope(box v @ Val(_)) => {
        self.state.end_scope();
        v
      },
      While(box Val(Bool(b)), e1o, _, e2o, e3) => {
        match b {
          true => While(e1o.clone(), e1o, e2o.clone(), e2o, e3),
          false => *e3,
        }
      },
      Print(box Val(v)) => {
        println!("{}", v);
        Val(Undefined)
      },
      /**
       * Search Cases
       */
      Bop(op, v1 @ box Val(_), box e2) => {
        Bop(
          op,
          v1,
          Box::new(self.step(e2)?)
        )
      },
      Bop(Assign, v1 @ box Var(_), box e2) => {
        Bop(
          Assign,
          v1,
          Box::new(self.step(e2)?)
        )
      },
      Bop(op, box e1, e2) => {
        Bop(op, Box::new(self.step(e1)?), e2)
      },
      Uop(op, box e1) => {
        Uop(op, Box::new(self.step(e1)?))
      },
      Ternary(box e1, e2, e3) => {
        Ternary(Box::new(self.step(e1)?), e2, e3)
      },
      While(box e1, e1o, v @ box Val(_), e2o, e3) => {
        While(Box::new(self.step(e1)?), e1o, v, e2o, e3)
      },
      While(e1, e1o, box e2, e2o, e3) => {
        While(e1, e1o, Box::new(self.step(e2)?), e2o, e3)
      },
      Decl(dt, box addr, box e1, e2) => {
        Decl(dt, Box::new(addr), Box::new(self.step(e1)?), e2)
      },
      FnCall(f @ box Val(Func(_, _, _)), mut args) => {
        // find the first nonvalue arg and call step() on it
        if let Some(index) = args.iter().position(|e| {
          match e {
            &Val(_) => false,
            _ => true,
          }
        }) {
          // temporary placeholder so we can safely move the value
          // this ensures good vec state in between when data is read and rewritten
          let expr = mem::replace(&mut args[index], Val(Undefined));
          args[index] = self.step(expr)?;
        }

        FnCall(f, args)
      },
      FnCall(box e1, args) => {
        FnCall(Box::new(self.step(e1)?), args)
      },
      Scope(box e1) => {
        Scope(Box::new(self.step(e1)?))
      },
      Print(box e1) => {
        Print(Box::new(self.step(e1)?))
      },
    };

    debug!("returning with mem {:?}" , self.state.mem);
    debug!("returning with e {:?}" , e1);
    Ok(e1)
  }

  pub fn eval(&mut self, input: &str) -> Result<Expr> {
    let mut e = parse(input)?;

    let mut num_iterations = 0;

    loop {
      if num_iterations > 1000000000 {
        return Err(RuntimeError::TooManyIterations(num_iterations))
      }

      debug!("-----------------");
      debug!("--- iterating on e {:?} ", e);
      debug!("--- iterating on m {:?} ", self.state.mem);
      num_iterations += 1;
      if let Val(_) = e {
        debug!("--- iterations: {}", num_iterations);
        return Ok(e.clone());
      } else {
        e = self.step(e.clone())?;
      }
    }
  }
}
<commit_msg>🎉smarter compiler, no need to clone every step, huge perf increase<commit_after>use parser::parser::{parse};
use expr::Expr;
use expr::Expr::*;
use expr::Val::*;
use expr::UnOp::*;
use expr::BinOp::*;
use expr::Dec::*;
use state::State;
use runtime_error::RuntimeError;
use std::result;
use std::mem;

pub type Result<T> = result::Result<T, RuntimeError>;

pub struct Interpreter {
  pub state: State,
}

impl Interpreter {
  pub fn new() -> Interpreter {
    Interpreter {
      state: State::new(),
    }
  }

  pub fn step(&mut self, e: Expr) -> Result<Expr> {
    debug!("step(e) : {:?}", e);
    debug!("step(self.state) : {:?}", self.state.mem);

    let e1 = match e {
      Var(x) => {
        match self.state.get(x.clone()) {
          Some(e) => e,
          None => return Err(RuntimeError::VariableNotFound(x)),
        }
      },
      /**
       * Values are ineligible for step
       */
      Val(_) => {
        debug!("stepping on a value {:?}", e);
        return Err(RuntimeError::SteppingOnValue(e));
      },
      /**
       * Base cases
       */
      Uop(Not, box Val(Bool(b))) => {
        Val(Bool(!b))
      },
      Uop(Neg, box Val(Int(n))) => {
        Val(Int(-1 * n))
      },
      Bop(And, box Val(Bool(b1)), box Val(Bool(b2))) => {
        Val(Bool(b1 && b2))
      },
      Bop(Or, box Val(Bool(b1)), box Val(Bool(b2))) => {
        Val(Bool(b1 || b2))
      },
      Bop(Eq, box Val(v1), box Val(v2)) => {
        Val(Bool(v1 == v2))
      },
      Bop(Ne, box Val(v1), box Val(v2)) => {
        Val(Bool(v1 != v2))
      },
      Bop(Mod, box Val(Int(n1)), box Val(Int(n2))) => {
        // rust % gives the remainder, not modulus
        // let result = ((n1 % n2) + n2) % n2;
        let result = n1.checked_rem(n2)
          .ok_or(RuntimeError::IntegerUnderflow)?
          .checked_add(n2)
          .ok_or(RuntimeError::IntegerOverflow)?
          .checked_rem(n2)
          .ok_or(RuntimeError::IntegerUnderflow)?;

        Val(Int(result))
      },
      Bop(Lt, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 < n2))
      },
      Bop(Gt, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 > n2))
      },
      Bop(Leq, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 <= n2))
      },
      Bop(Geq, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 >= n2))
      },
      Bop(Plus, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_add(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerOverflow),
        }
      },
      Bop(Minus, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_sub(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerUnderflow),
        }
      },
      Bop(Times, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_mul(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerOverflow),
        }
      },
      Bop(Div, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_div(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerUnderflow),
        }
      },
      Bop(Seq, box Val(_), box e1) => {
        e1
      },
      Bop(Assign, box Var(x), box v @ Val(_)) => {
        self.state.assign(x, v.clone())?;
        debug!("done assigning {:?}", self.state.mem);
        v
      },
      Ternary(box Val(Bool(b)), box e1, box e2) => {
        match b {
          true => e1,
          false => e2,
        }
      },
      Decl(DConst, box Var(x), box v1 @ Val(_), box e1) => {
        self.state.alloc_const(x, v1)?;
        e1
      },
      Decl(DVar, box Var(x), box v1 @ Val(_), box e1) => {
        debug!("allocing {:?}", v1);
        self.state.alloc(x, v1)?;
        e1
      },
      // lambda lift so we can use iter() in guard
      // https://github.com/rust-lang/rfcs/issues/1006
      FnCall(
        box Val(Func(ref name, ref e1, ref xs)),
        ref es
      ) if (|| es.iter().all(|v| if let Val(_) = *v { true } else { false }))() => {
        self.state.begin_scope();

        // alloc the params
        for (xn, en) in xs.iter().zip(es.iter()) {
          if let &Var(ref x) = xn {
            self.state.alloc(x.to_string(), en.clone())?;
          } else {
            return Err(RuntimeError::InvalidTypeConversion("var".to_string(), xn.clone()));
          }
        }

        // alloc the fn body for named functions
        if let Some(box Var(ref s)) = *name {
          self.state.alloc(s.clone(), Val(Func(name.clone(), e1.clone(), xs.clone())))?;
        }

        Scope(e1.clone())
      },
      Scope(box v @ Val(_)) => {
        self.state.end_scope();
        v
      },
      While(box Val(Bool(b)), e1o, _, e2o, e3) => {
        match b {
          true => While(e1o.clone(), e1o, e2o.clone(), e2o, e3),
          false => *e3,
        }
      },
      Print(box Val(v)) => {
        println!("{}", v);
        Val(Undefined)
      },
      /**
       * Search Cases
       */
      Bop(op, v1 @ box Val(_), box e2) => {
        Bop(
          op,
          v1,
          Box::new(self.step(e2)?)
        )
      },
      Bop(Assign, v1 @ box Var(_), box e2) => {
        Bop(
          Assign,
          v1,
          Box::new(self.step(e2)?)
        )
      },
      Bop(op, box e1, e2) => {
        Bop(op, Box::new(self.step(e1)?), e2)
      },
      Uop(op, box e1) => {
        Uop(op, Box::new(self.step(e1)?))
      },
      Ternary(box e1, e2, e3) => {
        Ternary(Box::new(self.step(e1)?), e2, e3)
      },
      While(box e1, e1o, v @ box Val(_), e2o, e3) => {
        While(Box::new(self.step(e1)?), e1o, v, e2o, e3)
      },
      While(e1, e1o, box e2, e2o, e3) => {
        While(e1, e1o, Box::new(self.step(e2)?), e2o, e3)
      },
      Decl(dt, box addr, box e1, e2) => {
        Decl(dt, Box::new(addr), Box::new(self.step(e1)?), e2)
      },
      FnCall(f @ box Val(Func(_, _, _)), mut args) => {
        // find the first nonvalue arg and call step() on it
        if let Some(index) = args.iter().position(|e| {
          match e {
            &Val(_) => false,
            _ => true,
          }
        }) {
          // temporary placeholder so we can safely move the value
          // this ensures good vec state in between when data is read and rewritten
          let expr = mem::replace(&mut args[index], Val(Undefined));
          args[index] = self.step(expr)?;
        }

        FnCall(f, args)
      },
      FnCall(box e1, args) => {
        FnCall(Box::new(self.step(e1)?), args)
      },
      Scope(box e1) => {
        Scope(Box::new(self.step(e1)?))
      },
      Print(box e1) => {
        Print(Box::new(self.step(e1)?))
      },
    };

    debug!("returning with mem {:?}" , self.state.mem);
    debug!("returning with e {:?}" , e1);
    Ok(e1)
  }

  pub fn eval(&mut self, input: &str) -> Result<Expr> {
    let mut e = parse(input)?;

    let mut num_iterations = 0;

    loop {
      if num_iterations > 1000000000 {
        return Err(RuntimeError::TooManyIterations(num_iterations))
      }

      debug!("-----------------");
      debug!("--- iterating on e {:?} ", e);
      debug!("--- iterating on m {:?} ", self.state.mem);
      num_iterations += 1;
      if let Val(_) = e {
        debug!("--- iterations: {}", num_iterations);
        return Ok(e);
      } else {
        e = self.step(e)?;
      }
    }
  }
}
<|endoftext|>


<commit_before>extern crate irc;

use std::sync::Mutex;
use std::sync::Arc;
use std::thread;

/// Reexport the irc crate server config for now. Example programs can just grab it from here rather
/// than know the irc crate internals.
pub use irc::client::data::Config;

use irc::client::data::Command;
use irc::client::data::message::ToMessage;
use irc::client::server::IrcServer;
use irc::client::server::Server;
use irc::client::server::utils::ServerExt;

use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;

use chatbot::Chatbot;
use adapter::ChatAdapter;
use message::IncomingMessage;

/// Connect your bot to IRC with the IrcAdapter
pub struct IrcAdapter {
    config: Config
}

impl IrcAdapter {
    pub fn new(config: Config) -> IrcAdapter {
        IrcAdapter {
            config: config
        }
    }
}

impl ChatAdapter for IrcAdapter {
    fn get_name(&self) -> &str {
        "IrcAdapter"
    }

    fn process_events(&self, bot: &Chatbot, tx_incoming: Sender<IncomingMessage>) {
        let server = Arc::new(IrcServer::from_config(self.config.clone()).unwrap());
        server.identify().unwrap();

        let (tx_outgoing, rx_outgoing) = channel();
        let name = bot.get_name().to_owned();

        {
            let server = server.clone();
            thread::Builder::new().name("IrcAdapter lisener".to_owned()).spawn(move || {

                for message in server.iter() {
                    if message.is_err() {
                        continue;
                    }

                    let msg = message.unwrap();

                    let user = msg.get_source_nickname().map(|user| user.to_owned());
                    if let Ok(command) = Command::from_message(&msg) {
                        match command {
                            Command::PRIVMSG(ref chan, ref msg) => {
                                let incoming = IncomingMessage::new("IrcAdapter".to_owned(),
                                    Some(server.config().server().to_owned()),
                                    Some(chan.to_owned()), user, msg.to_owned(),
                                    tx_outgoing.clone());

                                println!("{:?}", incoming);

                                tx_incoming.send(incoming)
                                           .ok().expect("chatbot not receiving messages");
                            },
                            _ => ()
                        }
                    }
                }

                // for command in server.iter_cmd() {
                //     // Use of unwrap() on the results of iter_cmd() is discouraged since response
                //     // codes will be received as parsing errors when using this type of iterator.
                //     println!("{:?}", command);
                //     if let Ok(Command::PRIVMSG(chan, msg)) = command {

                //         let incoming = IncomingMessage::new("IrcAdapter".to_owned(),
                //             Some(server.config().server().to_owned()),
                //             Some(chan.to_owned()), user, msg.to_owned(), tx_outgoing.clone());

                //         println!("{:?}", incoming);

                //         tx_incoming.send(incoming).ok().expect("chatbot not receiving messages");
                //     }
                // }
            }).ok().expect("failed to create irc listener thread");
        }

        // for message in server.iter() {
        //     let message = message.unwrap(); // We'll just panic if there's an error.
        //     println!("{:?}", message);
        //     if let Some(src_nick) = message.get_source_nickname() {
        //         println!("get_source_nickname: {}", src_nick);
        //     }
        //     if &message.command[..] == "PRIVMSG" {
        //         if let Some(msg) = message.suffix {
        //             if msg.contains("mr_t_bot") {
        //                 server.send_privmsg(&message.args[0], "Hi!").unwrap();
        //             }
        //         }
        //     }
        // }

    }
}
<commit_msg>Remove some dead commented code from irc.rs<commit_after>extern crate irc;

use std::sync::Mutex;
use std::sync::Arc;
use std::thread;

/// Reexport the irc crate server config for now. Example programs can just grab it from here rather
/// than know the irc crate internals.
pub use irc::client::data::Config;

use irc::client::data::Command;
use irc::client::data::message::ToMessage;
use irc::client::server::IrcServer;
use irc::client::server::Server;
use irc::client::server::utils::ServerExt;

use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;

use chatbot::Chatbot;
use adapter::ChatAdapter;
use message::IncomingMessage;

/// Connect your bot to IRC with the IrcAdapter
pub struct IrcAdapter {
    config: Config
}

impl IrcAdapter {
    pub fn new(config: Config) -> IrcAdapter {
        IrcAdapter {
            config: config
        }
    }
}

impl ChatAdapter for IrcAdapter {
    fn get_name(&self) -> &str {
        "IrcAdapter"
    }

    fn process_events(&self, bot: &Chatbot, tx_incoming: Sender<IncomingMessage>) {
        let server = Arc::new(IrcServer::from_config(self.config.clone()).unwrap());
        server.identify().unwrap();

        let (tx_outgoing, rx_outgoing) = channel();
        let name = bot.get_name().to_owned();

        {
            let server = server.clone();
            thread::Builder::new().name("IrcAdapter lisener".to_owned()).spawn(move || {

                for message in server.iter() {
                    if message.is_err() {
                        continue;
                    }

                    let msg = message.unwrap();

                    let user = msg.get_source_nickname().map(|user| user.to_owned());
                    if let Ok(command) = Command::from_message(&msg) {
                        match command {
                            Command::PRIVMSG(ref chan, ref msg) => {
                                let incoming = IncomingMessage::new("IrcAdapter".to_owned(),
                                    Some(server.config().server().to_owned()),
                                    Some(chan.to_owned()), user, msg.to_owned(),
                                    tx_outgoing.clone());

                                println!("{:?}", incoming);

                                tx_incoming.send(incoming)
                                           .ok().expect("chatbot not receiving messages");
                            },
                            _ => ()
                        }
                    }
                }
            }).ok().expect("failed to create irc listener thread");
        }
    }
}
<|endoftext|>


<commit_before>#![doc="Defines some operators.
"]

// std imports
use std::ops::Div;

/// A type for which computing the reciprocal is supported.
/// Supported types include f32, f64, etc..
pub trait Recip {
    /// The resulting type after computing 1 / x.
    type Output = Self;

    /// The method for the computing 1 / x.
    fn recip(self) -> Self::Output;
}

impl Recip for f32 {
    type Output = Self;
    #[inline]
    fn recip(self) -> f32{
        1.0 / self
    }
}

impl Recip for f64 {
    type Output = Self;
    #[inline]
    fn recip(self) -> f64{
        1.0 / self
    }
}

/// Marker interface for restricting division to only those types which
/// support exact division
pub trait Division : Div
{

}

impl Division for f32 {}
impl Division for f64 {}
<commit_msg>Add feature to make rustc on CI happy (mine wasn't complaining)<commit_after>#![feature(associated_type_defaults)]
#![doc="Defines some operators.
"]

// std imports
use std::ops::Div;

/// A type for which computing the reciprocal is supported.
/// Supported types include f32, f64, etc..
pub trait Recip {
    /// The resulting type after computing 1 / x.
    type Output = Self;

    /// The method for the computing 1 / x.
    fn recip(self) -> Self::Output;
}

impl Recip for f32 {
    type Output = Self;
    #[inline]
    fn recip(self) -> f32{
        1.0 / self
    }
}

impl Recip for f64 {
    type Output = Self;
    #[inline]
    fn recip(self) -> f64{
        1.0 / self
    }
}

/// Marker interface for restricting division to only those types which
/// support exact division
pub trait Division : Div
{

}

impl Division for f32 {}
impl Division for f64 {}
<|endoftext|>


<commit_before>#![cfg(feature = "serde-serialize")]

use na::{
    DMatrix, Isometry3, IsometryMatrix3, Matrix3x4, Point3, Quaternion, Rotation3, Similarity3,
    SimilarityMatrix3, Translation3, Unit,
};
use rand;
use serde_json;

macro_rules! test_serde(
    ($($test: ident, $ty: ident);* $(;)*) => {$(
        #[test]
        fn $test() {
            let v: $ty<f32> = rand::random();
            let serialized = serde_json::to_string(&v).unwrap();
            assert_eq!(v, serde_json::from_str(&serialized).unwrap());
        }
    )*}
);

#[test]
fn serde_dmatrix() {
    let v: DMatrix<f32> = DMatrix::new_random(3, 4);
    let serialized = serde_json::to_string(&v).unwrap();
    assert_eq!(v, serde_json::from_str(&serialized).unwrap());
}

test_serde!(
    serde_matrix3x4,          Matrix3x4;
    serde_point3,             Point3;
    serde_translation3,       Translation3;
    serde_rotation3,          Rotation3;
    serde_isometry3,          Isometry3;
    serde_isometry_matrix3,   IsometryMatrix3;
    serde_similarity3,        Similarity3;
    serde_similarity_matrix3, SimilarityMatrix3;
    serde_quaternion,         Quaternion;
);

#[test]
fn serde_flat() {
    // The actual storage is hidden behind three layers of wrapper types that shouldn't appear in serialized form.
    let v = Unit::new_normalize(Quaternion::new(0., 0., 0., 1.));
    let serialized = serde_json::to_string(&v).unwrap();
    assert_eq!(serialized, "[0.0,0.0,1.0,0.0]");
}
<commit_msg>Add tests for serialization of 2D transformations.<commit_after>#![cfg(feature = "serde-serialize")]

use na::{
    DMatrix, Isometry3, IsometryMatrix3, Matrix3x4, Point3, Quaternion, Rotation3, Similarity3,
    SimilarityMatrix3, Translation3, Unit, Point2, Translation2, Rotation2, Isometry2, IsometryMatrix2,
    Similarity2, SimilarityMatrix2,
};
use rand;
use serde_json;

macro_rules! test_serde(
    ($($test: ident, $ty: ident);* $(;)*) => {$(
        #[test]
        fn $test() {
            let v: $ty<f32> = rand::random();
            let serialized = serde_json::to_string(&v).unwrap();
            assert_eq!(v, serde_json::from_str(&serialized).unwrap());
        }
    )*}
);

#[test]
fn serde_dmatrix() {
    let v: DMatrix<f32> = DMatrix::new_random(3, 4);
    let serialized = serde_json::to_string(&v).unwrap();
    assert_eq!(v, serde_json::from_str(&serialized).unwrap());
}

test_serde!(
    serde_matrix3x4,          Matrix3x4;
    serde_point3,             Point3;
    serde_translation3,       Translation3;
    serde_rotation3,          Rotation3;
    serde_isometry3,          Isometry3;
    serde_isometry_matrix3,   IsometryMatrix3;
    serde_similarity3,        Similarity3;
    serde_similarity_matrix3, SimilarityMatrix3;
    serde_quaternion,         Quaternion;
    serde_point2,             Point2;
    serde_translation2,       Translation2;
    serde_rotation2,          Rotation2;
    serde_isometry2,          Isometry2;
    serde_isometry_matrix2,   IsometryMatrix2;
    serde_similarity2,        Similarity2;
    serde_similarity_matrix2, SimilarityMatrix2;
);

#[test]
fn serde_flat() {
    // The actual storage is hidden behind three layers of wrapper types that shouldn't appear in serialized form.
    let v = Unit::new_normalize(Quaternion::new(0., 0., 0., 1.));
    let serialized = serde_json::to_string(&v).unwrap();
    assert_eq!(serialized, "[0.0,0.0,1.0,0.0]");
}
<|endoftext|>


<commit_before>use std::net::SocketAddr;

use crate::{
    base::{
        ctx::{ctxs, Ctx},
        handler::{default_handler, BoxedHandler},
        http,
        middleware::MiddleWares,
        Request, Response,
    },
    config::{Config, Route},
    handlers::{fs_handler, method_maybe_proxy, proxy_handler},
    middlewares::{auth::Authenticator, logger::Logger, path::PathNormalizer},
    service::GlobalState,
};

pub struct Router {
    global_middlewares: MiddleWares,
    routes: Vec<(Route, MiddleWares, BoxedHandler)>,
    notfound: BoxedHandler,
    proxy: Option<(Route, MiddleWares, BoxedHandler)>,
}

impl Router {
    pub fn new(config: &Config) -> Self {
        let mut routes = config
            .routes
            .values()
            .map(|r| {
                let mut r = r.clone();
                r.urlcs = r.url.split('/').filter(|c| !c.is_empty()).count();

                let mut middlewares = MiddleWares::new();
                if let Some(auth) = &config.auth {
                    if r.authorized {
                        let authenticator = Authenticator::new(auth.clone());
                        middlewares.push(authenticator);
                    }
                }

                (r, middlewares, fs_handler())
            })
            .collect::<Vec<(Route, _, _)>>();

        routes.sort_by(|a, b| a.0.urlcs.cmp(&b.0.urlcs));

        let mut global_middlewares = MiddleWares::with_capacity(2);
        global_middlewares.push(Logger);
        global_middlewares.push(PathNormalizer);

        Self {
            routes,
            global_middlewares,
            notfound: default_handler(),
            proxy: config.proxy.as_ref().map(|route| {
                (
                    route.clone(),
                    {
                        let mut middlewares = MiddleWares::new();
                        if let Some(auth) = &config.auth {
                            if route.authorized {
                                let authenticator = Authenticator::new(auth.clone());
                                middlewares.push(authenticator);
                            }
                        }

                        middlewares
                    },
                    proxy_handler(&route.path),
                )
            }),
        }
    }

    pub async fn call(addr: SocketAddr, req: Request, state: GlobalState) -> Result<Response, http::Error> {
        let this = state.router();

        let mut ctx = Ctx::with_capacity(ctxs::CAPACITY);
        ctx.insert(state);

        for idx in 0..this.global_middlewares.len() {
            if let Err(resp) = (this.global_middlewares[idx]).before(&req, &addr, &mut ctx) {
                // take global_middlewares return ok
                for gm in this.global_middlewares.as_ref()[0..idx].iter().rev() {
                    gm.after(&resp, &addr, &mut ctx);
                }

                return Ok(resp);
            }
        }

        let reqpath = ctx.get::<ctxs::ReqPath>().unwrap();
        let matched = if method_maybe_proxy(&req).is_some() {
            this.proxy.as_ref()
        } else {
            this.routes.iter().find(|&(route, _, _)| {
                reqpath.starts_with(&route.url)
                    && (reqpath.ends_with('/')
                        || reqpath.len() == route.url.len()
                        || reqpath.as_bytes()[route.url.len() - 1] == b'/')
            })
        };

        debug!(
            "matched: {} -> {:?}",
            reqpath,
            matched.as_ref().map(|m| m.0.url.as_str()) // .unwrap_or("")
        );

        let resp = if let Some((route, middlewares, handler)) = matched {
            ctx.insert(route);
            // assert_eq!(route, *ctx.get::<ctx::Route>().unwrap());

            let mut resp = None;
            for idx in 0..middlewares.len() {
                if let Err(resp_) = (middlewares[idx]).before(&req, &addr, &mut ctx) {
                    // take middlewares return ok
                    for lm in middlewares.as_ref()[0..idx].iter().rev() {
                        lm.after(&resp_, &addr, &mut ctx);
                    }
                    resp = Some(resp_);
                }
            }

            let resp = if resp.is_none() {
                (*handler)(req, &addr, &mut ctx).await?
            } else {
                resp.unwrap()
            };

            for lm in middlewares.as_ref().iter().rev() {
                lm.after(&resp, &addr, &mut ctx);
            }

            resp
        } else {
            (this.notfound)(req, &addr, &mut ctx).await?
        };

        for gm in this.global_middlewares.as_ref().iter().rev() {
            gm.after(&resp, &addr, &mut ctx);
        }

        Ok(resp)
    }
}
<commit_msg>fix router for sharing many paths<commit_after>use std::net::SocketAddr;

use crate::{
    base::{
        ctx::{ctxs, Ctx},
        handler::{default_handler, BoxedHandler},
        http,
        middleware::MiddleWares,
        Request, Response,
    },
    config::{Config, Route},
    handlers::{fs_handler, method_maybe_proxy, proxy_handler},
    middlewares::{auth::Authenticator, logger::Logger, path::PathNormalizer},
    service::GlobalState,
};

pub struct Router {
    global_middlewares: MiddleWares,
    routes: Vec<(Route, MiddleWares, BoxedHandler)>,
    notfound: BoxedHandler,
    proxy: Option<(Route, MiddleWares, BoxedHandler)>,
}

impl Router {
    pub fn new(config: &Config) -> Self {
        let mut routes = config
            .routes
            .values()
            .map(|r| {
                let mut r = r.clone();
                r.urlcs = r.url.split('/').filter(|c| !c.is_empty()).count();

                let mut middlewares = MiddleWares::new();
                if let Some(auth) = &config.auth {
                    if r.authorized {
                        let authenticator = Authenticator::new(auth.clone());
                        middlewares.push(authenticator);
                    }
                }

                (r, middlewares, fs_handler())
            })
            .collect::<Vec<(Route, _, _)>>();

        routes.sort_by(|a, b| b.0.urlcs.cmp(&a.0.urlcs));

        let mut global_middlewares = MiddleWares::with_capacity(2);
        global_middlewares.push(Logger);
        global_middlewares.push(PathNormalizer);

        Self {
            routes,
            global_middlewares,
            notfound: default_handler(),
            proxy: config.proxy.as_ref().map(|route| {
                (
                    route.clone(),
                    {
                        let mut middlewares = MiddleWares::new();
                        if let Some(auth) = &config.auth {
                            if route.authorized {
                                let authenticator = Authenticator::new(auth.clone());
                                middlewares.push(authenticator);
                            }
                        }

                        middlewares
                    },
                    proxy_handler(&route.path),
                )
            }),
        }
    }

    pub async fn call(addr: SocketAddr, req: Request, state: GlobalState) -> Result<Response, http::Error> {
        let this = state.router();

        let mut ctx = Ctx::with_capacity(ctxs::CAPACITY);
        ctx.insert(state);

        for idx in 0..this.global_middlewares.len() {
            if let Err(resp) = (this.global_middlewares[idx]).before(&req, &addr, &mut ctx) {
                // take global_middlewares return ok
                for gm in this.global_middlewares.as_ref()[0..idx].iter().rev() {
                    gm.after(&resp, &addr, &mut ctx);
                }

                return Ok(resp);
            }
        }

        let reqpath = ctx.get::<ctxs::ReqPath>().unwrap();
        let matched = if method_maybe_proxy(&req).is_some() {
            this.proxy.as_ref()
        } else {
            this.routes.iter().find(|&(route, _, _)| {
                reqpath.starts_with(&route.url) && (route.url.ends_with('/') || reqpath.len() == route.url.len())
                    || reqpath.trim_end_matches("/") == route.url.trim_end_matches("/")
            })
        };

        debug!(
            "matched: {} -> {:?}",
            reqpath,
            matched.as_ref().map(|m| m.0.url.as_str()) // .unwrap_or("")
        );

        let resp = if let Some((route, middlewares, handler)) = matched {
            ctx.insert(route);
            // assert_eq!(route, *ctx.get::<ctx::Route>().unwrap());

            let mut resp = None;
            for idx in 0..middlewares.len() {
                if let Err(resp_) = (middlewares[idx]).before(&req, &addr, &mut ctx) {
                    // take middlewares return ok
                    for lm in middlewares.as_ref()[0..idx].iter().rev() {
                        lm.after(&resp_, &addr, &mut ctx);
                    }
                    resp = Some(resp_);
                }
            }

            let resp = if resp.is_none() {
                (*handler)(req, &addr, &mut ctx).await?
            } else {
                resp.unwrap()
            };

            for lm in middlewares.as_ref().iter().rev() {
                lm.after(&resp, &addr, &mut ctx);
            }

            resp
        } else {
            (this.notfound)(req, &addr, &mut ctx).await?
        };

        for gm in this.global_middlewares.as_ref().iter().rev() {
            gm.after(&resp, &addr, &mut ctx);
        }

        Ok(resp)
    }
}
<|endoftext|>


<commit_before>use indoc::indoc;
use serde_derive::Deserialize;
use std::fmt::Debug;

fn test_error<T>(yaml: &str, expected: &str)
where
    T: serde::de::DeserializeOwned + Debug,
{
    let result = serde_yaml::from_str::<T>(yaml);
    assert_eq!(expected, format!("{}", result.unwrap_err()));
}

#[test]
fn test_incorrect_type() {
    let yaml = indoc! {"
        ---
        str
    "};
    let expected = "invalid type: string \"str\", expected i16 at line 2 column 1";
    test_error::<i16>(yaml, expected);
}

#[test]
fn test_incorrect_nested_type() {
    #[derive(Deserialize, Debug)]
    struct A {
        #[allow(dead_code)]
        b: Vec<B>,
    }
    #[derive(Deserialize, Debug)]
    enum B {
        C(C),
    }
    #[derive(Deserialize, Debug)]
    struct C {
        #[allow(dead_code)]
        d: bool,
    }
    let yaml = indoc! {"
        ---
        b:
          - C:
              d: fase
    "};
    let expected =
        "b[0].C.d: invalid type: string \"fase\", expected a boolean at line 4 column 10";
    test_error::<A>(yaml, expected);
}

#[test]
fn test_empty() {
    let expected = "EOF while parsing a value";
    test_error::<String>("", expected);
}

#[test]
fn test_missing_field() {
    #[derive(Deserialize, Debug)]
    struct Basic {
        #[allow(dead_code)]
        v: bool,
        #[allow(dead_code)]
        w: bool,
    }
    let yaml = indoc! {"
        ---
        v: true
    "};
    let expected = "missing field `w` at line 2 column 2";
    test_error::<Basic>(yaml, expected);
}

#[test]
fn test_unknown_anchor() {
    let yaml = indoc! {"
        ---
        *some
    "};
    let expected = "while parsing node, found unknown anchor at line 2 column 1";
    test_error::<String>(yaml, expected);
}

#[test]
fn test_ignored_unknown_anchor() {
    #[derive(Deserialize, Debug)]
    struct Wrapper {
        #[allow(dead_code)]
        c: (),
    }
    let yaml = indoc! {"
        ---
        b: [*a]
        c: ~
    "};
    let expected = "while parsing node, found unknown anchor at line 2 column 5";
    test_error::<Wrapper>(yaml, expected);
}

#[test]
fn test_two_documents() {
    let yaml = indoc! {"
        ---
        0
        ---
        1
    "};
    let expected = "deserializing from YAML containing more than one document is not supported";
    test_error::<usize>(yaml, expected);
}

#[test]
fn test_variant_map_wrong_size() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        ---
        "V": 16
        "other": 32
    "#};
    let expected = "invalid length 2, expected map containing 1 entry";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_variant_not_a_map() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        ---
        - "V"
    "#};
    let expected = "invalid type: sequence, expected string or singleton map at line 2 column 1";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_variant_not_string() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(bool),
    }
    let yaml = indoc! {r#"
        ---
        {}: true
    "#};
    let expected = "invalid type: map, expected variant of enum `E` at line 2 column 1";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_bad_bool() {
    let yaml = indoc! {"
        ---
        !!bool str
    "};
    let expected = "invalid value: string \"str\", expected a boolean at line 2 column 8";
    test_error::<bool>(yaml, expected);
}

#[test]
fn test_bad_int() {
    let yaml = indoc! {"
        ---
        !!int str
    "};
    let expected = "invalid value: string \"str\", expected an integer at line 2 column 7";
    test_error::<i64>(yaml, expected);
}

#[test]
fn test_bad_float() {
    let yaml = indoc! {"
        ---
        !!float str
    "};
    let expected = "invalid value: string \"str\", expected a float at line 2 column 9";
    test_error::<f64>(yaml, expected);
}

#[test]
fn test_bad_null() {
    let yaml = indoc! {"
        ---
        !!null str
    "};
    let expected = "invalid value: string \"str\", expected null at line 2 column 8";
    test_error::<()>(yaml, expected);
}

#[test]
fn test_short_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0]
    "};
    let expected = "invalid length 2, expected a tuple of size 3 at line 2 column 1";
    test_error::<(u8, u8, u8)>(yaml, expected);
}

#[test]
fn test_long_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0, 0]
    "};
    let expected = "invalid length 3, expected sequence of 2 elements at line 2 column 1";
    test_error::<(u8, u8)>(yaml, expected);
}

#[test]
fn test_no_location() {
    let invalid_utf8: Result<serde_yaml::Value, serde_yaml::Error> =
        serde_yaml::from_slice(b"\x80\xae");

    let utf8_location = invalid_utf8.unwrap_err().location();

    assert!(utf8_location.is_none());
}

#[test]
fn test_invalid_scalar_type() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: [(); 1],
    }

    let yaml = "x:\n";
    let expected = "x: invalid type: unit value, expected an array of length 1 at line 2 column 1";
    test_error::<S>(yaml, expected);
}

#[test]
fn test_infinite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "&a {'x': *a}";
    let expected = "recursion limit exceeded at line 1 column 4";
    test_error::<S>(yaml, expected);
}

#[test]
fn test_infinite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "&a [*a]";
    let expected = "recursion limit exceeded at line 1 column 4";
    test_error::<S>(yaml, expected);
}

#[test]
fn test_finite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "{'x':".repeat(1_000) + &"}".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 1276";
    test_error::<S>(&yaml, expected);
}

#[test]
fn test_finite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "[".repeat(1_000) + &"]".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 256";
    test_error::<S>(&yaml, expected);
}
<commit_msg>Disable slow recursion tests on miri<commit_after>use indoc::indoc;
use serde_derive::Deserialize;
use std::fmt::Debug;

fn test_error<T>(yaml: &str, expected: &str)
where
    T: serde::de::DeserializeOwned + Debug,
{
    let result = serde_yaml::from_str::<T>(yaml);
    assert_eq!(expected, format!("{}", result.unwrap_err()));
}

#[test]
fn test_incorrect_type() {
    let yaml = indoc! {"
        ---
        str
    "};
    let expected = "invalid type: string \"str\", expected i16 at line 2 column 1";
    test_error::<i16>(yaml, expected);
}

#[test]
fn test_incorrect_nested_type() {
    #[derive(Deserialize, Debug)]
    struct A {
        #[allow(dead_code)]
        b: Vec<B>,
    }
    #[derive(Deserialize, Debug)]
    enum B {
        C(C),
    }
    #[derive(Deserialize, Debug)]
    struct C {
        #[allow(dead_code)]
        d: bool,
    }
    let yaml = indoc! {"
        ---
        b:
          - C:
              d: fase
    "};
    let expected =
        "b[0].C.d: invalid type: string \"fase\", expected a boolean at line 4 column 10";
    test_error::<A>(yaml, expected);
}

#[test]
fn test_empty() {
    let expected = "EOF while parsing a value";
    test_error::<String>("", expected);
}

#[test]
fn test_missing_field() {
    #[derive(Deserialize, Debug)]
    struct Basic {
        #[allow(dead_code)]
        v: bool,
        #[allow(dead_code)]
        w: bool,
    }
    let yaml = indoc! {"
        ---
        v: true
    "};
    let expected = "missing field `w` at line 2 column 2";
    test_error::<Basic>(yaml, expected);
}

#[test]
fn test_unknown_anchor() {
    let yaml = indoc! {"
        ---
        *some
    "};
    let expected = "while parsing node, found unknown anchor at line 2 column 1";
    test_error::<String>(yaml, expected);
}

#[test]
fn test_ignored_unknown_anchor() {
    #[derive(Deserialize, Debug)]
    struct Wrapper {
        #[allow(dead_code)]
        c: (),
    }
    let yaml = indoc! {"
        ---
        b: [*a]
        c: ~
    "};
    let expected = "while parsing node, found unknown anchor at line 2 column 5";
    test_error::<Wrapper>(yaml, expected);
}

#[test]
fn test_two_documents() {
    let yaml = indoc! {"
        ---
        0
        ---
        1
    "};
    let expected = "deserializing from YAML containing more than one document is not supported";
    test_error::<usize>(yaml, expected);
}

#[test]
fn test_variant_map_wrong_size() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        ---
        "V": 16
        "other": 32
    "#};
    let expected = "invalid length 2, expected map containing 1 entry";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_variant_not_a_map() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(usize),
    }
    let yaml = indoc! {r#"
        ---
        - "V"
    "#};
    let expected = "invalid type: sequence, expected string or singleton map at line 2 column 1";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_variant_not_string() {
    #[derive(Deserialize, Debug)]
    enum E {
        V(bool),
    }
    let yaml = indoc! {r#"
        ---
        {}: true
    "#};
    let expected = "invalid type: map, expected variant of enum `E` at line 2 column 1";
    test_error::<E>(yaml, expected);
}

#[test]
fn test_bad_bool() {
    let yaml = indoc! {"
        ---
        !!bool str
    "};
    let expected = "invalid value: string \"str\", expected a boolean at line 2 column 8";
    test_error::<bool>(yaml, expected);
}

#[test]
fn test_bad_int() {
    let yaml = indoc! {"
        ---
        !!int str
    "};
    let expected = "invalid value: string \"str\", expected an integer at line 2 column 7";
    test_error::<i64>(yaml, expected);
}

#[test]
fn test_bad_float() {
    let yaml = indoc! {"
        ---
        !!float str
    "};
    let expected = "invalid value: string \"str\", expected a float at line 2 column 9";
    test_error::<f64>(yaml, expected);
}

#[test]
fn test_bad_null() {
    let yaml = indoc! {"
        ---
        !!null str
    "};
    let expected = "invalid value: string \"str\", expected null at line 2 column 8";
    test_error::<()>(yaml, expected);
}

#[test]
fn test_short_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0]
    "};
    let expected = "invalid length 2, expected a tuple of size 3 at line 2 column 1";
    test_error::<(u8, u8, u8)>(yaml, expected);
}

#[test]
fn test_long_tuple() {
    let yaml = indoc! {"
        ---
        [0, 0, 0]
    "};
    let expected = "invalid length 3, expected sequence of 2 elements at line 2 column 1";
    test_error::<(u8, u8)>(yaml, expected);
}

#[test]
fn test_no_location() {
    let invalid_utf8: Result<serde_yaml::Value, serde_yaml::Error> =
        serde_yaml::from_slice(b"\x80\xae");

    let utf8_location = invalid_utf8.unwrap_err().location();

    assert!(utf8_location.is_none());
}

#[test]
fn test_invalid_scalar_type() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: [(); 1],
    }

    let yaml = "x:\n";
    let expected = "x: invalid type: unit value, expected an array of length 1 at line 2 column 1";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "&a {'x': *a}";
    let expected = "recursion limit exceeded at line 1 column 4";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_infinite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "&a [*a]";
    let expected = "recursion limit exceeded at line 1 column 4";
    test_error::<S>(yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_finite_recursion_objects() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "{'x':".repeat(1_000) + &"}".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 1276";
    test_error::<S>(&yaml, expected);
}

#[cfg(not(miri))]
#[test]
fn test_finite_recursion_arrays() {
    #[derive(Deserialize, Debug)]
    struct S {
        #[allow(dead_code)]
        x: Option<Box<S>>,
    }

    let yaml = "[".repeat(1_000) + &"]".repeat(1_000);
    let expected = "recursion limit exceeded at line 1 column 256";
    test_error::<S>(&yaml, expected);
}
<|endoftext|>


<commit_before>//! Handles dynamic library loading for proc macro

use std::{
    fs::File,
    io,
    path::{Path, PathBuf},
};

use libloading::Library;
use memmap2::Mmap;
use object::Object;
use proc_macro_api::ProcMacroKind;

use crate::{proc_macro::bridge, rustc_server::TokenStream};

const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";

fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
    io::Error::new(io::ErrorKind::InvalidData, e)
}

fn is_derive_registrar_symbol(symbol: &str) -> bool {
    symbol.contains(NEW_REGISTRAR_SYMBOL)
}

fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
    let file = File::open(file)?;
    let buffer = unsafe { Mmap::map(&file)? };

    Ok(object::File::parse(&*buffer)
        .map_err(invalid_data_err)?
        .exports()
        .map_err(invalid_data_err)?
        .into_iter()
        .map(|export| export.name())
        .filter_map(|sym| String::from_utf8(sym.into()).ok())
        .find(|sym| is_derive_registrar_symbol(sym))
        .map(|sym| {
            // From MacOS docs:
            // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
            // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
            // prepended with an underscore.
            if cfg!(target_os = "macos") && sym.starts_with('_') {
                sym[1..].to_owned()
            } else {
                sym
            }
        }))
}

/// Loads dynamic library in platform dependent manner.
///
/// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
/// and [here](https://github.com/rust-lang/rust/issues/60593).
///
/// Usage of RTLD_DEEPBIND
/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
///
/// It seems that on Windows that behaviour is default, so we do nothing in that case.
#[cfg(windows)]
fn load_library(file: &Path) -> Result<Library, libloading::Error> {
    unsafe { Library::new(file) }
}

#[cfg(unix)]
fn load_library(file: &Path) -> Result<Library, libloading::Error> {
    use libloading::os::unix::Library as UnixLibrary;
    use std::os::raw::c_int;

    const RTLD_NOW: c_int = 0x00002;
    const RTLD_DEEPBIND: c_int = 0x00008;

    unsafe { UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into()) }
}

struct ProcMacroLibraryLibloading {
    // Hold the dylib to prevent it from unloading
    _lib: Library,
    exported_macros: Vec<bridge::client::ProcMacro>,
}

impl ProcMacroLibraryLibloading {
    fn open(file: &Path) -> io::Result<Self> {
        let symbol_name = find_registrar_symbol(file)?.ok_or_else(|| {
            invalid_data_err(format!("Cannot find registrar symbol in file {}", file.display()))
        })?;

        let lib = load_library(file).map_err(invalid_data_err)?;
        let exported_macros = {
            let macros: libloading::Symbol<&&[bridge::client::ProcMacro]> =
                unsafe { lib.get(symbol_name.as_bytes()) }.map_err(invalid_data_err)?;
            macros.to_vec()
        };

        Ok(ProcMacroLibraryLibloading { _lib: lib, exported_macros })
    }
}

pub struct Expander {
    inner: ProcMacroLibraryLibloading,
}

impl Expander {
    pub fn new(lib: &Path) -> io::Result<Expander> {
        // Some libraries for dynamic loading require canonicalized path even when it is
        // already absolute
        let lib = lib.canonicalize()?;

        let lib = ensure_file_with_lock_free_access(&lib)?;

        let library = ProcMacroLibraryLibloading::open(&lib)?;

        Ok(Expander { inner: library })
    }

    pub fn expand(
        &self,
        macro_name: &str,
        macro_body: &tt::Subtree,
        attributes: Option<&tt::Subtree>,
    ) -> Result<tt::Subtree, bridge::PanicMessage> {
        let parsed_body = TokenStream::with_subtree(macro_body.clone());

        let parsed_attributes = attributes
            .map_or(crate::rustc_server::TokenStream::new(), |attr| {
                TokenStream::with_subtree(attr.clone())
            });

        for proc_macro in &self.inner.exported_macros {
            match proc_macro {
                bridge::client::ProcMacro::CustomDerive { trait_name, client, .. }
                    if *trait_name == macro_name =>
                {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_body,
                        false,
                    );
                    return res.map(|it| it.into_subtree());
                }
                bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_body,
                        false,
                    );
                    return res.map(|it| it.into_subtree());
                }
                bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_attributes,
                        parsed_body,
                        false,
                    );
                    return res.map(|it| it.into_subtree());
                }
                _ => continue,
            }
        }

        Err(bridge::PanicMessage::String("Nothing to expand".to_string()))
    }

    pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
        self.inner
            .exported_macros
            .iter()
            .map(|proc_macro| match proc_macro {
                bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
                    (trait_name.to_string(), ProcMacroKind::CustomDerive)
                }
                bridge::client::ProcMacro::Bang { name, .. } => {
                    (name.to_string(), ProcMacroKind::FuncLike)
                }
                bridge::client::ProcMacro::Attr { name, .. } => {
                    (name.to_string(), ProcMacroKind::Attr)
                }
            })
            .collect()
    }
}

/// Copy the dylib to temp directory to prevent locking in Windows
#[cfg(windows)]
fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
    use std::{ffi::OsString, time::SystemTime};

    let mut to = std::env::temp_dir();

    let file_name = path.file_name().ok_or_else(|| {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("File path is invalid: {}", path.display()),
        )
    })?;

    // generate a time deps unique number
    let t = SystemTime::now().duration_since(std::time::UNIX_EPOCH).expect("Time went backwards");

    let mut unique_name = OsString::from(t.as_millis().to_string());
    unique_name.push(file_name);

    to.push(unique_name);
    std::fs::copy(path, &to).unwrap();
    Ok(to)
}

#[cfg(unix)]
fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
    Ok(path.to_path_buf())
}
<commit_msg>Try to fix unique file names on Windows<commit_after>//! Handles dynamic library loading for proc macro

use std::{
    fs::File,
    io,
    path::{Path, PathBuf},
};

use libloading::Library;
use memmap2::Mmap;
use object::Object;
use proc_macro_api::ProcMacroKind;

use crate::{proc_macro::bridge, rustc_server::TokenStream};

const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";

fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
    io::Error::new(io::ErrorKind::InvalidData, e)
}

fn is_derive_registrar_symbol(symbol: &str) -> bool {
    symbol.contains(NEW_REGISTRAR_SYMBOL)
}

fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
    let file = File::open(file)?;
    let buffer = unsafe { Mmap::map(&file)? };

    Ok(object::File::parse(&*buffer)
        .map_err(invalid_data_err)?
        .exports()
        .map_err(invalid_data_err)?
        .into_iter()
        .map(|export| export.name())
        .filter_map(|sym| String::from_utf8(sym.into()).ok())
        .find(|sym| is_derive_registrar_symbol(sym))
        .map(|sym| {
            // From MacOS docs:
            // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
            // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
            // prepended with an underscore.
            if cfg!(target_os = "macos") && sym.starts_with('_') {
                sym[1..].to_owned()
            } else {
                sym
            }
        }))
}

/// Loads dynamic library in platform dependent manner.
///
/// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
/// and [here](https://github.com/rust-lang/rust/issues/60593).
///
/// Usage of RTLD_DEEPBIND
/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
///
/// It seems that on Windows that behaviour is default, so we do nothing in that case.
#[cfg(windows)]
fn load_library(file: &Path) -> Result<Library, libloading::Error> {
    unsafe { Library::new(file) }
}

#[cfg(unix)]
fn load_library(file: &Path) -> Result<Library, libloading::Error> {
    use libloading::os::unix::Library as UnixLibrary;
    use std::os::raw::c_int;

    const RTLD_NOW: c_int = 0x00002;
    const RTLD_DEEPBIND: c_int = 0x00008;

    unsafe { UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into()) }
}

struct ProcMacroLibraryLibloading {
    // Hold the dylib to prevent it from unloading
    _lib: Library,
    exported_macros: Vec<bridge::client::ProcMacro>,
}

impl ProcMacroLibraryLibloading {
    fn open(file: &Path) -> io::Result<Self> {
        let symbol_name = find_registrar_symbol(file)?.ok_or_else(|| {
            invalid_data_err(format!("Cannot find registrar symbol in file {}", file.display()))
        })?;

        let lib = load_library(file).map_err(invalid_data_err)?;
        let exported_macros = {
            let macros: libloading::Symbol<&&[bridge::client::ProcMacro]> =
                unsafe { lib.get(symbol_name.as_bytes()) }.map_err(invalid_data_err)?;
            macros.to_vec()
        };

        Ok(ProcMacroLibraryLibloading { _lib: lib, exported_macros })
    }
}

pub struct Expander {
    inner: ProcMacroLibraryLibloading,
}

impl Expander {
    pub fn new(lib: &Path) -> io::Result<Expander> {
        // Some libraries for dynamic loading require canonicalized path even when it is
        // already absolute
        let lib = lib.canonicalize()?;

        let lib = ensure_file_with_lock_free_access(&lib)?;

        let library = ProcMacroLibraryLibloading::open(&lib)?;

        Ok(Expander { inner: library })
    }

    pub fn expand(
        &self,
        macro_name: &str,
        macro_body: &tt::Subtree,
        attributes: Option<&tt::Subtree>,
    ) -> Result<tt::Subtree, bridge::PanicMessage> {
        let parsed_body = TokenStream::with_subtree(macro_body.clone());

        let parsed_attributes = attributes
            .map_or(crate::rustc_server::TokenStream::new(), |attr| {
                TokenStream::with_subtree(attr.clone())
            });

        for proc_macro in &self.inner.exported_macros {
            match proc_macro {
                bridge::client::ProcMacro::CustomDerive { trait_name, client, .. }
                    if *trait_name == macro_name =>
                {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_body,
                        false,
                    );
                    return res.map(|it| it.into_subtree());
                }
                bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_body,
                        false,
                    );
                    return res.map(|it| it.into_subtree());
                }
                bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_attributes,
                        parsed_body,
                        false,
                    );
                    return res.map(|it| it.into_subtree());
                }
                _ => continue,
            }
        }

        Err(bridge::PanicMessage::String("Nothing to expand".to_string()))
    }

    pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
        self.inner
            .exported_macros
            .iter()
            .map(|proc_macro| match proc_macro {
                bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
                    (trait_name.to_string(), ProcMacroKind::CustomDerive)
                }
                bridge::client::ProcMacro::Bang { name, .. } => {
                    (name.to_string(), ProcMacroKind::FuncLike)
                }
                bridge::client::ProcMacro::Attr { name, .. } => {
                    (name.to_string(), ProcMacroKind::Attr)
                }
            })
            .collect()
    }
}

/// Copy the dylib to temp directory to prevent locking in Windows
#[cfg(windows)]
fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
    use std::collections::hash_map::RandomState;
    use std::ffi::OsString;
    use std::hash::{BuildHasher, Hasher};

    let mut to = std::env::temp_dir();

    let file_name = path.file_name().ok_or_else(|| {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("File path is invalid: {}", path.display()),
        )
    })?;

    // Generate a unique number by abusing `HashMap`'s hasher.
    // Maybe this will also "inspire" a libs team member to finally put `rand` in libstd.
    let t = RandomState::new().build_hasher().finish();

    let mut unique_name = OsString::from(t.to_string());
    unique_name.push(file_name);

    to.push(unique_name);
    std::fs::copy(path, &to).unwrap();
    Ok(to)
}

#[cfg(unix)]
fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
    Ok(path.to_path_buf())
}
<|endoftext|>