<commit_before>//! Async WebSocket usage.
//!
//! This library is an implementation of WebSocket handshakes and streams. It
//! is based on the crate which implements all required WebSocket protocol
//! logic. So this crate basically just brings tokio support / tokio integration
//! to it.
//!
//! Each WebSocket stream implements the required `Stream` and `Sink` traits,
//! so the socket is just a stream of messages coming in and going out.

#![deny(
    missing_docs,
    unused_must_use,
    unused_mut,
    unused_imports,
    unused_import_braces
)]

pub use tungstenite;

mod compat;
#[cfg(feature = "connect")]
mod connect;
mod handshake;
#[cfg(feature = "stream")]
pub mod stream;

use std::io::{Read, Write};

use compat::{cvt, AllowStd, ContextWaker};
use futures_util::{
    sink::{Sink, SinkExt},
    stream::Stream,
};
use log::*;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite};

use tungstenite::{
    client::IntoClientRequest,
    error::Error as WsError,
    handshake::{
        client::{ClientHandshake, Request, Response},
        server::{Callback, NoCallback},
    },
    protocol::{Message, Role, WebSocket, WebSocketConfig},
    server,
};

#[cfg(feature = "connect")]
pub use connect::{client_async_tls, connect_async};

#[cfg(all(feature = "connect", feature = "tls"))]
pub use connect::MaybeTlsStream;
use tungstenite::protocol::CloseFrame;

/// Creates a WebSocket handshake from a request and a stream.
/// For convenience, the user may call this with a url string, a URL,
/// or a `Request`. Calling with `Request` allows the user to add
/// a WebSocket protocol or other custom headers.
///
/// Internally, this custom creates a handshake representation and returns
/// a future representing the resolution of the WebSocket handshake. The
/// returned future will resolve to either `WebSocketStream<S>` or `Error`
/// depending on whether the handshake is successful.
///
/// This is typically used for clients who have already established, for
/// example, a TCP connection to the remote server.
pub async fn client_async<'a, R, S>(
    request: R,
    stream: S,
) -> Result<(WebSocketStream<S>, Response), WsError>
where
    R: IntoClientRequest + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    client_async_with_config(request, stream, None).await
}

/// The same as `client_async()` but the one can specify a websocket configuration.
/// Please refer to `client_async()` for more details.
pub async fn client_async_with_config<'a, R, S>(
    request: R,
    stream: S,
    config: Option<WebSocketConfig>,
) -> Result<(WebSocketStream<S>, Response), WsError>
where
    R: IntoClientRequest + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let f = handshake::client_handshake(stream, move |allow_std| {
        let request = request.into_client_request()?;
        let cli_handshake = ClientHandshake::start(allow_std, request, config)?;
        cli_handshake.handshake()
    });
    f.await.map_err(|e| {
        WsError::Io(std::io::Error::new(
            std::io::ErrorKind::Other,
            e.to_string(),
        ))
    })
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function will internally call `server::accept` to create a
/// handshake representation and returns a future representing the
/// resolution of the WebSocket handshake. The returned future will resolve
/// to either `WebSocketStream<S>` or `Error` depending if it's successful
/// or not.
///
/// This is typically used after a socket has been accepted from a
/// `TcpListener`. That socket is then passed to this function to perform
/// the server half of the accepting a client's websocket connection.
pub async fn accept_async<S>(stream: S) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
{
    accept_hdr_async(stream, NoCallback).await
}

/// The same as `accept_async()` but the one can specify a websocket configuration.
/// Please refer to `accept_async()` for more details.
pub async fn accept_async_with_config<S>(
    stream: S,
    config: Option<WebSocketConfig>,
) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
{
    accept_hdr_async_with_config(stream, NoCallback, config).await
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function does the same as `accept_async()` but accepts an extra callback
/// for header processing. The callback receives headers of the incoming
/// requests and is able to add extra headers to the reply.
pub async fn accept_hdr_async<S, C>(stream: S, callback: C) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
    C: Callback + Unpin,
{
    accept_hdr_async_with_config(stream, callback, None).await
}

/// The same as `accept_hdr_async()` but the one can specify a websocket configuration.
/// Please refer to `accept_hdr_async()` for more details.
pub async fn accept_hdr_async_with_config<S, C>(
    stream: S,
    callback: C,
    config: Option<WebSocketConfig>,
) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
    C: Callback + Unpin,
{
    let f = handshake::server_handshake(stream, move |allow_std| {
        server::accept_hdr_with_config(allow_std, callback, config)
    });
    f.await.map_err(|e| {
        WsError::Io(std::io::Error::new(
            std::io::ErrorKind::Other,
            e.to_string(),
        ))
    })
}

/// A wrapper around an underlying raw stream which implements the WebSocket
/// protocol.
///
/// A `WebSocketStream<S>` represents a handshake that has been completed
/// successfully and both the server and the client are ready for receiving
/// and sending data. Message from a `WebSocketStream<S>` are accessible
/// through the respective `Stream` and `Sink`. Check more information about
/// them in `futures-rs` crate documentation or have a look on the examples
/// and unit tests for this crate.
#[derive(Debug)]
pub struct WebSocketStream<S> {
    inner: WebSocket<AllowStd<S>>,
}

impl<S> WebSocketStream<S> {
    /// Convert a raw socket into a WebSocketStream without performing a
    /// handshake.
    pub async fn from_raw_socket(stream: S, role: Role, config: Option<WebSocketConfig>) -> Self
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        handshake::without_handshake(stream, move |allow_std| {
            WebSocket::from_raw_socket(allow_std, role, config)
        })
        .await
    }

    /// Convert a raw socket into a WebSocketStream without performing a
    /// handshake.
    pub async fn from_partially_read(
        stream: S,
        part: Vec<u8>,
        role: Role,
        config: Option<WebSocketConfig>,
    ) -> Self
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        handshake::without_handshake(stream, move |allow_std| {
            WebSocket::from_partially_read(allow_std, part, role, config)
        })
        .await
    }

    pub(crate) fn new(ws: WebSocket<AllowStd<S>>) -> Self {
        WebSocketStream { inner: ws }
    }

    fn with_context<F, R>(&mut self, ctx: Option<(ContextWaker, &mut Context<'_>)>, f: F) -> R
    where
        S: Unpin,
        F: FnOnce(&mut WebSocket<AllowStd<S>>) -> R,
        AllowStd<S>: Read + Write,
    {
        trace!("{}:{} WebSocketStream.with_context", file!(), line!());
        if let Some((kind, ctx)) = ctx {
            self.inner.get_mut().set_waker(kind, &ctx.waker());
        }
        f(&mut self.inner)
    }

    /// Returns a shared reference to the inner stream.
    pub fn get_ref(&self) -> &S
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        &self.inner.get_ref().get_ref()
    }

    /// Returns a mutable reference to the inner stream.
    pub fn get_mut(&mut self) -> &mut S
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        self.inner.get_mut().get_mut()
    }

    /// Close the underlying web socket
    pub async fn close(&mut self, msg: Option<CloseFrame<'_>>) -> Result<(), WsError>
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        let msg = msg.map(|msg| msg.into_owned());
        self.send(Message::Close(msg)).await
    }
}

impl<T> Stream for WebSocketStream<T>
where
    T: AsyncRead + AsyncWrite + Unpin,
{
    type Item = Result<Message, WsError>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        trace!("{}:{} Stream.poll_next", file!(), line!());
        match futures_util::ready!(self.with_context(Some((ContextWaker::Read, cx)), |s| {
            trace!(
                "{}:{} Stream.with_context poll_next -> read_message()",
                file!(),
                line!()
            );
            cvt(s.read_message())
        })) {
            Ok(v) => Poll::Ready(Some(Ok(v))),
            Err(WsError::AlreadyClosed) | Err(WsError::ConnectionClosed) => Poll::Ready(None),
            Err(e) => Poll::Ready(Some(Err(e))),
        }
    }
}

impl<T> Sink<Message> for WebSocketStream<T>
where
    T: AsyncRead + AsyncWrite + Unpin,
{
    type Error = WsError;

    fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        (*self).with_context(Some((ContextWaker::Write, cx)), |s| cvt(s.write_pending()))
    }

    fn start_send(mut self: Pin<&mut Self>, item: Message) -> Result<(), Self::Error> {
        match (*self).with_context(None, |s| s.write_message(item)) {
            Ok(()) => Ok(()),
            Err(::tungstenite::Error::Io(ref err))
                if err.kind() == std::io::ErrorKind::WouldBlock =>
            {
                // the message was accepted and queued
                // isn't an error.
                Ok(())
            }
            Err(e) => {
                debug!("websocket start_send error: {}", e);
                Err(e)
            }
        }
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        (*self).with_context(Some((ContextWaker::Write, cx)), |s| cvt(s.write_pending()))
    }

    fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        match (*self).with_context(Some((ContextWaker::Write, cx)), |s| s.close(None)) {
            Ok(()) => Poll::Ready(Ok(())),
            Err(::tungstenite::Error::ConnectionClosed) => Poll::Ready(Ok(())),
            Err(err) => {
                debug!("websocket close error: {}", err);
                Poll::Ready(Err(err))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::compat::AllowStd;
    #[cfg(feature = "connect")]
    use crate::connect::encryption::AutoStream;
    use crate::WebSocketStream;
    use std::io::{Read, Write};
    use tokio::io::{AsyncReadExt, AsyncWriteExt};

    fn is_read<T: Read>() {}
    fn is_write<T: Write>() {}
    fn is_async_read<T: AsyncReadExt>() {}
    fn is_async_write<T: AsyncWriteExt>() {}
    fn is_unpin<T: Unpin>() {}

    #[test]
    fn web_socket_stream_has_traits() {
        is_read::<AllowStd<tokio::net::TcpStream>>();
        is_write::<AllowStd<tokio::net::TcpStream>>();

        #[cfg(feature = "connect")]
        is_async_read::<AutoStream<tokio::net::TcpStream>>();
        #[cfg(feature = "connect")]
        is_async_write::<AutoStream<tokio::net::TcpStream>>();

        is_unpin::<WebSocketStream<tokio::net::TcpStream>>();
        #[cfg(feature = "connect")]
        is_unpin::<WebSocketStream<AutoStream<tokio::net::TcpStream>>>();
    }
}
<commit_msg>Forward handshake errors directly instead of wrapping them in a Other IO error<commit_after>//! Async WebSocket usage.
//!
//! This library is an implementation of WebSocket handshakes and streams. It
//! is based on the crate which implements all required WebSocket protocol
//! logic. So this crate basically just brings tokio support / tokio integration
//! to it.
//!
//! Each WebSocket stream implements the required `Stream` and `Sink` traits,
//! so the socket is just a stream of messages coming in and going out.

#![deny(
    missing_docs,
    unused_must_use,
    unused_mut,
    unused_imports,
    unused_import_braces
)]

pub use tungstenite;

mod compat;
#[cfg(feature = "connect")]
mod connect;
mod handshake;
#[cfg(feature = "stream")]
pub mod stream;

use std::io::{Read, Write};

use compat::{cvt, AllowStd, ContextWaker};
use futures_util::{
    sink::{Sink, SinkExt},
    stream::Stream,
};
use log::*;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite};

use tungstenite::{
    client::IntoClientRequest,
    error::Error as WsError,
    handshake::{
        client::{ClientHandshake, Request, Response},
        server::{Callback, NoCallback},
        HandshakeError,
    },
    protocol::{Message, Role, WebSocket, WebSocketConfig},
    server,
};

#[cfg(feature = "connect")]
pub use connect::{client_async_tls, connect_async};

#[cfg(all(feature = "connect", feature = "tls"))]
pub use connect::MaybeTlsStream;
use tungstenite::protocol::CloseFrame;

/// Creates a WebSocket handshake from a request and a stream.
/// For convenience, the user may call this with a url string, a URL,
/// or a `Request`. Calling with `Request` allows the user to add
/// a WebSocket protocol or other custom headers.
///
/// Internally, this custom creates a handshake representation and returns
/// a future representing the resolution of the WebSocket handshake. The
/// returned future will resolve to either `WebSocketStream<S>` or `Error`
/// depending on whether the handshake is successful.
///
/// This is typically used for clients who have already established, for
/// example, a TCP connection to the remote server.
pub async fn client_async<'a, R, S>(
    request: R,
    stream: S,
) -> Result<(WebSocketStream<S>, Response), WsError>
where
    R: IntoClientRequest + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    client_async_with_config(request, stream, None).await
}

/// The same as `client_async()` but the one can specify a websocket configuration.
/// Please refer to `client_async()` for more details.
pub async fn client_async_with_config<'a, R, S>(
    request: R,
    stream: S,
    config: Option<WebSocketConfig>,
) -> Result<(WebSocketStream<S>, Response), WsError>
where
    R: IntoClientRequest + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let f = handshake::client_handshake(stream, move |allow_std| {
        let request = request.into_client_request()?;
        let cli_handshake = ClientHandshake::start(allow_std, request, config)?;
        cli_handshake.handshake()
    });
    f.await.map_err(|e| match e {
        HandshakeError::Failure(e) => e,
        e => WsError::Io(std::io::Error::new(
            std::io::ErrorKind::Other,
            e.to_string(),
        )),
    })
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function will internally call `server::accept` to create a
/// handshake representation and returns a future representing the
/// resolution of the WebSocket handshake. The returned future will resolve
/// to either `WebSocketStream<S>` or `Error` depending if it's successful
/// or not.
///
/// This is typically used after a socket has been accepted from a
/// `TcpListener`. That socket is then passed to this function to perform
/// the server half of the accepting a client's websocket connection.
pub async fn accept_async<S>(stream: S) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
{
    accept_hdr_async(stream, NoCallback).await
}

/// The same as `accept_async()` but the one can specify a websocket configuration.
/// Please refer to `accept_async()` for more details.
pub async fn accept_async_with_config<S>(
    stream: S,
    config: Option<WebSocketConfig>,
) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
{
    accept_hdr_async_with_config(stream, NoCallback, config).await
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function does the same as `accept_async()` but accepts an extra callback
/// for header processing. The callback receives headers of the incoming
/// requests and is able to add extra headers to the reply.
pub async fn accept_hdr_async<S, C>(stream: S, callback: C) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
    C: Callback + Unpin,
{
    accept_hdr_async_with_config(stream, callback, None).await
}

/// The same as `accept_hdr_async()` but the one can specify a websocket configuration.
/// Please refer to `accept_hdr_async()` for more details.
pub async fn accept_hdr_async_with_config<S, C>(
    stream: S,
    callback: C,
    config: Option<WebSocketConfig>,
) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
    C: Callback + Unpin,
{
    let f = handshake::server_handshake(stream, move |allow_std| {
        server::accept_hdr_with_config(allow_std, callback, config)
    });
    f.await.map_err(|e| match e {
        HandshakeError::Failure(e) => e,
        e => WsError::Io(std::io::Error::new(
            std::io::ErrorKind::Other,
            e.to_string(),
        )),
    })
}

/// A wrapper around an underlying raw stream which implements the WebSocket
/// protocol.
///
/// A `WebSocketStream<S>` represents a handshake that has been completed
/// successfully and both the server and the client are ready for receiving
/// and sending data. Message from a `WebSocketStream<S>` are accessible
/// through the respective `Stream` and `Sink`. Check more information about
/// them in `futures-rs` crate documentation or have a look on the examples
/// and unit tests for this crate.
#[derive(Debug)]
pub struct WebSocketStream<S> {
    inner: WebSocket<AllowStd<S>>,
}

impl<S> WebSocketStream<S> {
    /// Convert a raw socket into a WebSocketStream without performing a
    /// handshake.
    pub async fn from_raw_socket(stream: S, role: Role, config: Option<WebSocketConfig>) -> Self
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        handshake::without_handshake(stream, move |allow_std| {
            WebSocket::from_raw_socket(allow_std, role, config)
        })
        .await
    }

    /// Convert a raw socket into a WebSocketStream without performing a
    /// handshake.
    pub async fn from_partially_read(
        stream: S,
        part: Vec<u8>,
        role: Role,
        config: Option<WebSocketConfig>,
    ) -> Self
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        handshake::without_handshake(stream, move |allow_std| {
            WebSocket::from_partially_read(allow_std, part, role, config)
        })
        .await
    }

    pub(crate) fn new(ws: WebSocket<AllowStd<S>>) -> Self {
        WebSocketStream { inner: ws }
    }

    fn with_context<F, R>(&mut self, ctx: Option<(ContextWaker, &mut Context<'_>)>, f: F) -> R
    where
        S: Unpin,
        F: FnOnce(&mut WebSocket<AllowStd<S>>) -> R,
        AllowStd<S>: Read + Write,
    {
        trace!("{}:{} WebSocketStream.with_context", file!(), line!());
        if let Some((kind, ctx)) = ctx {
            self.inner.get_mut().set_waker(kind, &ctx.waker());
        }
        f(&mut self.inner)
    }

    /// Returns a shared reference to the inner stream.
    pub fn get_ref(&self) -> &S
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        &self.inner.get_ref().get_ref()
    }

    /// Returns a mutable reference to the inner stream.
    pub fn get_mut(&mut self) -> &mut S
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        self.inner.get_mut().get_mut()
    }

    /// Close the underlying web socket
    pub async fn close(&mut self, msg: Option<CloseFrame<'_>>) -> Result<(), WsError>
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        let msg = msg.map(|msg| msg.into_owned());
        self.send(Message::Close(msg)).await
    }
}

impl<T> Stream for WebSocketStream<T>
where
    T: AsyncRead + AsyncWrite + Unpin,
{
    type Item = Result<Message, WsError>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        trace!("{}:{} Stream.poll_next", file!(), line!());
        match futures_util::ready!(self.with_context(Some((ContextWaker::Read, cx)), |s| {
            trace!(
                "{}:{} Stream.with_context poll_next -> read_message()",
                file!(),
                line!()
            );
            cvt(s.read_message())
        })) {
            Ok(v) => Poll::Ready(Some(Ok(v))),
            Err(WsError::AlreadyClosed) | Err(WsError::ConnectionClosed) => Poll::Ready(None),
            Err(e) => Poll::Ready(Some(Err(e))),
        }
    }
}

impl<T> Sink<Message> for WebSocketStream<T>
where
    T: AsyncRead + AsyncWrite + Unpin,
{
    type Error = WsError;

    fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        (*self).with_context(Some((ContextWaker::Write, cx)), |s| cvt(s.write_pending()))
    }

    fn start_send(mut self: Pin<&mut Self>, item: Message) -> Result<(), Self::Error> {
        match (*self).with_context(None, |s| s.write_message(item)) {
            Ok(()) => Ok(()),
            Err(::tungstenite::Error::Io(ref err))
                if err.kind() == std::io::ErrorKind::WouldBlock =>
            {
                // the message was accepted and queued
                // isn't an error.
                Ok(())
            }
            Err(e) => {
                debug!("websocket start_send error: {}", e);
                Err(e)
            }
        }
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        (*self).with_context(Some((ContextWaker::Write, cx)), |s| cvt(s.write_pending()))
    }

    fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        match (*self).with_context(Some((ContextWaker::Write, cx)), |s| s.close(None)) {
            Ok(()) => Poll::Ready(Ok(())),
            Err(::tungstenite::Error::ConnectionClosed) => Poll::Ready(Ok(())),
            Err(err) => {
                debug!("websocket close error: {}", err);
                Poll::Ready(Err(err))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::compat::AllowStd;
    #[cfg(feature = "connect")]
    use crate::connect::encryption::AutoStream;
    use crate::WebSocketStream;
    use std::io::{Read, Write};
    use tokio::io::{AsyncReadExt, AsyncWriteExt};

    fn is_read<T: Read>() {}
    fn is_write<T: Write>() {}
    fn is_async_read<T: AsyncReadExt>() {}
    fn is_async_write<T: AsyncWriteExt>() {}
    fn is_unpin<T: Unpin>() {}

    #[test]
    fn web_socket_stream_has_traits() {
        is_read::<AllowStd<tokio::net::TcpStream>>();
        is_write::<AllowStd<tokio::net::TcpStream>>();

        #[cfg(feature = "connect")]
        is_async_read::<AutoStream<tokio::net::TcpStream>>();
        #[cfg(feature = "connect")]
        is_async_write::<AutoStream<tokio::net::TcpStream>>();

        is_unpin::<WebSocketStream<tokio::net::TcpStream>>();
        #[cfg(feature = "connect")]
        is_unpin::<WebSocketStream<AutoStream<tokio::net::TcpStream>>>();
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate rustc_serialize;

mod error;
mod util;
pub mod types;

pub use types::*;
pub use error::*;
use util::Params;

use rustc_serialize::{json, Decodable};
use std::io::Read;
use std::net::ToSocketAddrs;
use hyper::{Client, Url, Server};
use hyper::client::IntoUrl;
use hyper::header::Connection;
use hyper::server;
use hyper::net::Fresh;

/// API-URL prefix
pub const API_URL : &'static str = "https://api.telegram.org/bot";

/// The Bot. Main type for doing nearly everything.
pub struct Bot {
    offset: Integer,
    url: Url,
    client: Client,
}

impl Bot {
    // =======================================================================
    // Constructors
    // =======================================================================
    /// Creates a new bot with the given token. If the token is completely
    /// invalid (resulting in an invalid API-URL), the function will panic.
    /// However, the function will not check if the given token is a valid
    /// Telegram token. You can call `get_me` to execute a test request.
    pub fn new(token: String) -> Bot {
        let url = match Url::parse(&*format!("{}{}/dummy", API_URL, token)) {
            Ok(url) => url,
            Err(e) => panic!("Invalid token! ({})", e),
        };
        Bot {
            offset: 0,
            url: url,
            client: Client::new(),
        }
    }

    // =======================================================================
    // Methods corresponding directly to a API method
    // =======================================================================
    /// Corresponds to the "getMe" method of the API.
    pub fn get_me(&mut self) -> Result<User> {
        // Execute request with empty parameter list
        self.send_request("getMe", Params::new())
    }

    /// Corresponds to the "sendMessage" method of the API.
    pub fn send_message(&mut self, chat_id: Integer, text: String,
                        disable_web_page_preview: Option<bool>,
                        reply_to_message_id: Option<Integer>,
                        reply_markup: Option<ReplyMarkup>)
                        -> Result<Message> {
        // Prepare parameters
        let mut params = Params::new();
        params.add_get("chat_id", chat_id);
        params.add_get("text", text);
        params.add_get_opt("disable_web_page_preview", disable_web_page_preview);
        params.add_get_opt("reply_to_message_id", reply_to_message_id);
        try!(params.add_get_json_opt("reply_markup", reply_markup));

        // Execute request
        self.send_request("sendMessage", params)
    }

    /// Corresponds to the "forwardMessage" method of the API.
    pub fn forward_message(&mut self, chat_id: Integer, from_chat_id: Integer,
                           message_id: Integer) -> Result<Message> {
        // Prepare parameters
        let mut params = Params::new();
        params.add_get("chat_id", chat_id);
        params.add_get("from_chat_id", from_chat_id);
        params.add_get("message_id", message_id);

        // Execute request
        self.send_request("forwardMessage", params)
    }

    /// Corresponds to the "sendLocation" method of the API.
    pub fn send_location(&mut self, chat_id: Integer, latitude: Float,
                         longitude: Float, reply_to_message_id: Option<Integer>,
                         reply_markup: Option<ReplyMarkup>)
                         -> Result<Message> {
        // Prepare parameters
        let mut params = Params::new();
        params.add_get("chat_id", chat_id);
        params.add_get("latitude", latitude);
        params.add_get("longitude", longitude);
        params.add_get_opt("reply_to_message_id", reply_to_message_id);
        try!(params.add_get_json_opt("reply_markup", reply_markup));

        // Execute request
        self.send_request("sendLocation", params)
    }

    /// Corresponds to the "sendChatAction" method of the API.
    pub fn send_chat_action(&mut self, chat_id: Integer, action: ChatAction)
                            -> Result<bool> {
        let mut params = Params::new();
        params.add_get("chat_id", chat_id);
        params.add_get("action", action);

        // Execute request
        self.send_request("sendChatAction", params)
    }

    /// Corresponds to the "getUserProfilePhotos" method of the API.
    pub fn get_user_profile_photos(&mut self, user_id: Integer,
                                   offset: Option<Integer>,
                                   limit: Option<Integer>)
                                   -> Result<UserProfilePhotos> {
        let mut params = Params::new();
        params.add_get("user_id", user_id);
        params.add_get_opt("offset", offset);
        params.add_get_opt("limit", limit);

        // Execute request
        self.send_request("getUserProfilePhotos", params)
    }

    /// Corresponds to the "getUpdates" method of the API.
    ///
    /// **Note:**
    /// The method will not set the offset parameter on its own. To receive
    /// updates in a more high level way, see `long_poll`.
    pub fn get_updates(&mut self, offset: Option<Integer>,
                       limit: Option<Integer>, timeout: Option<Integer>)
                       -> Result<Vec<Update>> {
        // Prepare parameters
        let mut params = Params::new();
        params.add_get_opt("offset", offset);
        params.add_get_opt("limit", limit);
        params.add_get_opt("timeout", timeout);

        // Execute request
        self.send_request("getUpdates", params)
    }

    pub fn set_webhook<U: IntoUrl>(&mut self, url: Option<U>) -> Result<bool> {
        let u = url.map_or("".into(), |u| u.into_url().unwrap().to_string());

        // Prepare parameters
        let mut params = Params::new();
        params.add_get("url", u);

        // Execute request
        self.send_request("setWebhook", params)
    }

    // =======================================================================
    // Methods for receiving updates
    // =======================================================================
    /// Receive and handle updates via "getUpdates".
    ///
    /// This method will repeatedly call `get_updates` to receive new updates.
    /// It will then call the given handler for every update and increase the
    /// update offset accordingly, so the handler will never be called with
    /// the same update twice.
    /// The `timeout` parameter influences how long (in seconds) each poll may
    /// last. Defaults to 30.
    ///
    /// **Note:**
    /// If the bot is restarted, but the last received updates are not yet
    /// confirmed (the last poll was not empty), there will be some duplicate
    /// updates.
    pub fn long_poll<H>(&mut self, timeout: Option<Integer>, handler: H)
                        -> Result<()>
                        where H: Fn(&mut Bot, Update) -> Result<()> {
        // Calculate final timeout: Given or default (30s)
        let timeout = timeout.or(Some(30));

        loop {
            // Receive updates with correct offset
            let offset = Some(self.offset);
            let updates = try!(self.get_updates(offset, None, timeout));

            // For every update: Increase the offset and call the handler.
            for u in updates {
                if u.update_id >= self.offset {
                    self.offset = u.update_id + 1;
                }

                try!(handler(self, u));
            }
        }
    }

    pub fn listen<U, H>(&mut self, url: U, handler: H) -> Result<()>
                     where H: Fn(&mut Bot, Update) -> Result<()>,
                           U: IntoUrl {
        // blabla
        println!("Hello Listen!");

        fn handle_update(mut req: server::Request, mut res: server::Response<Fresh>) {
            use hyper::header;
            println!("Hello Handle!");

            let mut body = String::new();
            req.read_to_string(&mut body);

            println!("DING: {}", body);

            res.headers_mut().set(header::Connection::close());
        }

        // TODO: Port 80 not hardcoded!
        let listener = try!(Server::http("0.0.0.0:8443")).handle(handle_update);

        println!("AFTER");
        // Tell Telegram that we're listening
        self.set_webhook(Some(url));

        Ok(())
    }

    // =======================================================================
    // Private methods
    // =======================================================================
    fn send_request<T: Decodable>(&mut self, method: &str, p: Params)
                   -> Result<T> {
        // Prepare URL for request: Clone and change the last path fragment
        // to the method name and append GET parameters.
        let mut url = self.url.clone();
        url.path_mut().map(|path| {         // if theres a path: Change it
            path.last_mut().map(|last| {    // if its not empty: Change last...
                *last = method.into()       // ... into method name
            })
        });

        // For all (str, String) pairs: Map to (str, str) and append it to URL
        let it = p.get_params().iter().map(|&(k, ref v)| (k, &**v));
        url.set_query_from_pairs(it);

        // Prepare HTTP Request
        let req = self.client.get(url).header(Connection::close());

        // Send request and check if it failed
        let mut resp = try!(req.send());

        // Read response into String and return error if it failed
        let mut body = String::new();
        try!(resp.read_to_string(&mut body));

        // Try to decode response as JSON representing a Response
        match try!(json::decode(&*body)) {
            // If the response says that there was an error: Return API-Error
            // with the given description.
            Response { ok: false, description: Some(desc), ..} => {
                Err(Error::Api(desc))
            },
            // If response is "ok": Return the result.
            Response { ok: true, result: Some(res), ..} => {
                Ok(res)
            },
            // This should never occur: If "ok"==false, "description" should
            // always be Some. If "ok"==true, then "result" should always be
            // Some. We could also panic in this case.
            _ => Err(Error::InvalidState("Invalid server response".into())),
        }
    }
}
<commit_msg>Remove unfinished function and warnings<commit_after>extern crate hyper;
extern crate rustc_serialize;

mod error;
mod util;
pub mod types;

pub use types::*;
pub use error::*;
use util::Params;

use rustc_serialize::{json, Decodable};
use std::io::Read;
use hyper::{Client, Url};
use hyper::client::IntoUrl;
use hyper::header::Connection;

/// API-URL prefix
pub const API_URL : &'static str = "https://api.telegram.org/bot";

/// The Bot. Main type for doing nearly everything.
pub struct Bot {
    offset: Integer,
    url: Url,
    client: Client,
}

impl Bot {
    // =======================================================================
    // Constructors
    // =======================================================================
    /// Creates a new bot with the given token. If the token is completely
    /// invalid (resulting in an invalid API-URL), the function will panic.
    /// However, the function will not check if the given token is a valid
    /// Telegram token. You can call `get_me` to execute a test request.
    pub fn new(token: String) -> Bot {
        let url = match Url::parse(&*format!("{}{}/dummy", API_URL, token)) {
            Ok(url) => url,
            Err(e) => panic!("Invalid token! ({})", e),
        };
        Bot {
            offset: 0,
            url: url,
            client: Client::new(),
        }
    }

    // =======================================================================
    // Methods corresponding directly to a API method
    // =======================================================================
    /// Corresponds to the "getMe" method of the API.
    pub fn get_me(&mut self) -> Result<User> {
        // Execute request with empty parameter list
        self.send_request("getMe", Params::new())
    }

    /// Corresponds to the "sendMessage" method of the API.
    pub fn send_message(&mut self, chat_id: Integer, text: String,
                        disable_web_page_preview: Option<bool>,
                        reply_to_message_id: Option<Integer>,
                        reply_markup: Option<ReplyMarkup>)
                        -> Result<Message> {
        // Prepare parameters
        let mut params = Params::new();
        params.add_get("chat_id", chat_id);
        params.add_get("text", text);
        params.add_get_opt("disable_web_page_preview", disable_web_page_preview);
        params.add_get_opt("reply_to_message_id", reply_to_message_id);
        try!(params.add_get_json_opt("reply_markup", reply_markup));

        // Execute request
        self.send_request("sendMessage", params)
    }

    /// Corresponds to the "forwardMessage" method of the API.
    pub fn forward_message(&mut self, chat_id: Integer, from_chat_id: Integer,
                           message_id: Integer) -> Result<Message> {
        // Prepare parameters
        let mut params = Params::new();
        params.add_get("chat_id", chat_id);
        params.add_get("from_chat_id", from_chat_id);
        params.add_get("message_id", message_id);

        // Execute request
        self.send_request("forwardMessage", params)
    }

    /// Corresponds to the "sendLocation" method of the API.
    pub fn send_location(&mut self, chat_id: Integer, latitude: Float,
                         longitude: Float, reply_to_message_id: Option<Integer>,
                         reply_markup: Option<ReplyMarkup>)
                         -> Result<Message> {
        // Prepare parameters
        let mut params = Params::new();
        params.add_get("chat_id", chat_id);
        params.add_get("latitude", latitude);
        params.add_get("longitude", longitude);
        params.add_get_opt("reply_to_message_id", reply_to_message_id);
        try!(params.add_get_json_opt("reply_markup", reply_markup));

        // Execute request
        self.send_request("sendLocation", params)
    }

    /// Corresponds to the "sendChatAction" method of the API.
    pub fn send_chat_action(&mut self, chat_id: Integer, action: ChatAction)
                            -> Result<bool> {
        let mut params = Params::new();
        params.add_get("chat_id", chat_id);
        params.add_get("action", action);

        // Execute request
        self.send_request("sendChatAction", params)
    }

    /// Corresponds to the "getUserProfilePhotos" method of the API.
    pub fn get_user_profile_photos(&mut self, user_id: Integer,
                                   offset: Option<Integer>,
                                   limit: Option<Integer>)
                                   -> Result<UserProfilePhotos> {
        let mut params = Params::new();
        params.add_get("user_id", user_id);
        params.add_get_opt("offset", offset);
        params.add_get_opt("limit", limit);

        // Execute request
        self.send_request("getUserProfilePhotos", params)
    }

    /// Corresponds to the "getUpdates" method of the API.
    ///
    /// **Note:**
    /// The method will not set the offset parameter on its own. To receive
    /// updates in a more high level way, see `long_poll`.
    pub fn get_updates(&mut self, offset: Option<Integer>,
                       limit: Option<Integer>, timeout: Option<Integer>)
                       -> Result<Vec<Update>> {
        // Prepare parameters
        let mut params = Params::new();
        params.add_get_opt("offset", offset);
        params.add_get_opt("limit", limit);
        params.add_get_opt("timeout", timeout);

        // Execute request
        self.send_request("getUpdates", params)
    }

    pub fn set_webhook<U: IntoUrl>(&mut self, url: Option<U>) -> Result<bool> {
        let u = url.map_or("".into(), |u| u.into_url().unwrap().to_string());

        // Prepare parameters
        let mut params = Params::new();
        params.add_get("url", u);

        // Execute request
        self.send_request("setWebhook", params)
    }

    // =======================================================================
    // Methods for receiving updates
    // =======================================================================
    /// Receive and handle updates via "getUpdates".
    ///
    /// This method will repeatedly call `get_updates` to receive new updates.
    /// It will then call the given handler for every update and increase the
    /// update offset accordingly, so the handler will never be called with
    /// the same update twice.
    /// The `timeout` parameter influences how long (in seconds) each poll may
    /// last. Defaults to 30.
    ///
    /// **Note:**
    /// If the bot is restarted, but the last received updates are not yet
    /// confirmed (the last poll was not empty), there will be some duplicate
    /// updates.
    pub fn long_poll<H>(&mut self, timeout: Option<Integer>, handler: H)
                        -> Result<()>
                        where H: Fn(&mut Bot, Update) -> Result<()> {
        // Calculate final timeout: Given or default (30s)
        let timeout = timeout.or(Some(30));

        loop {
            // Receive updates with correct offset
            let offset = Some(self.offset);
            let updates = try!(self.get_updates(offset, None, timeout));

            // For every update: Increase the offset and call the handler.
            for u in updates {
                if u.update_id >= self.offset {
                    self.offset = u.update_id + 1;
                }

                try!(handler(self, u));
            }
        }
    }

    // =======================================================================
    // Private methods
    // =======================================================================
    fn send_request<T: Decodable>(&mut self, method: &str, p: Params)
                   -> Result<T> {
        // Prepare URL for request: Clone and change the last path fragment
        // to the method name and append GET parameters.
        let mut url = self.url.clone();
        url.path_mut().map(|path| {         // if theres a path: Change it
            path.last_mut().map(|last| {    // if its not empty: Change last...
                *last = method.into()       // ... into method name
            })
        });

        // For all (str, String) pairs: Map to (str, str) and append it to URL
        let it = p.get_params().iter().map(|&(k, ref v)| (k, &**v));
        url.set_query_from_pairs(it);

        // Prepare HTTP Request
        let req = self.client.get(url).header(Connection::close());

        // Send request and check if it failed
        let mut resp = try!(req.send());

        // Read response into String and return error if it failed
        let mut body = String::new();
        try!(resp.read_to_string(&mut body));

        // Try to decode response as JSON representing a Response
        match try!(json::decode(&*body)) {
            // If the response says that there was an error: Return API-Error
            // with the given description.
            Response { ok: false, description: Some(desc), ..} => {
                Err(Error::Api(desc))
            },
            // If response is "ok": Return the result.
            Response { ok: true, result: Some(res), ..} => {
                Ok(res)
            },
            // This should never occur: If "ok"==false, "description" should
            // always be Some. If "ok"==true, then "result" should always be
            // Some. We could also panic in this case.
            _ => Err(Error::InvalidState("Invalid server response".into())),
        }
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "nightly", feature(collections))]

/// Create a `HashMap` containing the arguments
///
/// `hashmap!` allows `HashMap`s to be constructed using minimal syntax:
///
/// ```
/// # #[cfg_attr(feature = "nightly", feature(collections))]
/// # #[macro_use] extern crate collection_macros;
/// use std::collections::HashMap;
/// # fn main() {
/// let m = hashmap!{
///     "a" => "foo",
///     "b" => "bar",
///     "c" => "baz",
/// };
/// assert_eq!(m.get("a"), Some(&"foo"));
/// assert_eq!(m.get("b"), Some(&"bar"));
/// assert_eq!(m.get("c"), Some(&"baz"));
/// # }
/// ```
///
#[macro_export]
macro_rules! hashmap {
    ( $($x:expr => $y:expr),* ) => ({
        let mut temp_map = HashMap::new();
        $(
            temp_map.insert($x, $y);
        )*
        temp_map
    });
    ( $($x:expr => $y:expr,)* ) => (
        hashmap!{$($x => $y),*}
    );
}

/// Create a `BTreeMap` containing the arguments
///
/// `btreemap!` allows `BTreeMap`s to be constructed using minimal syntax:
///
/// - Create a `BTreeMap` using a list of `key => value` pairs:
///
/// ```
/// # #[macro_use] extern crate collection_macros;
/// use std::collections::BTreeMap;
/// # fn main() {
/// let m = btreemap!{
///     1 => "foo",
///     2 => "bar",
///     3 => "baz",
///     5 => "quux",
/// };
/// assert_eq!(m.get(&1), Some(&"foo"));
/// assert_eq!(m.get(&2), Some(&"bar"));
/// assert_eq!(m.get(&3), Some(&"baz"));
/// assert_eq!(m.get(&5), Some(&"quux"));
/// # }
/// ```
///
#[cfg_attr(feature = "nightly", doc = r#"If you are using nightly, there is a second form to this macro:"#)]
#[cfg_attr(feature = "nightly", doc = r#""#)]
#[cfg_attr(feature = "nightly", doc = r#"- Create a `BTreeMap` using the `BTreeMap::with_b` constructor, and a list"#)]
#[cfg_attr(feature = "nightly", doc = r#"  of `key => value` pairs. This is currently only available on nightly"#)]
#[cfg_attr(feature = "nightly", doc = r#""#)]
#[cfg_attr(feature = "nightly", doc = r#"```"#)]
#[cfg_attr(feature = "nightly", doc = r#"# #![feature(collections)]"#)]
#[cfg_attr(feature = "nightly", doc = r#"# #[macro_use] extern crate collection_macros;"#)]
#[cfg_attr(feature = "nightly", doc = r#"use std::collections::BTreeMap;"#)]
#[cfg_attr(feature = "nightly", doc = r#"# fn main() {"#)]
#[cfg_attr(feature = "nightly", doc = r#"let m = btreemap!{"#)]
#[cfg_attr(feature = "nightly", doc = r#"    6;"#)]
#[cfg_attr(feature = "nightly", doc = r#"    1 => "foo","#)]
#[cfg_attr(feature = "nightly", doc = r#"    2 => "bar","#)]
#[cfg_attr(feature = "nightly", doc = r#"    3 => "baz","#)]
#[cfg_attr(feature = "nightly", doc = r#"    5 => "quux","#)]
#[cfg_attr(feature = "nightly", doc = r#"};"#)]
#[cfg_attr(feature = "nightly", doc = r#"assert_eq!(m.get(&1), Some(&"foo"));"#)]
#[cfg_attr(feature = "nightly", doc = r#"assert_eq!(m.get(&2), Some(&"bar"));"#)]
#[cfg_attr(feature = "nightly", doc = r#"assert_eq!(m.get(&3), Some(&"baz"));"#)]
#[cfg_attr(feature = "nightly", doc = r#"assert_eq!(m.get(&5), Some(&"quux"));"#)]
#[cfg_attr(feature = "nightly", doc = r#"# }"#)]
#[cfg_attr(feature = "nightly", doc = "```")]
#[cfg_attr(feature = "nightly", doc = "")]
#[macro_export]
macro_rules! btreemap {
    ( $b:expr; $($x:expr => $y:expr),* ) => ({
        let mut temp_map = BTreeMap::with_b($b);
        $(
            temp_map.insert($x, $y);
        )*
        temp_map
    });
    ( $($x:expr => $y:expr),* ) => ({
        let mut temp_map = BTreeMap::new();
        $(
            temp_map.insert($x, $y);
        )*
        temp_map
    });
    ( $b:expr; $($x:expr => $y:expr,)* ) => (
        btreemap!{$b; $($x => $y),*}
    );
    ( $($x:expr => $y:expr,)* ) => (
        btreemap!{$($x => $y),*}
    );
}

#[cfg(test)] mod tests {
    use std::collections::{BTreeMap, HashMap};

    #[cfg(feature = "nightly")]
    #[test]
    fn test_btreemap_with_b() {
        let bmap = btreemap! {
            6;
            1 => "hello",
            3 => "blah",
        };

        let mut should_be = BTreeMap::new();
        should_be.insert(1, "hello");
        should_be.insert(3, "blah");

        assert_eq!(bmap, should_be);
    }

    #[test]
    fn test_btreemap() {
        let map = btreemap! {
            1 => "hello",
            3 => "blah",
        };

        let mut should_be = BTreeMap::new();
        should_be.insert(1, "hello");
        should_be.insert(3, "blah");

        assert_eq!(map, should_be);

    }

    #[test]
    fn test_hashmap() {
        let map = hashmap!{
            "one" => "two",
            "three" => "four",
        };

        let mut should_be = HashMap::new();
        should_be.insert("one", "two");
        should_be.insert("three", "four");

        assert_eq!(map, should_be);
    }
}

<commit_msg>add doc root<commit_after>#![doc(html_root_url = "https://pwoolcoc.github.io/collection_macros/")]
#![cfg_attr(feature = "nightly", feature(collections))]

/// Create a `HashMap` containing the arguments
///
/// `hashmap!` allows `HashMap`s to be constructed using minimal syntax:
///
/// ```
/// # #[cfg_attr(feature = "nightly", feature(collections))]
/// # #[macro_use] extern crate collection_macros;
/// use std::collections::HashMap;
/// # fn main() {
/// let m = hashmap!{
///     "a" => "foo",
///     "b" => "bar",
///     "c" => "baz",
/// };
/// assert_eq!(m.get("a"), Some(&"foo"));
/// assert_eq!(m.get("b"), Some(&"bar"));
/// assert_eq!(m.get("c"), Some(&"baz"));
/// # }
/// ```
///
#[macro_export]
macro_rules! hashmap {
    ( $($x:expr => $y:expr),* ) => ({
        let mut temp_map = HashMap::new();
        $(
            temp_map.insert($x, $y);
        )*
        temp_map
    });
    ( $($x:expr => $y:expr,)* ) => (
        hashmap!{$($x => $y),*}
    );
}

/// Create a `BTreeMap` containing the arguments
///
/// `btreemap!` allows `BTreeMap`s to be constructed using minimal syntax:
///
/// - Create a `BTreeMap` using a list of `key => value` pairs:
///
/// ```
/// # #[macro_use] extern crate collection_macros;
/// use std::collections::BTreeMap;
/// # fn main() {
/// let m = btreemap!{
///     1 => "foo",
///     2 => "bar",
///     3 => "baz",
///     5 => "quux",
/// };
/// assert_eq!(m.get(&1), Some(&"foo"));
/// assert_eq!(m.get(&2), Some(&"bar"));
/// assert_eq!(m.get(&3), Some(&"baz"));
/// assert_eq!(m.get(&5), Some(&"quux"));
/// # }
/// ```
///
#[cfg_attr(feature = "nightly", doc = r#"If you are using nightly, there is a second form to this macro:"#)]
#[cfg_attr(feature = "nightly", doc = r#""#)]
#[cfg_attr(feature = "nightly", doc = r#"- Create a `BTreeMap` using the `BTreeMap::with_b` constructor, and a list"#)]
#[cfg_attr(feature = "nightly", doc = r#"  of `key => value` pairs. This is currently only available on nightly"#)]
#[cfg_attr(feature = "nightly", doc = r#""#)]
#[cfg_attr(feature = "nightly", doc = r#"```"#)]
#[cfg_attr(feature = "nightly", doc = r#"# #![feature(collections)]"#)]
#[cfg_attr(feature = "nightly", doc = r#"# #[macro_use] extern crate collection_macros;"#)]
#[cfg_attr(feature = "nightly", doc = r#"use std::collections::BTreeMap;"#)]
#[cfg_attr(feature = "nightly", doc = r#"# fn main() {"#)]
#[cfg_attr(feature = "nightly", doc = r#"let m = btreemap!{"#)]
#[cfg_attr(feature = "nightly", doc = r#"    6;"#)]
#[cfg_attr(feature = "nightly", doc = r#"    1 => "foo","#)]
#[cfg_attr(feature = "nightly", doc = r#"    2 => "bar","#)]
#[cfg_attr(feature = "nightly", doc = r#"    3 => "baz","#)]
#[cfg_attr(feature = "nightly", doc = r#"    5 => "quux","#)]
#[cfg_attr(feature = "nightly", doc = r#"};"#)]
#[cfg_attr(feature = "nightly", doc = r#"assert_eq!(m.get(&1), Some(&"foo"));"#)]
#[cfg_attr(feature = "nightly", doc = r#"assert_eq!(m.get(&2), Some(&"bar"));"#)]
#[cfg_attr(feature = "nightly", doc = r#"assert_eq!(m.get(&3), Some(&"baz"));"#)]
#[cfg_attr(feature = "nightly", doc = r#"assert_eq!(m.get(&5), Some(&"quux"));"#)]
#[cfg_attr(feature = "nightly", doc = r#"# }"#)]
#[cfg_attr(feature = "nightly", doc = "```")]
#[cfg_attr(feature = "nightly", doc = "")]
#[macro_export]
macro_rules! btreemap {
    ( $b:expr; $($x:expr => $y:expr),* ) => ({
        let mut temp_map = BTreeMap::with_b($b);
        $(
            temp_map.insert($x, $y);
        )*
        temp_map
    });
    ( $($x:expr => $y:expr),* ) => ({
        let mut temp_map = BTreeMap::new();
        $(
            temp_map.insert($x, $y);
        )*
        temp_map
    });
    ( $b:expr; $($x:expr => $y:expr,)* ) => (
        btreemap!{$b; $($x => $y),*}
    );
    ( $($x:expr => $y:expr,)* ) => (
        btreemap!{$($x => $y),*}
    );
}

#[cfg(test)] mod tests {
    use std::collections::{BTreeMap, HashMap};

    #[cfg(feature = "nightly")]
    #[test]
    fn test_btreemap_with_b() {
        let bmap = btreemap! {
            6;
            1 => "hello",
            3 => "blah",
        };

        let mut should_be = BTreeMap::new();
        should_be.insert(1, "hello");
        should_be.insert(3, "blah");

        assert_eq!(bmap, should_be);
    }

    #[test]
    fn test_btreemap() {
        let map = btreemap! {
            1 => "hello",
            3 => "blah",
        };

        let mut should_be = BTreeMap::new();
        should_be.insert(1, "hello");
        should_be.insert(3, "blah");

        assert_eq!(map, should_be);

    }

    #[test]
    fn test_hashmap() {
        let map = hashmap!{
            "one" => "two",
            "three" => "four",
        };

        let mut should_be = HashMap::new();
        should_be.insert("one", "two");
        should_be.insert("three", "four");

        assert_eq!(map, should_be);
    }
}

<|endoftext|>


<commit_before>extern crate libc;

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

/* Re-exports */

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

/* Submodules */

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

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

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

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

struct EngineInternal {
    p: *mut QrsEngine,
}

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

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

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

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

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

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

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

        Engine {
            i: i
        }
    }

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

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

        Engine {
            i: i
        }
    }

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

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

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

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

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

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

            boxed.qobj = qobj;

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

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

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

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

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

        MetaObject { p: p }
    }

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

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

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

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

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

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

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

            ffi::qmlrs_varlist_destroy(c_args);

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

            Ok(ret)
        }
    }
}
*/

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

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

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

/* Re-exports */

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

/* Submodules */

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

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

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

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

struct EngineInternal {
    p: *mut QrsEngine,
}

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

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

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

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

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

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

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

        Engine {
            i: i
        }
    }

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

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

        Engine {
            i: i
        }
    }

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

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

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

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

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

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

            boxed.qobj = qobj;

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

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

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

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

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

        MetaObject { p: p }
    }

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

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

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

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

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

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

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

            ffi::qmlrs_varlist_destroy(c_args);

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

            Ok(ret)
        }
    }
}
*/

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

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


<commit_before>#![doc(html_root_url = "https://urschrei.github.io/ostn02_phf/")]
//! Look up OSTN02 adjustments for transforming ETRS89 Eastings and Northings
//! to OSGB36 Eastings and Northings

const MIN_X_SHIFT: f64 = 86.275;
const MIN_Y_SHIFT: f64 = -81.603;
const MIN_Z_SHIFT: f64 = 43.982;

extern crate phf;
include!("ostn02.rs");

extern crate libc;
use libc::{c_double, uint32_t};

/// Return a 3-tuple of adjustments which convert ETRS89 Eastings and Northings
/// to OSGB36 Eastings, Northings, and Orthometric height
fn get_shifts(tup: (u32, u32)) -> (f64, f64, f64) {
    // look up the shifts, or return 9999.000
    let key = format!("{:03x}{:03x}", tup.1, tup.0);
    match ostn02_lookup(&*key) {
        Some(res) => {
            (res.0 as f64 / 1000. + MIN_X_SHIFT,
             res.1 as f64 / 1000. + MIN_Y_SHIFT,
             res.2 as f64 / 1000. + MIN_Z_SHIFT)
        }
        None => (9999.000, 9999.000, 9999.000),
    }
}

#[repr(C)]
/// Incoming ETRS89 kilometer-grid references
pub struct GridRefs {
    pub easting: uint32_t,
    pub northing: uint32_t,
}

#[repr(C)]
#[derive(Debug)]
/// Outgoing OSTN02 Easting, Northing, and height adjustments
pub struct Adjustment {
    pub x_shift: c_double,
    pub y_shift: c_double,
    pub z_shift: c_double,
}

// From and Into traits for GridRefs
impl From<(u32, u32)> for GridRefs {
    fn from(gr: (u32, u32)) -> GridRefs {
        GridRefs {
            easting: gr.0,
            northing: gr.1,
        }
    }
}

impl From<GridRefs> for (u32, u32) {
    fn from(gr: GridRefs) -> (u32, u32) {
        (gr.easting, gr.northing)
    }
}

// From and Into traits for Adjustment
impl From<(f64, f64, f64)> for Adjustment {
    fn from(adj: (f64, f64, f64)) -> Adjustment {
        Adjustment {
            x_shift: adj.0,
            y_shift: adj.1,
            z_shift: adj.2,
        }
    }
}

impl From<Adjustment> for (f64, f64, f64) {
    fn from(adj: Adjustment) -> (f64, f64, f64) {
        (adj.x_shift, adj.y_shift, adj.z_shift)
    }
}

/// FFI function returning a 3-tuple of Easting, Northing, and height adjustments, for use in transforming
/// ETRS89 Eastings and Northings to OSGB36 Eastings, Northings.
/// The argument is a Struct containing kilometer-grid references of the ETRS89 Northings and Eastings you wish to convert
///
/// # Examples
///
/// ```python
/// # Python example using ctypes
/// import sys, ctypes
/// from ctypes import c_uint32, c_double, Structure
///
///
/// class GridRefs(Structure):
///     _fields_ = [("eastings", c_uint32),
///                 ("northings", c_uint32)]
///
///     def __str__(self):
///         return "({},{})".format(self.eastings, self.northings)
///
///
/// class Shifts(Structure):
///     _fields_ = [("x_shift", c_double),
///                 ("y_shift", c_double),
///                 ("z_shift", c_double)]
///
///     def __str__(self):
///         return "({}, {}, {})".format(self.x_shift, self.y_shift, self.z_shift)
///
///
/// prefix = {'win32': ''}.get(sys.platform, 'lib')
/// extension = {'darwin': '.dylib', 'win32': '.dll'}.get(sys.platform, '.so')
/// lib = ctypes.cdll.LoadLibrary(prefix + "ostn02_phf" + extension)
///
/// lib.get_shifts_ffi.argtypes = (GridRefs,)
/// lib.get_shifts_ffi.restype = Shifts
///
/// tup = GridRefs(651, 313)
///
/// # Should return (102.775, -78.244, 44.252)
/// print lib.get_shifts_ffi(tup)
/// ```
#[no_mangle]
pub extern "C" fn get_shifts_ffi(gr: GridRefs) -> Adjustment {
    get_shifts(gr.into()).into()
}

/// Return a 3-tuple of Easting, Northing, and height adjustments, for use in transforming
/// ETRS89 Eastings and Northings to OSGB36 Eastings, Northings.
/// The key is the combined hex-transformed (03x) kilometer-grid reference of the Northings and Eastings:
///
/// # Examples
///
/// ```
/// use ostn02_phf::ostn02_lookup;
///
/// // Caister Tower Eastings and Northings: 651307.003, 313255.686
/// let e_grid = (651307.003 / 1000.) as i32;
/// let n_grid = (313255.686 / 1000.) as i32;
/// let key = format!("{:03x}{:03x}", n_grid, e_grid);
/// // key is 13928b
/// let result = ostn02_lookup(&*key).unwrap();
/// // result should be (16500, 3359, 270)
/// assert_eq!(result, (16500, 3359, 270));
/// // remember that the actual adjustment for a coordinate is a bilinear transform, using a square
/// // see ostn02_shifts in https://github.com/urschrei/lonlat_bng/blob/master/src/ostn02/mod.rs
/// ```
pub fn ostn02_lookup(key: &str) -> Option<(i32, i32, i32)> {
    if key.is_empty() {
        return None;
    }
    OSTN02.get(&*key).cloned()
}

#[test]
fn test_internal_ffi() {
    assert_eq!((102.775, -78.244, 44.252), get_shifts((651, 313)));
}

#[test]
fn test_ffi() {
    let gr = GridRefs {easting: 651, northing: 313};
    assert_eq!((102.775, -78.244, 44.252), get_shifts_ffi(gr).into());
}
<commit_msg>Getting rid of some additional spaces<commit_after>#![doc(html_root_url = "https://urschrei.github.io/ostn02_phf/")]
//! Look up OSTN02 adjustments for transforming ETRS89 Eastings and Northings
//! to OSGB36 Eastings and Northings

const MIN_X_SHIFT: f64 = 86.275;
const MIN_Y_SHIFT: f64 = -81.603;
const MIN_Z_SHIFT: f64 = 43.982;

extern crate phf;
include!("ostn02.rs");

extern crate libc;
use libc::{c_double, uint32_t};

/// Return a 3-tuple of adjustments which convert ETRS89 Eastings and Northings
/// to OSGB36 Eastings, Northings, and Orthometric height
fn get_shifts(tup: (u32, u32)) -> (f64, f64, f64) {
    // look up the shifts, or return 9999.000
    let key = format!("{:03x}{:03x}", tup.1, tup.0);
    match ostn02_lookup(&*key) {
        Some(res) => {
            (res.0 as f64 / 1000. + MIN_X_SHIFT,
             res.1 as f64 / 1000. + MIN_Y_SHIFT,
             res.2 as f64 / 1000. + MIN_Z_SHIFT)
        }
        None => (9999.000, 9999.000, 9999.000),
    }
}

#[repr(C)]
/// Incoming ETRS89 kilometer-grid references
pub struct GridRefs {
    pub easting: uint32_t,
    pub northing: uint32_t,
}

#[repr(C)]
#[derive(Debug)]
/// Outgoing OSTN02 Easting, Northing, and height adjustments
pub struct Adjustment {
    pub x_shift: c_double,
    pub y_shift: c_double,
    pub z_shift: c_double,
}

// From and Into traits for GridRefs
impl From<(u32, u32)> for GridRefs {
    fn from(gr: (u32, u32)) -> GridRefs {
        GridRefs {
            easting: gr.0,
            northing: gr.1,
        }
    }
}

impl From<GridRefs> for (u32, u32) {
    fn from(gr: GridRefs) -> (u32, u32) {
        (gr.easting, gr.northing)
    }
}

// From and Into traits for Adjustment
impl From<(f64, f64, f64)> for Adjustment {
    fn from(adj: (f64, f64, f64)) -> Adjustment {
        Adjustment {
            x_shift: adj.0,
            y_shift: adj.1,
            z_shift: adj.2,
        }
    }
}

impl From<Adjustment> for (f64, f64, f64) {
    fn from(adj: Adjustment) -> (f64, f64, f64) {
        (adj.x_shift, adj.y_shift, adj.z_shift)
    }
}

/// FFI function returning a 3-tuple of Easting, Northing, and height adjustments, for use in transforming
/// ETRS89 Eastings and Northings to OSGB36 Eastings, Northings.
/// The argument is a Struct containing kilometer-grid references of the ETRS89 Northings and Eastings you wish to convert
///
/// # Examples
///
/// ```python
/// # Python example using ctypes
/// import sys, ctypes
/// from ctypes import c_uint32, c_double, Structure
///
///
/// class GridRefs(Structure):
///     _fields_ = [("eastings", c_uint32),
///                 ("northings", c_uint32)]
///
///     def __str__(self):
///         return "({},{})".format(self.eastings, self.northings)
///
///
/// class Shifts(Structure):
///     _fields_ = [("x_shift", c_double),
///                 ("y_shift", c_double),
///                 ("z_shift", c_double)]
///
///     def __str__(self):
///         return "({}, {}, {})".format(self.x_shift, self.y_shift, self.z_shift)
///
///
/// prefix = {'win32': ''}.get(sys.platform, 'lib')
/// extension = {'darwin': '.dylib', 'win32': '.dll'}.get(sys.platform, '.so')
/// lib = ctypes.cdll.LoadLibrary(prefix + "ostn02_phf" + extension)
///
/// lib.get_shifts_ffi.argtypes = (GridRefs,)
/// lib.get_shifts_ffi.restype = Shifts
///
/// tup = GridRefs(651, 313)
///
/// # Should return (102.775, -78.244, 44.252)
/// print lib.get_shifts_ffi(tup)
/// ```
#[no_mangle]
pub extern "C" fn get_shifts_ffi(gr: GridRefs) -> Adjustment {
    get_shifts(gr.into()).into()
}

/// Return a 3-tuple of Easting, Northing, and height adjustments, for use in transforming
/// ETRS89 Eastings and Northings to OSGB36 Eastings, Northings.
/// The key is the combined hex-transformed (03x) kilometer-grid reference of the Northings and Eastings:
///
/// # Examples
///
/// ```
/// use ostn02_phf::ostn02_lookup;
///
/// // Caister Tower Eastings and Northings: 651307.003, 313255.686
/// let e_grid = (651307.003 / 1000.) as i32;
/// let n_grid = (313255.686 / 1000.) as i32;
/// let key = format!("{:03x}{:03x}", n_grid, e_grid);
/// // key is 13928b
/// let result = ostn02_lookup(&*key).unwrap();
/// // result should be (16500, 3359, 270)
/// assert_eq!(result, (16500, 3359, 270));
/// // remember that the actual adjustment for a coordinate is a bilinear transform, using a square
/// // see ostn02_shifts in https://github.com/urschrei/lonlat_bng/blob/master/src/ostn02/mod.rs
/// ```
pub fn ostn02_lookup(key: &str) -> Option<(i32, i32, i32)> {
    if key.is_empty() {
        return None;
    }
    OSTN02.get(&*key).cloned()
}

#[test]
fn test_internal_ffi() {
    assert_eq!((102.775, -78.244, 44.252), get_shifts((651, 313)));
}

#[test]
fn test_ffi() {
    let gr = GridRefs {easting: 651, northing: 313};
    assert_eq!((102.775, -78.244, 44.252), get_shifts_ffi(gr).into());
}
<|endoftext|>


<commit_before>#![crate_name = "shader_version"]
#![deny(missing_doc)]

//! A helper library for detecting and picking compatible shaders.

<commit_msg>Added `VersionRange`<commit_after>#![crate_name = "shader_version"]
#![deny(missing_doc)]

//! A helper library for detecting and picking compatible shaders.

/// Models knowledge about version range.
pub enum VersionRange<T> {
    /// The version range is working from a version,
    /// up to but not included another version.
    ///
    /// With other words, from first time it works until it breaks.
    VersionFromTo(T, T),
    /// The version range is working from a version,
    /// and possibly for all newer versions unless
    /// the context it is used implies otherwise.
    VersionFrom(T)
}

<|endoftext|>


<commit_before>extern crate libc;
extern crate core_foundation;
extern crate security_framework;

macro_rules! fail_on_error {
    ($e:expr) => {
        match $e {
            Ok(s) => s,
            Err(_) => return false,
        }
    }
}

pub mod os_x {
    use security_framework::certificate::SecCertificate;
    use security_framework::policy::SecPolicy;
    use security_framework::secure_transport::ProtocolSide;
    use security_framework::trust::SecTrust;

    pub fn validate_cert_chain(encoded_certs: Vec<&[u8]>, hostname: &str) -> bool {
        let mut certs = Vec::new();
        for encoded_cert in encoded_certs {
            let cert = SecCertificate::from_der(encoded_cert);
            match cert {
                Ok(cert) => certs.push(cert),
                Err(_) => return false,
            }
        }

        let ssl_policy = fail_on_error!(SecPolicy::for_ssl(ProtocolSide::Client, hostname));
        let trust = fail_on_error!(SecTrust::create_with_certificates(&certs[..], &[ssl_policy]));

        // Deliberately swallow errors here: any error is likely to do with the
        // hostname or cert chain, and if those are invalid then by definition the
        // cert does not validate.
        match trust.evaluate() {
            Ok(result) => result.success(),
            Err(_) => false
        }
    }
}

#[cfg(test)]
mod test {
    use os_x::validate_cert_chain;

    fn certifi_chain() -> Vec<&'static[u8]> {
        let leaf = include_bytes!("../fixtures/certifi-leaf.crt");
        let first_inter = include_bytes!("../fixtures/certifi-first-intermediate.crt");
        let second_inter = include_bytes!("../fixtures/certifi-second-intermediate.crt");

        vec![leaf, first_inter, second_inter]
    }

    #[test]
    fn can_validate_good_chain() {
        let chain = certifi_chain();
        let valid = validate_cert_chain(chain, "certifi.io");
        assert_eq!(valid, true);
    }

    #[test]
    fn fails_on_bad_hostname() {
        let chain = certifi_chain();
        let valid = validate_cert_chain(chain, "lukasa.co.uk");
        assert_eq!(valid, false);
    }
}
<commit_msg>Test invalid certificate files.<commit_after>extern crate libc;
extern crate core_foundation;
extern crate security_framework;

macro_rules! fail_on_error {
    ($e:expr) => {
        match $e {
            Ok(s) => s,
            Err(_) => return false,
        }
    }
}

pub mod os_x {
    use security_framework::certificate::SecCertificate;
    use security_framework::policy::SecPolicy;
    use security_framework::secure_transport::ProtocolSide;
    use security_framework::trust::SecTrust;

    pub fn validate_cert_chain(encoded_certs: Vec<&[u8]>, hostname: &str) -> bool {
        let mut certs = Vec::new();
        for encoded_cert in encoded_certs {
            let cert = SecCertificate::from_der(encoded_cert);
            match cert {
                Ok(cert) => certs.push(cert),
                Err(_) => return false,
            }
        }

        let ssl_policy = fail_on_error!(SecPolicy::for_ssl(ProtocolSide::Client, hostname));
        let trust = fail_on_error!(SecTrust::create_with_certificates(&certs[..], &[ssl_policy]));

        // Deliberately swallow errors here: any error is likely to do with the
        // hostname or cert chain, and if those are invalid then by definition the
        // cert does not validate.
        match trust.evaluate() {
            Ok(result) => result.success(),
            Err(_) => false
        }
    }
}

#[cfg(test)]
mod test {
    use os_x::validate_cert_chain;

    fn certifi_chain() -> Vec<&'static[u8]> {
        let leaf = include_bytes!("../fixtures/certifi-leaf.crt");
        let first_inter = include_bytes!("../fixtures/certifi-first-intermediate.crt");
        let second_inter = include_bytes!("../fixtures/certifi-second-intermediate.crt");

        vec![leaf, first_inter, second_inter]
    }

    #[test]
    fn can_validate_good_chain() {
        let chain = certifi_chain();
        let valid = validate_cert_chain(chain, "certifi.io");
        assert_eq!(valid, true);
    }

    #[test]
    fn fails_on_bad_hostname() {
        let chain = certifi_chain();
        let valid = validate_cert_chain(chain, "lukasa.co.uk");
        assert_eq!(valid, false);
    }

    #[test]
    fn fails_on_bad_cert() {
        let mut good_chain = certifi_chain();
        let originals = good_chain.split_first_mut().unwrap();
        let leaf = originals.0;
        let intermediates = originals.1;

        // Deliberately truncate the leaf cert.
        let mut certs = vec![&leaf[1..50]];
        certs.extend(intermediates.iter());
        let valid = validate_cert_chain(certs, "certifi.io");
        assert_eq!(valid, false);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Itoa Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_root_url = "https://docs.rs/itoa/0.3.4")]

#![cfg_attr(feature = "i128", feature(i128_type, i128))]

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, unreadable_literal))]

#[cfg(feature = "i128")]
mod udiv128;

use std::{io, mem, ptr, slice};

#[inline]
pub fn write<W: io::Write, V: Integer>(wr: W, value: V) -> io::Result<usize> {
    value.write(wr)
}

pub trait Integer {
    fn write<W: io::Write>(self, W) -> io::Result<usize>;
}

trait IntegerPrivate {
    fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8];
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

const MAX_LEN: usize = 40; // i128::MIN (including minus sign)

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_IntegerCommon {
    ($t:ident) => {
        impl Integer for $t {
            fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
                let mut buf = unsafe { mem::uninitialized() };
                let bytes = self.write_to(&mut buf);
                try!(wr.write_all(bytes));
                Ok(bytes.len())
            }
        }
    };
}

macro_rules! impl_Integer {
    ($($t:ident),* as $conv_fn:ident) => {$(
        impl_IntegerCommon!($t);

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let mut n = if is_nonnegative {
                    self as $conv_fn
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as $conv_fn)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();
                let lut_ptr = DEC_DIGITS_LUT.as_ptr();

                unsafe {
                    // need at least 16 bits for the 4-characters-at-a-time to work.
                    if mem::size_of::<$t>() >= 2 {
                        // eagerly decode 4 characters at a time
                        while n >= 10000 {
                            let rem = (n % 10000) as isize;
                            n /= 10000;

                            let d1 = (rem / 100) << 1;
                            let d2 = (rem % 100) << 1;
                            curr -= 4;
                            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                            ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                        }
                    }

                    // if we reach here numbers are <= 9999, so at most 4 chars long
                    let mut n = n as isize; // possibly reduce 64bit math

                    // decode 2 more chars, if > 2 chars
                    if n >= 100 {
                        let d1 = (n % 100) << 1;
                        n /= 100;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    // decode last 1 or 2 chars
                    if n < 10 {
                        curr -= 1;
                        *buf_ptr.offset(curr) = (n as u8) + b'0';
                    } else {
                        let d1 = n << 1;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }
                }

                let len = buf.len() - curr as usize;
                unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
            }
        }
    )*};
}

impl_Integer!(i8, u8, i16, u16, i32, u32 as u32);
impl_Integer!(i64, u64 as u64);
#[cfg(target_pointer_width = "16")]
impl_Integer!(isize, usize as u16);
#[cfg(target_pointer_width = "32")]
impl_Integer!(isize, usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(isize, usize as u64);

#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
    ($($t:ident),*) => {$(
        impl_IntegerCommon!($t);

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let n = if is_nonnegative {
                    self as u128
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as u128)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();

                unsafe {
                    // Divide by 10^19 which is the highest power less than 2^64.
                    let (n, rem) = udiv128::udivmod_1e19(n);
                    curr -= rem.write_to(buf).len() as isize;

                    if n != 0 {
                        // Memset the base10 leading zeros of rem.
                        let target = buf.len() as isize - 19;
                        ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                        curr = target;

                        // Divide by 10^19 again.
                        let (n, rem) = udiv128::udivmod_1e19(n);
                        let buf2 = buf_ptr.offset(curr - buf.len() as isize) as *mut _;
                        curr -= rem.write_to(&mut *buf2).len() as isize;

                        if n != 0 {
                            // Memset the leading zeros.
                            let target = buf.len() as isize - 38;
                            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                            curr = target;

                            // There is at most one digit left
                            // because u128::max / 10^19 / 10^19 is 3.
                            curr -= 1;
                            *buf_ptr.offset(curr) = (n as u8) + b'0';
                        }
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }

                    let len = buf.len() - curr as usize;
                    slice::from_raw_parts(buf_ptr.offset(curr), len)
                }
            }
        }
    )*};
}

#[cfg(all(feature = "i128"))]
impl_Integer128!(i128, u128);
<commit_msg>Prevent downstream implementations of the Integer trait<commit_after>// Copyright 2016 Itoa Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_root_url = "https://docs.rs/itoa/0.3.4")]

#![cfg_attr(feature = "i128", feature(i128_type, i128))]

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, unreadable_literal))]

#[cfg(feature = "i128")]
mod udiv128;

use std::{io, mem, ptr, slice};

#[inline]
pub fn write<W: io::Write, V: Integer>(wr: W, value: V) -> io::Result<usize> {
    value.write(wr)
}

// Seal to prevent downstream implementations of the Integer trait.
mod private {
    pub trait Sealed {}
}

pub trait Integer: private::Sealed {
    fn write<W: io::Write>(self, W) -> io::Result<usize>;
}

trait IntegerPrivate {
    fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8];
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

const MAX_LEN: usize = 40; // i128::MIN (including minus sign)

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_IntegerCommon {
    ($t:ident) => {
        impl Integer for $t {
            fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
                let mut buf = unsafe { mem::uninitialized() };
                let bytes = self.write_to(&mut buf);
                try!(wr.write_all(bytes));
                Ok(bytes.len())
            }
        }

        impl private::Sealed for $t {}
    };
}

macro_rules! impl_Integer {
    ($($t:ident),* as $conv_fn:ident) => {$(
        impl_IntegerCommon!($t);

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let mut n = if is_nonnegative {
                    self as $conv_fn
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as $conv_fn)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();
                let lut_ptr = DEC_DIGITS_LUT.as_ptr();

                unsafe {
                    // need at least 16 bits for the 4-characters-at-a-time to work.
                    if mem::size_of::<$t>() >= 2 {
                        // eagerly decode 4 characters at a time
                        while n >= 10000 {
                            let rem = (n % 10000) as isize;
                            n /= 10000;

                            let d1 = (rem / 100) << 1;
                            let d2 = (rem % 100) << 1;
                            curr -= 4;
                            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                            ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                        }
                    }

                    // if we reach here numbers are <= 9999, so at most 4 chars long
                    let mut n = n as isize; // possibly reduce 64bit math

                    // decode 2 more chars, if > 2 chars
                    if n >= 100 {
                        let d1 = (n % 100) << 1;
                        n /= 100;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    // decode last 1 or 2 chars
                    if n < 10 {
                        curr -= 1;
                        *buf_ptr.offset(curr) = (n as u8) + b'0';
                    } else {
                        let d1 = n << 1;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }
                }

                let len = buf.len() - curr as usize;
                unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
            }
        }
    )*};
}

impl_Integer!(i8, u8, i16, u16, i32, u32 as u32);
impl_Integer!(i64, u64 as u64);
#[cfg(target_pointer_width = "16")]
impl_Integer!(isize, usize as u16);
#[cfg(target_pointer_width = "32")]
impl_Integer!(isize, usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(isize, usize as u64);

#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
    ($($t:ident),*) => {$(
        impl_IntegerCommon!($t);

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let n = if is_nonnegative {
                    self as u128
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as u128)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();

                unsafe {
                    // Divide by 10^19 which is the highest power less than 2^64.
                    let (n, rem) = udiv128::udivmod_1e19(n);
                    curr -= rem.write_to(buf).len() as isize;

                    if n != 0 {
                        // Memset the base10 leading zeros of rem.
                        let target = buf.len() as isize - 19;
                        ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                        curr = target;

                        // Divide by 10^19 again.
                        let (n, rem) = udiv128::udivmod_1e19(n);
                        let buf2 = buf_ptr.offset(curr - buf.len() as isize) as *mut _;
                        curr -= rem.write_to(&mut *buf2).len() as isize;

                        if n != 0 {
                            // Memset the leading zeros.
                            let target = buf.len() as isize - 38;
                            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                            curr = target;

                            // There is at most one digit left
                            // because u128::max / 10^19 / 10^19 is 3.
                            curr -= 1;
                            *buf_ptr.offset(curr) = (n as u8) + b'0';
                        }
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }

                    let len = buf.len() - curr as usize;
                    slice::from_raw_parts(buf_ptr.offset(curr), len)
                }
            }
        }
    )*};
}

#[cfg(all(feature = "i128"))]
impl_Integer128!(i128, u128);
<|endoftext|>