<commit_before>#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![cfg_attr(test, deny(warnings))]
#![doc(html_root_url = "https://docs.rs/reqwest/0.10.0-alpha.1")]

//! # reqwest
//!
//! The `reqwest` crate provides a convenient, higher-level HTTP
//! [`Client`][client].
//!
//! It handles many of the things that most people just expect an HTTP client
//! to do for them.
//!
//! - Async and [blocking](blocking) Clients
//! - Plain bodies, [JSON](#json), [urlencoded](#forms), [multipart](multipart)
//! - Customizable [redirect policy](#redirect-policy)
//! - HTTP [Proxies](#proxies)
//! - Uses system-native [TLS](#tls)
//! - Cookies
//!
//! The [`reqwest::Client`][client] is asynchronous. For applications wishing
//! to only make a few HTTP requests, the [`reqwest::blocking`](blocking) API
//! may be more convenient.
//!
//! Additional learning resources include:
//!
//! - [The Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/web/clients.html)
//! - [Reqwest Repository Examples](https://github.com/seanmonstar/reqwest/tree/master/examples)
//!
//! ## Making a GET request
//!
//! For a single request, you can use the [`get`][get] shortcut method.
//!
//! ```rust
//! # async fn run() -> Result<(), reqwest::Error> {
//! let body = reqwest::get("https://www.rust-lang.org")
//!     .await?
//!     .text()
//!     .await?;
//!
//! println!("body = {:?}", body);
//! # Ok(())
//! # }
//! ```
//!
//! **NOTE**: If you plan to perform multiple requests, it is best to create a
//! [`Client`][client] and reuse it, taking advantage of keep-alive connection
//! pooling.
//!
//! ## Making POST requests (or setting request bodies)
//!
//! There are several ways you can set the body of a request. The basic one is
//! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the
//! exact raw bytes of what the body should be. It accepts various types,
//! including `String`, `Vec<u8>`, and `File`. If you wish to pass a custom
//! type, you can use the `reqwest::Body` constructors.
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # async fn run() -> Result<(), Error> {
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .body("the exact body that is sent")
//!     .send()
//!     .await?;
//! # Ok(())
//! # }
//! ```
//!
//! ### Forms
//!
//! It's very common to want to send form data in a request body. This can be
//! done with any type that can be serialized into form data.
//!
//! This can be an array of tuples, or a `HashMap`, or a custom type that
//! implements [`Serialize`][serde].
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # async fn run() -> Result<(), Error> {
//! // This will POST a body of `foo=bar&baz=quux`
//! let params = [("foo", "bar"), ("baz", "quux")];
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .form(&params)
//!     .send()
//!     .await?;
//! # Ok(())
//! # }
//! ```
//!
//! ### JSON
//!
//! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in
//! a similar fashion the `form` method. It can take any value that can be
//! serialized into JSON. The feature `json` is required.
//!
//! ```rust
//! # use reqwest::Error;
//! # use std::collections::HashMap;
//! #
//! # #[cfg(feature = "json")]
//! # async fn run() -> Result<(), Error> {
//! // This will POST a body of `{"lang":"rust","body":"json"}`
//! let mut map = HashMap::new();
//! map.insert("lang", "rust");
//! map.insert("body", "json");
//!
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .json(&map)
//!     .send()
//!     .await?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Redirect Policies
//!
//! By default, a `Client` will automatically handle HTTP redirects, detecting
//! loops, and having a maximum redirect chain of 10 hops. To customize this
//! behavior, a [`RedirectPolicy`][redirect] can used with a `ClientBuilder`.
//!
//! ## Cookies
//!
//! The automatic storing and sending of session cookies can be enabled with
//! the [`cookie_store`][ClientBuilder::cookie_store] method on `ClientBuilder`.
//!
//! ## Proxies
//!
//! ** NOTE ** Proxies are enabled by default.
//!
//! System proxies look in environment variables to set HTTP or HTTPS proxies.
//!
//! `HTTP_PROXY` or `http_proxy` provide http proxies for http connections while
//! `HTTPS_PROXY` or `https_proxy` provide HTTPS proxies for HTTPS connections.
//!
//! These can be overwritten by adding a [`Proxy`](Proxy) to `ClientBuilder`
//! i.e. `let proxy = reqwest::Proxy::http("https://secure.example")?;`
//! or disabled by calling `ClientBuilder::no_proxy()`.
//!
//! ## TLS
//!
//! By default, a `Client` will make use of system-native transport layer
//! security to connect to HTTPS destinations. This means schannel on Windows,
//! Security-Framework on macOS, and OpenSSL on Linux.
//!
//! - Additional X509 certificates can be configured on a `ClientBuilder` with the
//!   [`Certificate`](Certificate) type.
//! - Client certificates can be add to a `ClientBuilder` with the
//!   [`Identity`][Identity] type.
//! - Various parts of TLS can also be configured or even disabled on the
//!   `ClientBuilder`.
//!
//! ## Optional Features
//!
//! The following are a list of [Cargo features][cargo-features] that can be
//! enabled or disabled:
//!
//! - **default-tls** *(enabled by default)*: Provides TLS support via the
//!   `native-tls` library to connect over HTTPS.
//! - **default-tls-vendored**: Enables the `vendored` feature of `native-tls`.
//! - **blocking**: Provides the [blocking][] client API.
//! - **cookies**: Provides cookie session support.
//! - **gzip**: Provides response body gzip decompression.
//! - **json**: Provides serialization and deserialization for JSON bodies.
//! - **unstable-stream** *(unstable)*: Adds support for `futures::Stream`.
//!
//!
//! [hyper]: http://hyper.rs
//! [client]: ./struct.Client.html
//! [response]: ./struct.Response.html
//! [get]: ./fn.get.html
//! [builder]: ./struct.RequestBuilder.html
//! [serde]: http://serde.rs
//! [redirect]: ./struct.RedirectPolicy.html
//! [Proxy]: ./struct.Proxy.html
//! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section

////! - **rustls-tls**: Provides TLS support via the `rustls` library.
////! - **socks**: Provides SOCKS5 proxy support.
////! - **trust-dns**: Enables a trust-dns async resolver instead of default
////!   threadpool using `getaddrinfo`.

macro_rules! if_wasm {
    ($($item:item)*) => {$(
        #[cfg(target_arch = "wasm32")]
        $item
    )*}
}

macro_rules! if_hyper {
    ($($item:item)*) => {$(
        #[cfg(not(target_arch = "wasm32"))]
        $item
    )*}
}

pub use http::header;
pub use http::Method;
pub use http::{StatusCode, Version};
pub use url::Url;

// universal mods
#[macro_use]
mod error;
mod into_url;

pub use self::error::{Error, Result};
pub use self::into_url::IntoUrl;

/// Shortcut method to quickly make a `GET` request.
///
/// See also the methods on the [`reqwest::Response`](./struct.Response.html)
/// type.
///
/// **NOTE**: This function creates a new internal `Client` on each call,
/// and so should not be used if making many requests. Create a
/// [`Client`](./struct.Client.html) instead.
///
/// # Examples
///
/// ```rust
/// # async fn run() -> Result<(), reqwest::Error> {
/// let body = reqwest::get("https://www.rust-lang.org").await?
///     .text().await?;
/// # Ok(())
/// # }
/// ```
///
/// # Errors
///
/// This function fails if:
///
/// - native TLS backend cannot be initialized
/// - supplied `Url` cannot be parsed
/// - there was an error while sending request
/// - redirect loop was detected
/// - redirect limit was exhausted
pub async fn get<T: IntoUrl>(url: T) -> crate::Result<Response> {
    Client::builder().build()?.get(url).send().await
}

fn _assert_impls() {
    fn assert_send<T: Send>() {}
    fn assert_sync<T: Sync>() {}
    fn assert_clone<T: Clone>() {}

    assert_send::<Client>();
    assert_sync::<Client>();
    assert_clone::<Client>();

    assert_send::<Request>();
    assert_send::<RequestBuilder>();

    #[cfg(not(target_arch = "wasm32"))]
    {
        assert_send::<Response>();
    }

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

if_hyper! {
    #[cfg(test)]
    #[macro_use]
    extern crate doc_comment;

    #[macro_use]
    extern crate lazy_static;

    #[cfg(test)]
    doctest!("../README.md");

    pub use self::async_impl::{
        multipart, Body, Client, ClientBuilder, Request, RequestBuilder, Response,
    };
    pub use self::proxy::Proxy;
    pub use self::redirect::{RedirectAction, RedirectAttempt, RedirectPolicy};
    #[cfg(feature = "tls")]
    pub use self::tls::{Certificate, Identity};

    mod async_impl;
    #[cfg(feature = "blocking")]
    pub mod blocking;
    mod connect;
    #[cfg(feature = "cookies")]
    pub mod cookie;
    //#[cfg(feature = "trust-dns")]
    //mod dns;
    mod proxy;
    mod redirect;
    #[cfg(feature = "tls")]
    mod tls;

    #[doc(hidden)]
    #[deprecated(note = "types moved to top of crate")]
    pub mod r#async {
        pub use crate::async_impl::{
            multipart, Body, Client, ClientBuilder, Request, RequestBuilder, Response,
        };
    }
}

if_wasm! {
    mod wasm;

    pub use self::wasm::{Body, Client, ClientBuilder, Request, RequestBuilder, Response};
}
<commit_msg>Fix a link in doc (#706)<commit_after>#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![cfg_attr(test, deny(warnings))]
#![doc(html_root_url = "https://docs.rs/reqwest/0.10.0-alpha.1")]

//! # reqwest
//!
//! The `reqwest` crate provides a convenient, higher-level HTTP
//! [`Client`][client].
//!
//! It handles many of the things that most people just expect an HTTP client
//! to do for them.
//!
//! - Async and [blocking](blocking) Clients
//! - Plain bodies, [JSON](#json), [urlencoded](#forms), [multipart](multipart)
//! - Customizable [redirect policy](#redirect-policies)
//! - HTTP [Proxies](#proxies)
//! - Uses system-native [TLS](#tls)
//! - Cookies
//!
//! The [`reqwest::Client`][client] is asynchronous. For applications wishing
//! to only make a few HTTP requests, the [`reqwest::blocking`](blocking) API
//! may be more convenient.
//!
//! Additional learning resources include:
//!
//! - [The Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/web/clients.html)
//! - [Reqwest Repository Examples](https://github.com/seanmonstar/reqwest/tree/master/examples)
//!
//! ## Making a GET request
//!
//! For a single request, you can use the [`get`][get] shortcut method.
//!
//! ```rust
//! # async fn run() -> Result<(), reqwest::Error> {
//! let body = reqwest::get("https://www.rust-lang.org")
//!     .await?
//!     .text()
//!     .await?;
//!
//! println!("body = {:?}", body);
//! # Ok(())
//! # }
//! ```
//!
//! **NOTE**: If you plan to perform multiple requests, it is best to create a
//! [`Client`][client] and reuse it, taking advantage of keep-alive connection
//! pooling.
//!
//! ## Making POST requests (or setting request bodies)
//!
//! There are several ways you can set the body of a request. The basic one is
//! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the
//! exact raw bytes of what the body should be. It accepts various types,
//! including `String`, `Vec<u8>`, and `File`. If you wish to pass a custom
//! type, you can use the `reqwest::Body` constructors.
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # async fn run() -> Result<(), Error> {
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .body("the exact body that is sent")
//!     .send()
//!     .await?;
//! # Ok(())
//! # }
//! ```
//!
//! ### Forms
//!
//! It's very common to want to send form data in a request body. This can be
//! done with any type that can be serialized into form data.
//!
//! This can be an array of tuples, or a `HashMap`, or a custom type that
//! implements [`Serialize`][serde].
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # async fn run() -> Result<(), Error> {
//! // This will POST a body of `foo=bar&baz=quux`
//! let params = [("foo", "bar"), ("baz", "quux")];
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .form(&params)
//!     .send()
//!     .await?;
//! # Ok(())
//! # }
//! ```
//!
//! ### JSON
//!
//! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in
//! a similar fashion the `form` method. It can take any value that can be
//! serialized into JSON. The feature `json` is required.
//!
//! ```rust
//! # use reqwest::Error;
//! # use std::collections::HashMap;
//! #
//! # #[cfg(feature = "json")]
//! # async fn run() -> Result<(), Error> {
//! // This will POST a body of `{"lang":"rust","body":"json"}`
//! let mut map = HashMap::new();
//! map.insert("lang", "rust");
//! map.insert("body", "json");
//!
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .json(&map)
//!     .send()
//!     .await?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Redirect Policies
//!
//! By default, a `Client` will automatically handle HTTP redirects, detecting
//! loops, and having a maximum redirect chain of 10 hops. To customize this
//! behavior, a [`RedirectPolicy`][redirect] can used with a `ClientBuilder`.
//!
//! ## Cookies
//!
//! The automatic storing and sending of session cookies can be enabled with
//! the [`cookie_store`][ClientBuilder::cookie_store] method on `ClientBuilder`.
//!
//! ## Proxies
//!
//! ** NOTE ** Proxies are enabled by default.
//!
//! System proxies look in environment variables to set HTTP or HTTPS proxies.
//!
//! `HTTP_PROXY` or `http_proxy` provide http proxies for http connections while
//! `HTTPS_PROXY` or `https_proxy` provide HTTPS proxies for HTTPS connections.
//!
//! These can be overwritten by adding a [`Proxy`](Proxy) to `ClientBuilder`
//! i.e. `let proxy = reqwest::Proxy::http("https://secure.example")?;`
//! or disabled by calling `ClientBuilder::no_proxy()`.
//!
//! ## TLS
//!
//! By default, a `Client` will make use of system-native transport layer
//! security to connect to HTTPS destinations. This means schannel on Windows,
//! Security-Framework on macOS, and OpenSSL on Linux.
//!
//! - Additional X509 certificates can be configured on a `ClientBuilder` with the
//!   [`Certificate`](Certificate) type.
//! - Client certificates can be add to a `ClientBuilder` with the
//!   [`Identity`][Identity] type.
//! - Various parts of TLS can also be configured or even disabled on the
//!   `ClientBuilder`.
//!
//! ## Optional Features
//!
//! The following are a list of [Cargo features][cargo-features] that can be
//! enabled or disabled:
//!
//! - **default-tls** *(enabled by default)*: Provides TLS support via the
//!   `native-tls` library to connect over HTTPS.
//! - **default-tls-vendored**: Enables the `vendored` feature of `native-tls`.
//! - **blocking**: Provides the [blocking][] client API.
//! - **cookies**: Provides cookie session support.
//! - **gzip**: Provides response body gzip decompression.
//! - **json**: Provides serialization and deserialization for JSON bodies.
//! - **unstable-stream** *(unstable)*: Adds support for `futures::Stream`.
//!
//!
//! [hyper]: http://hyper.rs
//! [client]: ./struct.Client.html
//! [response]: ./struct.Response.html
//! [get]: ./fn.get.html
//! [builder]: ./struct.RequestBuilder.html
//! [serde]: http://serde.rs
//! [redirect]: ./struct.RedirectPolicy.html
//! [Proxy]: ./struct.Proxy.html
//! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section

////! - **rustls-tls**: Provides TLS support via the `rustls` library.
////! - **socks**: Provides SOCKS5 proxy support.
////! - **trust-dns**: Enables a trust-dns async resolver instead of default
////!   threadpool using `getaddrinfo`.

macro_rules! if_wasm {
    ($($item:item)*) => {$(
        #[cfg(target_arch = "wasm32")]
        $item
    )*}
}

macro_rules! if_hyper {
    ($($item:item)*) => {$(
        #[cfg(not(target_arch = "wasm32"))]
        $item
    )*}
}

pub use http::header;
pub use http::Method;
pub use http::{StatusCode, Version};
pub use url::Url;

// universal mods
#[macro_use]
mod error;
mod into_url;

pub use self::error::{Error, Result};
pub use self::into_url::IntoUrl;

/// Shortcut method to quickly make a `GET` request.
///
/// See also the methods on the [`reqwest::Response`](./struct.Response.html)
/// type.
///
/// **NOTE**: This function creates a new internal `Client` on each call,
/// and so should not be used if making many requests. Create a
/// [`Client`](./struct.Client.html) instead.
///
/// # Examples
///
/// ```rust
/// # async fn run() -> Result<(), reqwest::Error> {
/// let body = reqwest::get("https://www.rust-lang.org").await?
///     .text().await?;
/// # Ok(())
/// # }
/// ```
///
/// # Errors
///
/// This function fails if:
///
/// - native TLS backend cannot be initialized
/// - supplied `Url` cannot be parsed
/// - there was an error while sending request
/// - redirect loop was detected
/// - redirect limit was exhausted
pub async fn get<T: IntoUrl>(url: T) -> crate::Result<Response> {
    Client::builder().build()?.get(url).send().await
}

fn _assert_impls() {
    fn assert_send<T: Send>() {}
    fn assert_sync<T: Sync>() {}
    fn assert_clone<T: Clone>() {}

    assert_send::<Client>();
    assert_sync::<Client>();
    assert_clone::<Client>();

    assert_send::<Request>();
    assert_send::<RequestBuilder>();

    #[cfg(not(target_arch = "wasm32"))]
    {
        assert_send::<Response>();
    }

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

if_hyper! {
    #[cfg(test)]
    #[macro_use]
    extern crate doc_comment;

    #[macro_use]
    extern crate lazy_static;

    #[cfg(test)]
    doctest!("../README.md");

    pub use self::async_impl::{
        multipart, Body, Client, ClientBuilder, Request, RequestBuilder, Response,
    };
    pub use self::proxy::Proxy;
    pub use self::redirect::{RedirectAction, RedirectAttempt, RedirectPolicy};
    #[cfg(feature = "tls")]
    pub use self::tls::{Certificate, Identity};

    mod async_impl;
    #[cfg(feature = "blocking")]
    pub mod blocking;
    mod connect;
    #[cfg(feature = "cookies")]
    pub mod cookie;
    //#[cfg(feature = "trust-dns")]
    //mod dns;
    mod proxy;
    mod redirect;
    #[cfg(feature = "tls")]
    mod tls;

    #[doc(hidden)]
    #[deprecated(note = "types moved to top of crate")]
    pub mod r#async {
        pub use crate::async_impl::{
            multipart, Body, Client, ClientBuilder, Request, RequestBuilder, Response,
        };
    }
}

if_wasm! {
    mod wasm;

    pub use self::wasm::{Body, Client, ClientBuilder, Request, RequestBuilder, Response};
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! `manticore` is a partial implementation of the [Cerberus] attestation
//! protocol for Root of Trust devices.
//!
//! Throughout the documentation of this crate, we use "Cerberus" to refer to
//! the specification as published. `manticore` is not a complete
//! implementation, and we take care to point out where it varies from
//! Cerberus.
//!
//! For example, protocol ["commands"](protocol/trait.Command.html) are a
//! Cerberus concept, although `manticore` adds its own (very clearly labeled)
//! commands. The [FPM](manifest/fpm/index.html) is a `manticore`-specific
//! concept, on the other hand, although it is derived from the Cerberus PFM.
//!
//! `manticore` also does not use MCTP, unlike Cerberus. Instead, `manticore`
//! abstracts away the packet layer in terms of sized buffers, so that it can
//! be used with any packet layer, such as MCTP, TCP, or ring-buffer IPC. See
//! the [`protocol` module] for more details.
//!
//! [Cerberus]:
//!   https://github.com/opencomputeproject/Project_Olympus/tree/master/Project_Cerberus
//! [`protocol` module]: protocol/index.html

#![cfg_attr(not(feature = "std"), no_std)]
#![deny(missing_docs)]
#![deny(warnings)]
#![deny(unused)]
#![deny(unsafe_code)]

#[macro_use]
pub mod protocol;

pub mod crypto;
pub mod hardware;
pub mod io;
pub mod manifest;
pub mod server;
<commit_msg>[cargo] Document Cargo features in lib.rs<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! `manticore` is a partial implementation of the [Cerberus] attestation
//! protocol for Root of Trust devices.
//!
//! Throughout the documentation of this crate, we use "Cerberus" to refer to
//! the specification as published. `manticore` is not a complete
//! implementation, and we take care to point out where it varies from
//! Cerberus.
//!
//! For example, protocol ["commands"](protocol/trait.Command.html) are a
//! Cerberus concept, although `manticore` adds its own (very clearly labeled)
//! commands. The [FPM](manifest/fpm/index.html) is a `manticore`-specific
//! concept, on the other hand, although it is derived from the Cerberus PFM.
//!
//! `manticore` also does not use MCTP, unlike Cerberus. Instead, `manticore`
//! abstracts away the packet layer in terms of sized buffers, so that it can
//! be used with any packet layer, such as MCTP, TCP, or ring-buffer IPC. See
//! the [`protocol` module] for more details.
//!
//! # Feature flags
//!
//! `manticore` provides a number of optional features that can be controlled
//! through feature flags:
//! - `std` (default) pulls in the full Rust standard library. This is
//!   not necessary for any on-device use-cases, but is available for using
//!   `manticore` as a library for talking to Cerberus devices.
//! - `ring` (default) enables the [`crypto::ring` module], which provides
//!   software implementations for cryptography traits used by `manticore`.
//!   This feature is not intended for on-device use-cases either.
//! - `serde` enables implementations of `serde`'s (de)serialization traits.
//! - `arbitrary-derive` enables implementations of fuzz-testing-related
//!   traits.
//!
//! [Cerberus]:
//!   https://github.com/opencomputeproject/Project_Olympus/tree/master/Project_Cerberus
//! [`protocol` module]: protocol/index.html
//! [`crypto::ring` module]: crypto/ring/index.html

#![cfg_attr(not(feature = "std"), no_std)]
#![deny(missing_docs)]
#![deny(warnings)]
#![deny(unused)]
#![deny(unsafe_code)]

#[macro_use]
pub mod protocol;

pub mod crypto;
pub mod hardware;
pub mod io;
pub mod manifest;
pub mod server;
<|endoftext|>


<commit_before>extern crate lmdb_rs as lmdb;

use lmdb::{FromMdbValue, ToMdbValue};
use lmdb::core::{MdbResult, Transaction};
use std::marker::PhantomData;

pub trait Tablename {
    fn as_str() -> &'static str;
}

pub trait IsNativeInt {}
impl IsNativeInt for i32 {}
impl IsNativeInt for u32 {}
impl IsNativeInt for i64 {}
impl IsNativeInt for u64 {}

/// A table that maps an integer to a set of integers.
/// Keys K1 and K2 must be native integers!
#[derive(Clone)]
pub struct IntToIntsTable<K1, K2, T> {
    pub db: lmdb::DbHandle,
    _k1: PhantomData<K1>,
    _k2: PhantomData<K2>,
    _t: PhantomData<T>,
}

/// A table that maps an integer to a blob.
#[derive(Clone)]
pub struct IntToBlobTable<K, T> {
    pub db: lmdb::DbHandle,
    _k: PhantomData<K>,
    _t: PhantomData<T>,
}

/// A table that maps an object of type `K` to a blob.
#[derive(Clone)]
pub struct KeyToBlobTable<K, T> {
    pub db: lmdb::DbHandle,
    _k: PhantomData<K>,
    _t: PhantomData<T>,
}

/// A table that maps an integer to a record/struct.
#[derive(Clone)]
pub struct IntToRecordTable<K, V, T> {
    pub db: lmdb::DbHandle,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
    _t: PhantomData<T>,
}

/// Bound IntToRecordTable.
pub struct BoundIntToRecordTable<'a, K, V, T> {
    db: lmdb::Database<'a>,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
    _t: PhantomData<T>,
}

/* Implementations */

impl<K1, K2, T> IntToIntsTable<K1, K2, T>
where K1: Sized + ToMdbValue + IsNativeInt + FromMdbValue,
      K2: Sized + ToMdbValue + IsNativeInt,
      T: Tablename
{
    fn flags() -> lmdb::core::DbFlags {
        lmdb::core::DbIntKey |
        lmdb::core::DbAllowDups | lmdb::core::DbAllowIntDups |
        lmdb::core::DbDupFixed
    }

    pub fn create(env: &lmdb::Environment) -> IntToIntsTable<K1, K2, T> {
        IntToIntsTable::new_from_handle(env.create_db(T::as_str(), Self::flags()).unwrap())
    }

    pub fn open(env: &lmdb::Environment) -> IntToIntsTable<K1, K2, T> {
        IntToIntsTable::new_from_handle(env.get_db(T::as_str(), Self::flags()).unwrap())
    }

    fn new_from_handle(db: lmdb::DbHandle) -> IntToIntsTable<K1, K2, T> {
        IntToIntsTable {db: db, _k1: PhantomData, _k2: PhantomData, _t: PhantomData}
    }

    // XXX: Can we optimize this, when iter is already sorted for example?
    pub fn insert_multiple<I>(&self, txn: &Transaction, iter: I) -> MdbResult<()> where I: Iterator<Item=(K1,K2)> {
        let db = txn.bind(&self.db);
        for (ref k1, ref k2) in iter {
            try!(db.set(k1, k2));
        }
        Ok(())
    }

    pub fn insert(&self, txn: &Transaction, kv: &(K1, K2)) -> MdbResult<()> {
        let db = txn.bind(&self.db);
        db.set(&kv.0, &kv.1)
    }

    fn last_key(&self, txn: &lmdb::core::ReadonlyTransaction) -> MdbResult<K1> {
        let db = txn.bind(&self.db);
        let mut cursor = try!(db.new_cursor());
        try!(cursor.to_last());
        cursor.get_key()
    }
}

impl<K, T> IntToBlobTable<K, T>
where K: Sized + ToMdbValue + IsNativeInt,
      T: Tablename
{
    fn flags() -> lmdb::core::DbFlags {
        lmdb::core::DbIntKey
    }

    pub fn create(env: &lmdb::Environment) -> IntToBlobTable<K, T> {
        IntToBlobTable::new_from_handle(env.create_db(T::as_str(), Self::flags()).unwrap())
    }

    pub fn open(env: &lmdb::Environment) -> IntToBlobTable<K, T> {
        IntToBlobTable::new_from_handle(env.get_db(T::as_str(), Self::flags()).unwrap())
    }

    fn new_from_handle(db: lmdb::DbHandle) -> IntToBlobTable<K, T> {
        IntToBlobTable {db: db, _k: PhantomData, _t: PhantomData}
    }

    pub fn insert(&self, txn: &Transaction, key: &K, val: &[u8]) -> MdbResult<()> {
        let db = txn.bind(&self.db);
        db.insert(key, &val)
    }

    // fn lookup
}

impl<K, T> KeyToBlobTable<K, T>
where K: Sized + ToMdbValue,
      T: Tablename
{
    fn flags() -> lmdb::core::DbFlags {
        lmdb::core::DbFlags::empty()
    }

    pub fn create(env: &lmdb::Environment) -> KeyToBlobTable<K, T> {
        KeyToBlobTable::new_from_handle(env.create_db(T::as_str(), Self::flags()).unwrap())
    }

    pub fn open(env: &lmdb::Environment) -> KeyToBlobTable<K, T> {
        KeyToBlobTable::new_from_handle(env.get_db(T::as_str(), Self::flags()).unwrap())
    }

    fn new_from_handle(db: lmdb::DbHandle) -> KeyToBlobTable<K, T> {
        KeyToBlobTable {db: db, _k: PhantomData, _t: PhantomData}
    }

    pub fn insert(&self, txn: &Transaction, key: &K, val: &[u8]) -> MdbResult<()> {
        let db = txn.bind(&self.db);
        db.insert(key, &val)
    }

    // fn lookup
}

//
// A unique(native-int) -> sized record value lookup table
//

impl<K, V, T> IntToRecordTable<K, V, T>
where K: Sized + ToMdbValue + IsNativeInt,
      V: Sized + ToMdbValue + FromMdbValue,
      T: Tablename
{
    fn flags() -> lmdb::core::DbFlags {
        lmdb::core::DbIntKey
    }

    pub fn create(env: &lmdb::Environment) -> IntToRecordTable<K, V, T> {
        IntToRecordTable::new_from_handle(env.create_db(T::as_str(), Self::flags()).unwrap())
    }

    pub fn open(env: &lmdb::Environment) -> IntToRecordTable<K, V, T> {
        IntToRecordTable::new_from_handle(env.get_db(T::as_str(), Self::flags()).unwrap())
    }

    fn new_from_handle(db: lmdb::DbHandle) -> IntToRecordTable<K, V, T> {
        IntToRecordTable {db: db, _k: PhantomData, _v: PhantomData, _t: PhantomData}
    }

    pub fn bind_to_txn<'a>(&self, txn: &'a lmdb::Transaction) -> BoundIntToRecordTable<'a, K, V, T> {
        BoundIntToRecordTable {
            db: txn.bind(&self.db),
            _k: PhantomData, _v: PhantomData, _t: PhantomData}
    }

    pub fn bind_to_ro_txn<'a>(&self, txn: &'a lmdb::ReadonlyTransaction) -> BoundIntToRecordTable<'a, K, V, T> {
        BoundIntToRecordTable {
            db: txn.bind(&self.db),
            _k: PhantomData, _v: PhantomData, _t: PhantomData}
    }
}

impl<'a, K, V, T> BoundIntToRecordTable<'a, K, V, T>
where K: Sized + ToMdbValue + IsNativeInt,
      V: Sized + ToMdbValue + FromMdbValue,
      T: Tablename
{
    // fails if key exists.
    pub fn insert(&self, key: &K, val: &V) -> MdbResult<()> {
        self.db.insert(key, val)
    }

    // XXX: Should go into ReadonlyBound...
    pub fn lookup(&self, key: &K) -> MdbResult<V> {
        self.db.get::<V>(key)
    }

    pub fn update<F>(&self, key: &K, update: F) -> MdbResult<()>
        where F: Fn(&mut V) -> bool {

        let mut cursor = try!(self.db.new_cursor());
        try!(cursor.to_key(key));

        let mut value: V = try!(cursor.get_value());

        let needs_update = update(&mut value);

        if needs_update {
            try!(cursor.replace(&value));
        }

        Ok(())
    }

    pub fn insert_or_update<N, F>(&self, key: &K, insert_fn: N, update_fn: F) -> MdbResult<()>
        where
                N: Fn() -> V,
                F: Fn(&mut V) -> bool {

        // Trying to update first
        {
                let mut cursor = try!(self.db.new_cursor());
                if let Ok(_) = cursor.to_key(key) {
                        let mut value: V = try!(cursor.get_value());
                        let needs_update = update_fn(&mut value);
                        if needs_update {
                                try!(cursor.replace(&value));
                        }
                        return Ok(());
                }
        }

        // Now try to insert
        {
            let value: V = insert_fn();
            try!(self.db.insert(key, &value));
            return Ok(());
        }
    }

    pub fn insert_or_update_default<F>(&self, key: &K, update_fn: F) -> MdbResult<bool>
        where
                V: Default,
                F: Fn(&mut V) -> bool {

        // Trying to update first
        {
                let mut cursor = try!(self.db.new_cursor());
                if let Ok(_) = cursor.to_key(key) {
                        let mut value: V = try!(cursor.get_value());
                        let needs_update = update_fn(&mut value);
                        if needs_update {
                                try!(cursor.replace(&value));
                        }
                        return Ok(needs_update);
                }
        }

        // Now try to insert
        {
            let mut value: V = V::default();
            let needs_update = update_fn(&mut value);
            if needs_update {
                try!(self.db.insert(key, &value));
            }
            return Ok(needs_update);
        }
    }
}
<commit_msg>Add KeyToRecordTable<commit_after>extern crate lmdb_rs as lmdb;

use lmdb::{FromMdbValue, ToMdbValue};
use lmdb::core::{MdbResult, Transaction};
use std::marker::PhantomData;

pub trait Tablename {
    fn as_str() -> &'static str;
}

pub trait IsNativeInt {}
impl IsNativeInt for i32 {}
impl IsNativeInt for u32 {}
impl IsNativeInt for i64 {}
impl IsNativeInt for u64 {}

/// A table that maps an integer to a set of integers.
/// Keys K1 and K2 must be native integers!
#[derive(Clone)]
pub struct IntToIntsTable<K1, K2, T> {
    pub db: lmdb::DbHandle,
    _k1: PhantomData<K1>,
    _k2: PhantomData<K2>,
    _t: PhantomData<T>,
}

/// A table that maps an integer to a blob.
#[derive(Clone)]
pub struct IntToBlobTable<K, T> {
    pub db: lmdb::DbHandle,
    _k: PhantomData<K>,
    _t: PhantomData<T>,
}

/// A table that maps an object of type `K` to a blob.
#[derive(Clone)]
pub struct KeyToBlobTable<K, T> {
    pub db: lmdb::DbHandle,
    _k: PhantomData<K>,
    _t: PhantomData<T>,
}

/// A table that maps an integer to a record/struct.
#[derive(Clone)]
pub struct IntToRecordTable<K, V, T> {
    pub db: lmdb::DbHandle,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
    _t: PhantomData<T>,
}

/// Bound IntToRecordTable.
pub struct BoundIntToRecordTable<'a, K, V, T> {
    db: lmdb::Database<'a>,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
    _t: PhantomData<T>,
}

/// A table that maps an object of type `K` to a record/struct.
#[derive(Clone)]
pub struct KeyToRecordTable<K, V, T> {
    pub db: lmdb::DbHandle,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
    _t: PhantomData<T>,
}

/* Implementations */

impl<K1, K2, T> IntToIntsTable<K1, K2, T>
where K1: Sized + ToMdbValue + IsNativeInt + FromMdbValue,
      K2: Sized + ToMdbValue + IsNativeInt,
      T: Tablename
{
    fn flags() -> lmdb::core::DbFlags {
        lmdb::core::DbIntKey |
        lmdb::core::DbAllowDups | lmdb::core::DbAllowIntDups |
        lmdb::core::DbDupFixed
    }

    pub fn create(env: &lmdb::Environment) -> IntToIntsTable<K1, K2, T> {
        IntToIntsTable::new_from_handle(env.create_db(T::as_str(), Self::flags()).unwrap())
    }

    pub fn open(env: &lmdb::Environment) -> IntToIntsTable<K1, K2, T> {
        IntToIntsTable::new_from_handle(env.get_db(T::as_str(), Self::flags()).unwrap())
    }

    fn new_from_handle(db: lmdb::DbHandle) -> IntToIntsTable<K1, K2, T> {
        IntToIntsTable {db: db, _k1: PhantomData, _k2: PhantomData, _t: PhantomData}
    }

    // XXX: Can we optimize this, when iter is already sorted for example?
    pub fn insert_multiple<I>(&self, txn: &Transaction, iter: I) -> MdbResult<()> where I: Iterator<Item=(K1,K2)> {
        let db = txn.bind(&self.db);
        for (ref k1, ref k2) in iter {
            try!(db.set(k1, k2));
        }
        Ok(())
    }

    pub fn insert(&self, txn: &Transaction, kv: &(K1, K2)) -> MdbResult<()> {
        let db = txn.bind(&self.db);
        db.set(&kv.0, &kv.1)
    }

    fn last_key(&self, txn: &lmdb::core::ReadonlyTransaction) -> MdbResult<K1> {
        let db = txn.bind(&self.db);
        let mut cursor = try!(db.new_cursor());
        try!(cursor.to_last());
        cursor.get_key()
    }
}

impl<K, T> IntToBlobTable<K, T>
where K: Sized + ToMdbValue + IsNativeInt,
      T: Tablename
{
    fn flags() -> lmdb::core::DbFlags {
        lmdb::core::DbIntKey
    }

    pub fn create(env: &lmdb::Environment) -> IntToBlobTable<K, T> {
        IntToBlobTable::new_from_handle(env.create_db(T::as_str(), Self::flags()).unwrap())
    }

    pub fn open(env: &lmdb::Environment) -> IntToBlobTable<K, T> {
        IntToBlobTable::new_from_handle(env.get_db(T::as_str(), Self::flags()).unwrap())
    }

    fn new_from_handle(db: lmdb::DbHandle) -> IntToBlobTable<K, T> {
        IntToBlobTable {db: db, _k: PhantomData, _t: PhantomData}
    }

    pub fn insert(&self, txn: &Transaction, key: &K, val: &[u8]) -> MdbResult<()> {
        let db = txn.bind(&self.db);
        db.insert(key, &val)
    }

    // fn lookup
}

impl<K, T> KeyToBlobTable<K, T>
where K: Sized + ToMdbValue,
      T: Tablename
{
    fn flags() -> lmdb::core::DbFlags {
        lmdb::core::DbFlags::empty()
    }

    pub fn create(env: &lmdb::Environment) -> KeyToBlobTable<K, T> {
        KeyToBlobTable::new_from_handle(env.create_db(T::as_str(), Self::flags()).unwrap())
    }

    pub fn open(env: &lmdb::Environment) -> KeyToBlobTable<K, T> {
        KeyToBlobTable::new_from_handle(env.get_db(T::as_str(), Self::flags()).unwrap())
    }

    fn new_from_handle(db: lmdb::DbHandle) -> KeyToBlobTable<K, T> {
        KeyToBlobTable {db: db, _k: PhantomData, _t: PhantomData}
    }

    pub fn insert(&self, txn: &Transaction, key: &K, val: &[u8]) -> MdbResult<()> {
        let db = txn.bind(&self.db);
        db.insert(key, &val)
    }

    // fn lookup
}

//
// A unique(native-int) -> sized record value lookup table
//

impl<K, V, T> IntToRecordTable<K, V, T>
where K: Sized + ToMdbValue + IsNativeInt,
      V: Sized + ToMdbValue + FromMdbValue,
      T: Tablename
{
    fn flags() -> lmdb::core::DbFlags {
        lmdb::core::DbIntKey
    }

    pub fn create(env: &lmdb::Environment) -> IntToRecordTable<K, V, T> {
        IntToRecordTable::new_from_handle(env.create_db(T::as_str(), Self::flags()).unwrap())
    }

    pub fn open(env: &lmdb::Environment) -> IntToRecordTable<K, V, T> {
        IntToRecordTable::new_from_handle(env.get_db(T::as_str(), Self::flags()).unwrap())
    }

    fn new_from_handle(db: lmdb::DbHandle) -> IntToRecordTable<K, V, T> {
        IntToRecordTable {db: db, _k: PhantomData, _v: PhantomData, _t: PhantomData}
    }

    pub fn bind_to_txn<'a>(&self, txn: &'a lmdb::Transaction) -> BoundIntToRecordTable<'a, K, V, T> {
        BoundIntToRecordTable {
            db: txn.bind(&self.db),
            _k: PhantomData, _v: PhantomData, _t: PhantomData}
    }

    pub fn bind_to_ro_txn<'a>(&self, txn: &'a lmdb::ReadonlyTransaction) -> BoundIntToRecordTable<'a, K, V, T> {
        BoundIntToRecordTable {
            db: txn.bind(&self.db),
            _k: PhantomData, _v: PhantomData, _t: PhantomData}
    }
}

impl<'a, K, V, T> BoundIntToRecordTable<'a, K, V, T>
where K: Sized + ToMdbValue + IsNativeInt,
      V: Sized + ToMdbValue + FromMdbValue,
      T: Tablename
{
    // fails if key exists.
    pub fn insert(&self, key: &K, val: &V) -> MdbResult<()> {
        self.db.insert(key, val)
    }

    // XXX: Should go into ReadonlyBound...
    pub fn lookup(&self, key: &K) -> MdbResult<V> {
        self.db.get::<V>(key)
    }

    pub fn update<F>(&self, key: &K, update: F) -> MdbResult<()>
        where F: Fn(&mut V) -> bool {

        let mut cursor = try!(self.db.new_cursor());
        try!(cursor.to_key(key));

        let mut value: V = try!(cursor.get_value());

        let needs_update = update(&mut value);

        if needs_update {
            try!(cursor.replace(&value));
        }

        Ok(())
    }

    pub fn insert_or_update<N, F>(&self, key: &K, insert_fn: N, update_fn: F) -> MdbResult<()>
        where
                N: Fn() -> V,
                F: Fn(&mut V) -> bool {

        // Trying to update first
        {
                let mut cursor = try!(self.db.new_cursor());
                if let Ok(_) = cursor.to_key(key) {
                        let mut value: V = try!(cursor.get_value());
                        let needs_update = update_fn(&mut value);
                        if needs_update {
                                try!(cursor.replace(&value));
                        }
                        return Ok(());
                }
        }

        // Now try to insert
        {
            let value: V = insert_fn();
            try!(self.db.insert(key, &value));
            return Ok(());
        }
    }

    pub fn insert_or_update_default<F>(&self, key: &K, update_fn: F) -> MdbResult<bool>
        where
                V: Default,
                F: Fn(&mut V) -> bool {

        // Trying to update first
        {
                let mut cursor = try!(self.db.new_cursor());
                if let Ok(_) = cursor.to_key(key) {
                        let mut value: V = try!(cursor.get_value());
                        let needs_update = update_fn(&mut value);
                        if needs_update {
                                try!(cursor.replace(&value));
                        }
                        return Ok(needs_update);
                }
        }

        // Now try to insert
        {
            let mut value: V = V::default();
            let needs_update = update_fn(&mut value);
            if needs_update {
                try!(self.db.insert(key, &value));
            }
            return Ok(needs_update);
        }
    }
}

impl<K, V, T> KeyToRecordTable<K, V, T>
where K: Sized + ToMdbValue,
      V: Sized + ToMdbValue + FromMdbValue,
      T: Tablename
{
    fn flags() -> lmdb::core::DbFlags {
        lmdb::core::DbFlags::empty()
    }

    pub fn create(env: &lmdb::Environment) -> KeyToRecordTable<K, V, T> {
        KeyToRecordTable::new_from_handle(env.create_db(T::as_str(), Self::flags()).unwrap())
    }

    pub fn open(env: &lmdb::Environment) -> KeyToRecordTable<K, V, T> {
        KeyToRecordTable::new_from_handle(env.get_db(T::as_str(), Self::flags()).unwrap())
    }

    fn new_from_handle(db: lmdb::DbHandle) -> KeyToRecordTable<K, V, T> {
        KeyToRecordTable {db: db, _k: PhantomData, _v: PhantomData, _t: PhantomData}
    }

    pub fn insert(&self, txn: &Transaction, key: &K, val: &V) -> MdbResult<()> {
        let db = txn.bind(&self.db);
        db.insert(key, val)
    }

    pub fn insert_or_update_default<F>(&self, txn: &Transaction, key: &K, update_fn: F) -> MdbResult<bool>
        where
                V: Default,
                F: Fn(&mut V) -> bool {

        let db = txn.bind(&self.db);

        // Trying to update first
        {
                let mut cursor = try!(db.new_cursor());
                if let Ok(_) = cursor.to_key(key) {
                        let mut value: V = try!(cursor.get_value());
                        let needs_update = update_fn(&mut value);
                        if needs_update {
                                try!(cursor.replace(&value));
                        }
                        return Ok(needs_update);
                }
        }

        // Now try to insert
        {
            let mut value: V = V::default();
            let needs_update = update_fn(&mut value);
            if needs_update {
                try!(db.insert(key, &value));
            }
            return Ok(needs_update);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

#[macro_use]
extern crate log;
extern crate fern;
extern crate time;
extern crate libc;
extern crate rand;
extern crate simple_stream;
extern crate num_cpus;
extern crate epoll;
extern crate rustc_serialize;

use std::sync::Mutex;
use std::net::ToSocketAddrs;

use types::*;

pub mod types;
pub mod socket;

mod stats;
mod epollloop;
mod resources;
mod workerthread;

/// Starts the server binding to the passed address.
/// This is a blocking call for the life of the server.
pub fn begin<T, K>(address: T, handler: Box<K>) where
    T: ToSocketAddrs + Send + 'static,
    K: EventHandler + Send + Sync + 'static {

    // Logger
    initialize_logger();

    // Data collection
    let mut data = Mutex::new(stats::GeneralData::new());
    stats::init(&mut data);

    // Begin server
    epollloop::begin(address, handler);
}

/// Initializes the global logger
fn initialize_logger() {
    let _ = fern::init_global_logger(fern::DispatchConfig {
        format: Box::new(|msg: &str, level: &log::LogLevel, _location: &log::LogLocation| {
            format!("[{}][{}] {}", time::now().strftime("%Y-%m-%d][%H:%M:%S").unwrap(), level, msg)
        }),
        output: vec![fern::OutputConfig::stdout(), fern::OutputConfig::file("/var/log/hydrogen.log")],
        level: log::LogLevelFilter::Trace,
    }, log::LogLevelFilter::Trace);
    info!("Logger initialized. \nLog file: /var/log/hydrogen.log");
}
<commit_msg>Update for fern errors<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

#[macro_use]
extern crate log;
extern crate fern;
extern crate time;
extern crate libc;
extern crate rand;
extern crate simple_stream;
extern crate num_cpus;
extern crate epoll;
extern crate rustc_serialize;

use std::sync::Mutex;
use std::net::ToSocketAddrs;

use types::*;

pub mod types;
pub mod socket;

mod stats;
mod epollloop;
mod resources;
mod workerthread;

/// Starts the server binding to the passed address.
/// This is a blocking call for the life of the server.
pub fn begin<T, K>(address: T, handler: Box<K>) where
    T: ToSocketAddrs + Send + 'static,
    K: EventHandler + Send + Sync + 'static {

    // Logger
    initialize_logger();

    // Data collection
    let mut data = Mutex::new(stats::GeneralData::new());
    stats::init(&mut data);

    // Begin server
    epollloop::begin(address, handler);
}

/// Initializes the global logger
fn initialize_logger() {
    let _ = fern::init_global_logger(fern::DispatchConfig {
        format: Box::new(|msg: &str, level: &log::LogLevel, _location: &log::LogLocation| {
            format!("[{}][{}] {}", time::now().strftime("%Y-%m-%d][%H:%M:%S").unwrap(), level, msg)
        }),
        output: vec![fern::OutputConfig::stdout(), fern::OutputConfig::file("/var/log/hydrogen.log")],
        level: log::LogLevelFilter::Trace,
    }, log::LogLevelFilter::Trace);

    info!("Logger initialized. \nLog file: /var/log/hydrogen.log");
}
<|endoftext|>


<commit_before>extern crate toml;

// Import traits
use std::io::prelude::Read;

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}

pub fn test() {
    println!("Hello from lib.rs");
}

#[derive(Debug)]
enum OnSuccess {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum OnFailure {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum Step {
    Echo {name: String, string: String},
    Run {name: String, command: String, arguments: String, on_success: OnSuccess, on_failure: OnFailure},
    Shell,
    SetEnv,
}

fn parse_toml(filename: &str) -> Vec<Step> {

    println!("Reading toml file {}", filename);

    // Read toml file content
    let mut input = String::new();
    std::fs::File::open(&filename).and_then(|mut f| {
        f.read_to_string(&mut input)
    }).unwrap();

    // Pase toml file
    let mut parser = toml::Parser::new(&input);

    let toml = parser.parse().unwrap_or_else(|| {
        for err in &parser.errors {
            let (loline, locol) = parser.to_linecol(err.lo);
            let (hiline, hicol) = parser.to_linecol(err.hi);
            println!("{}:{}:{}-{}:{} error: {}",
                     filename, loline, locol, hiline, hicol, err.desc);
        }
        panic!("Error parsing toml file.");
    });

    println!("toml: {:#?}", toml);
    println!("toml: {:?}", toml.len());

    // Parse "on" table
    // unimplemented!();

    // Parse "variables" table
    // unimplemented!();

    // Parse "steps" table
    let mut steps = Vec::<Step>::with_capacity(10);

    for step in toml.get("step").unwrap().as_slice().unwrap() {
        let action = step.as_table().unwrap().get("action").unwrap().as_str().unwrap();
        let name = step.as_table().unwrap().get("name").unwrap().as_str().unwrap().to_string();
        let details = step.as_table().unwrap().get("details").unwrap().as_table().unwrap();
        let step = match action {
            "echo" => {
                let string = details.get("string").unwrap().as_str().unwrap().to_string();
                Step::Echo {name: name, string: string}
            },
            "run" => {
                let command = details.get("command").unwrap().as_str().unwrap().to_string();
                let arguments = details.get("arguments").unwrap().as_str().unwrap().to_string();

                let on_success = match details.get("on_success") {
                    None => {
                        println!("WARNING: No 'on_success' set for {:?}, default of 'OnSuccess::Continue'", name);
                        OnSuccess::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnSuccess::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnSuccess::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                let on_failure = match details.get("on_failure") {
                    None => {
                        println!("WARNING: No 'on_failure' set for {:?}, default of 'OnFailure::Continue'", name);
                        OnFailure::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnFailure::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnFailure::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                Step::Run {name: name, command: command, arguments: arguments, on_success: on_success, on_failure: on_failure}
            },
            // "shell" => {
            // },
            // "setenv" => {
            // },
            _ => {
                println!("Unknown action '{}' in toml file", action);
                unimplemented!();
            },
        };
        println!("Step: {:?}", step);

        steps.push(step);
    }

    steps
}

pub fn execute_steps(filename: &str) {

    let steps = parse_toml(filename);

    println!("Steps: {:#?}", steps);
}
<commit_msg>Cleanup<commit_after>extern crate toml;

// Import traits
use std::io::prelude::Read;

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}

pub fn test() {
    println!("Hello from lib.rs");
}

#[derive(Debug)]
enum OnSuccess {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum OnFailure {
    Continue,
    Warn {message: String},
    Abort {message: String},
}

#[derive(Debug)]
enum Step {
    Echo {name: String, string: String},
    Run {name: String, command: String, arguments: String, on_success: OnSuccess, on_failure: OnFailure},
    Shell,
    SetEnv,
}

fn parse_toml(filename: &str) -> Vec<Step> {

    println!("Reading toml file {}", filename);

    // Read toml file content
    let mut input = String::new();
    std::fs::File::open(&filename).and_then(|mut f| {
        f.read_to_string(&mut input)
    }).unwrap();

    // Pase toml file
    let mut parser = toml::Parser::new(&input);

    let toml = parser.parse().unwrap_or_else(|| {
        for err in &parser.errors {
            let (loline, locol) = parser.to_linecol(err.lo);
            let (hiline, hicol) = parser.to_linecol(err.hi);
            println!("{}:{}:{}-{}:{} error: {}",
                     filename, loline, locol, hiline, hicol, err.desc);
        }
        panic!("Error parsing toml file.");
    });

    // println!("toml: {:#?}", toml);
    println!("toml: {:?}", toml.len());

    // Parse "on" table
    // unimplemented!();

    // Parse "variables" table
    // unimplemented!();

    // Parse "steps" table
    let mut steps = Vec::<Step>::with_capacity(10);

    for step in toml.get("step").unwrap().as_slice().unwrap() {
        let action = step.as_table().unwrap().get("action").unwrap().as_str().unwrap();
        let name = step.as_table().unwrap().get("name").unwrap().as_str().unwrap().to_string();
        let details = step.as_table().unwrap().get("details").unwrap().as_table().unwrap();
        let step = match action {
            "echo" => {
                let string = details.get("string").unwrap().as_str().unwrap().to_string();
                Step::Echo {name: name, string: string}
            },
            "run" => {
                let command = details.get("command").unwrap().as_str().unwrap().to_string();
                let arguments = details.get("arguments").unwrap().as_str().unwrap().to_string();

                let on_success = match details.get("on_success") {
                    None => {
                        println!("WARNING: No 'on_success' set for {:?}, default of 'OnSuccess::Continue'", name);
                        OnSuccess::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnSuccess::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnSuccess::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                let on_failure = match details.get("on_failure") {
                    None => {
                        println!("WARNING: No 'on_failure' set for {:?}, default of 'OnFailure::Continue'", name);
                        OnFailure::Continue
                    },
                    Some(toml_value) => {
                        let table = toml_value.as_table().unwrap();
                        let (message_type, message) = table.iter().nth(0).unwrap();
                        match message_type.as_ref() {
                            "warn" => OnFailure::Warn {message: message.as_str().unwrap().to_string()},
                            "abort" => OnFailure::Abort {message: message.as_str().unwrap().to_string()},
                            _ => unimplemented!()
                        }
                    }
                };

                Step::Run {name: name, command: command, arguments: arguments, on_success: on_success, on_failure: on_failure}
            },
            // "shell" => {
            // },
            // "setenv" => {
            // },
            _ => {
                println!("Unknown action '{}' in toml file", action);
                unimplemented!();
            },
        };
        println!("Step: {:?}", step);

        steps.push(step);
    }

    steps
}

pub fn execute_steps(filename: &str) {

    let steps = parse_toml(filename);

    println!("Steps: {:#?}", steps);
}
<|endoftext|>


<commit_before>
extern crate gl;

pub use gl::load_with;
pub use vertexarray::{VertexAttribute,AttributeType};

mod buffer;
mod util;
mod tracker;
mod vertexarray;

use std::rc::Rc;
use tracker::{SimpleBindingTracker,VertexArrayTracker};
use buffer::VertexBuffer;
use vertexarray::VertexArray;

pub type VertexBufferHandle = Handle<buffer::VertexBuffer>;
pub type IndexBufferHandle = Handle<buffer::IndexBuffer>;
pub type VertexArrayHandle = Handle<vertexarray::VertexArray>;

trait Bind {
    fn bind(&self);
    fn get_id(&self) -> u32;
}

pub struct Handle<T> {
    resource: Rc<T>
}

impl<T> Handle<T> {
    fn new(resource: T) -> Handle<T> {
        Handle { resource: Rc::new(resource) }
    }

    fn access(&self) -> &T {
        &*self.resource
    }
}

impl<T> Clone for Handle<T> {
    fn clone(&self) -> Handle<T> {
        Handle { resource: self.resource.clone() }
    }
}

pub struct Context {
    vbo_tracker: SimpleBindingTracker<VertexBuffer>,
    vao_tracker: VertexArrayTracker
}

impl Context {
    pub fn new() -> Context {
        Context { vbo_tracker: SimpleBindingTracker::new(), vao_tracker: VertexArrayTracker::new() }
    }

    pub fn new_vertex_buffer(&self) -> VertexBufferHandle {
        Handle::new(buffer::new_vertex_buffer())
    }

    pub fn new_index_buffer(&self) -> IndexBufferHandle {
        Handle::new(buffer::new_index_buffer())
    }

    pub fn new_vertex_array(&mut self,
                            attributes: &[VertexAttribute],
                            index_buffer: Option<IndexBufferHandle>) -> VertexArrayHandle {
        Handle::new(vertexarray::VertexArray::new(self, attributes, index_buffer))
    }

    pub fn vertex_data<T>(&mut self, vbo: &VertexBufferHandle, data: &[T]) {
        let vbo = vbo.access();
        self.vbo_tracker.bind(vbo);
        vbo.data(data);
    }

    pub fn vertex_sub_data<T>(&mut self, vbo: &VertexBufferHandle, data: &[T], offset: uint) {
        let vbo = vbo.access();
        self.vbo_tracker.bind(vbo);
        vbo.sub_data(data, offset);
    }

    fn bind_vbo_for_editing(&mut self, vbo: &VertexBufferHandle) {
        let vbo = vbo.access();
        self.vbo_tracker.bind(vbo);
    }

    fn bind_vao_for_editing(&mut self, vao: &VertexArray) {
        self.vao_tracker.bind_for_editing(vao);
    }
}<commit_msg>Put use statements before other things to make compiler happy.<commit_after>
extern crate gl;

pub use gl::load_with;
pub use vertexarray::{VertexAttribute,AttributeType};

use std::rc::Rc;
use tracker::{SimpleBindingTracker,VertexArrayTracker};
use buffer::VertexBuffer;
use vertexarray::VertexArray;

mod buffer;
mod util;
mod tracker;
mod vertexarray;

pub type VertexBufferHandle = Handle<buffer::VertexBuffer>;
pub type IndexBufferHandle = Handle<buffer::IndexBuffer>;
pub type VertexArrayHandle = Handle<vertexarray::VertexArray>;

trait Bind {
    fn bind(&self);
    fn get_id(&self) -> u32;
}

pub struct Handle<T> {
    resource: Rc<T>
}

impl<T> Handle<T> {
    fn new(resource: T) -> Handle<T> {
        Handle { resource: Rc::new(resource) }
    }

    fn access(&self) -> &T {
        &*self.resource
    }
}

impl<T> Clone for Handle<T> {
    fn clone(&self) -> Handle<T> {
        Handle { resource: self.resource.clone() }
    }
}

pub struct Context {
    vbo_tracker: SimpleBindingTracker<VertexBuffer>,
    vao_tracker: VertexArrayTracker
}

impl Context {
    pub fn new() -> Context {
        Context { vbo_tracker: SimpleBindingTracker::new(), vao_tracker: VertexArrayTracker::new() }
    }

    pub fn new_vertex_buffer(&self) -> VertexBufferHandle {
        Handle::new(buffer::new_vertex_buffer())
    }

    pub fn new_index_buffer(&self) -> IndexBufferHandle {
        Handle::new(buffer::new_index_buffer())
    }

    pub fn new_vertex_array(&mut self,
                            attributes: &[VertexAttribute],
                            index_buffer: Option<IndexBufferHandle>) -> VertexArrayHandle {
        Handle::new(vertexarray::VertexArray::new(self, attributes, index_buffer))
    }

    pub fn vertex_data<T>(&mut self, vbo: &VertexBufferHandle, data: &[T]) {
        let vbo = vbo.access();
        self.vbo_tracker.bind(vbo);
        vbo.data(data);
    }

    pub fn vertex_sub_data<T>(&mut self, vbo: &VertexBufferHandle, data: &[T], offset: uint) {
        let vbo = vbo.access();
        self.vbo_tracker.bind(vbo);
        vbo.sub_data(data, offset);
    }

    fn bind_vbo_for_editing(&mut self, vbo: &VertexBufferHandle) {
        let vbo = vbo.access();
        self.vbo_tracker.bind(vbo);
    }

    fn bind_vao_for_editing(&mut self, vao: &VertexArray) {
        self.vao_tracker.bind_for_editing(vao);
    }
}<|endoftext|>


<commit_before>extern crate libc;
// export it for now

use libc::{c_int, c_char, c_void};
use std::ffi::CString;
use std::ptr;

pub mod ffi;
pub use ffi::{IPaddress, _TCPsocket, _SDLNet_SocketSet, _SDLNet_GenericSocket};

pub struct TCPsocket {
    opaquePtr: *mut _TCPsocket,
}
pub struct SocketSet {
    opaquePtr: *mut _SDLNet_SocketSet,
}
pub struct IPAddress {
    opaquePtr: *mut IPaddress,
}
#[repr(C)]
pub struct CustTCPSocket {
    ready: i32,
}

pub fn init() -> bool { unsafe { ffi::SDLNet_Init() == 0 } }
pub fn quit() -> () { unsafe { ffi::SDLNet_Quit(); } }
pub fn get_error() -> String {
    unsafe {
        let raw = &ffi::SDLNet_GetError();
        std::str::from_utf8(std::ffi::c_str_to_bytes(raw)).unwrap().to_string()
    }
}

// Returns an IPaddress struct if successful in becoming a host on the given port
pub fn become_host(port: u16) -> Option<ffi::IPaddress> {
    let mut address = ffi::IPaddress { host: 0, port: 0};
    let mut result = 0;
    unsafe {
        result = ffi::SDLNet_ResolveHost(&mut address, ptr::null() , port)
    }
    if (result == 0){
        Some(address)
    } else {
        None
    }
}

// Resolves the host from the given IP and porn
pub fn resolve_host(host: &str, port: u16) -> Option<ffi::IPaddress> {
    let mut address = ffi::IPaddress { host: 0, port: 0 };
    let mut result = 0;
    unsafe {
        result = ffi::SDLNet_ResolveHost(&mut address, CString::from_slice(host.as_bytes()).as_ptr(), port)
    }
    if (result == 0) {
        Some(address)
    } else {
        None
    }
}

// Resolves the given IP from the given IPaddress struct
pub fn resolve_ip(mut address: IPaddress) -> String {
    unsafe {
        let raw = &ffi::SDLNet_ResolveIP(&mut address);
        std::str::from_utf8(std::ffi::c_str_to_bytes(raw)).unwrap().to_string()
    }
}

// Returns a TCPsocket from the data given in the IPaddress object
pub fn tcp_open(address: &mut IPaddress) -> Option<TCPsocket> {
    //let mut address = ffi::IPaddress { host: 0, port: 0};
    unsafe {
        let socket = ffi::SDLNet_TCP_Open(address);
        if socket as *const _TCPsocket != ptr::null() {
            Some(TCPsocket { opaquePtr: socket })
        } else {
            None
        }
    }
}

// Closes the given TCPsocket
pub fn tcp_close(sock: &TCPsocket) -> () {
    unsafe {
        ffi::SDLNet_TCP_Close(sock.opaquePtr)
    }
}

// Accepts a TCP connection on the given socket, returning the new socket of the connection
pub fn tcp_accept(server: &TCPsocket) -> Option<TCPsocket> {
    unsafe {
        let socket =  ffi::SDLNet_TCP_Accept(server.opaquePtr);
        if socket as *const _TCPsocket != ptr::null() {
            Some(TCPsocket { opaquePtr: socket})
        } else {
            None
        }
    }
}

pub fn tcp_get_peer_address(sock: &TCPsocket) -> Box<*mut IPaddress> {
    unsafe {
        Box::new(ffi::SDLNet_TCP_GetPeerAddress(sock.opaquePtr))
    }
}

// Writes the data out
pub fn tcp_send(sock: &TCPsocket, data: &[u8]) -> () {
    unsafe {
        ffi::SDLNet_TCP_Send(sock.opaquePtr, data.as_ptr() as *const c_void, data.len() as i32);
    }
}

// Receives incoming data
pub fn tcp_recv(sock: &TCPsocket, maxlen: i32) -> Vec<u8> {
    let mut data: Vec<u8> = Vec::with_capacity(maxlen as usize);
    unsafe {
        let read_ammnt = ffi::SDLNet_TCP_Recv(sock.opaquePtr, data.as_mut_ptr() as *mut c_void, data.len() as i32);
        data.set_len(read_ammnt as usize);
    }
    data
}

// Allocates a socket set to hold the given number of sockets
pub fn alloc_socket_set(maxsockets: i32) -> SocketSet {
    unsafe {
        SocketSet { opaquePtr: ffi::SDLNet_AllocSocketSet(maxsockets) }
    }
}

// Frees the given socket set
pub fn free_socket_set(set: &SocketSet) -> () {
    unsafe {
        ffi::SDLNet_FreeSocketSet(set.opaquePtr);
    }
}

// Adds a given socket to the given socket set
pub fn add_socket(set: &SocketSet, sock: &TCPsocket) -> i32 {
    unsafe {
        ffi::SDLNet_AddSocket(set.opaquePtr, sock.opaquePtr)
    }
}

// Maybe should take in the box here as it may get deleted.... not sure
pub fn del_socket(set: &SocketSet, sock: &TCPsocket) -> i32 {
    unsafe {
        ffi::SDLNet_DelSocket(set.opaquePtr, sock.opaquePtr)
    }
}

// Returns the incoming data amount  on the given socketset
pub fn check_sockets(set: &SocketSet, timeout: u32) -> i32 {
    unsafe {
        ffi::SDLNet_CheckSockets(set.opaquePtr, timeout)
    }
}

pub fn socket_ready(sock: &TCPsocket) -> bool {
    unsafe {
        (std::mem::transmute::<*mut ffi::_TCPsocket,&CustTCPSocket>(sock.opaquePtr)).ready != 0
    }
}
<commit_msg>Changes tcp_recv to take in a data pointer instead of returning a vector.<commit_after>extern crate libc;
// export it for now

use libc::{c_int, c_char, c_void};
use std::ffi::CString;
use std::ptr;

pub mod ffi;
pub use ffi::{IPaddress, _TCPsocket, _SDLNet_SocketSet, _SDLNet_GenericSocket};

pub struct TCPsocket {
    opaquePtr: *mut _TCPsocket,
}
pub struct SocketSet {
    opaquePtr: *mut _SDLNet_SocketSet,
}
pub struct IPAddress {
    opaquePtr: *mut IPaddress,
}
#[repr(C)]
pub struct CustTCPSocket {
    ready: i32,
}

pub fn init() -> bool { unsafe { ffi::SDLNet_Init() == 0 } }
pub fn quit() -> () { unsafe { ffi::SDLNet_Quit(); } }
pub fn get_error() -> String {
    unsafe {
        let raw = &ffi::SDLNet_GetError();
        std::str::from_utf8(std::ffi::c_str_to_bytes(raw)).unwrap().to_string()
    }
}

// Returns an IPaddress struct if successful in becoming a host on the given port
pub fn become_host(port: u16) -> Option<ffi::IPaddress> {
    let mut address = ffi::IPaddress { host: 0, port: 0};
    let mut result = 0;
    unsafe {
        result = ffi::SDLNet_ResolveHost(&mut address, ptr::null() , port)
    }
    if (result == 0){
        Some(address)
    } else {
        None
    }
}

// Resolves the host from the given IP and porn
pub fn resolve_host(host: &str, port: u16) -> Option<ffi::IPaddress> {
    let mut address = ffi::IPaddress { host: 0, port: 0 };
    let mut result = 0;
    unsafe {
        result = ffi::SDLNet_ResolveHost(&mut address, CString::from_slice(host.as_bytes()).as_ptr(), port)
    }
    if (result == 0) {
        Some(address)
    } else {
        None
    }
}

// Resolves the given IP from the given IPaddress struct
pub fn resolve_ip(mut address: IPaddress) -> String {
    unsafe {
        let raw = &ffi::SDLNet_ResolveIP(&mut address);
        std::str::from_utf8(std::ffi::c_str_to_bytes(raw)).unwrap().to_string()
    }
}

// Returns a TCPsocket from the data given in the IPaddress object
pub fn tcp_open(address: &mut IPaddress) -> Option<TCPsocket> {
    //let mut address = ffi::IPaddress { host: 0, port: 0};
    unsafe {
        let socket = ffi::SDLNet_TCP_Open(address);
        if socket as *const _TCPsocket != ptr::null() {
            Some(TCPsocket { opaquePtr: socket })
        } else {
            None
        }
    }
}

// Closes the given TCPsocket
pub fn tcp_close(sock: &TCPsocket) -> () {
    unsafe {
        ffi::SDLNet_TCP_Close(sock.opaquePtr)
    }
}

// Accepts a TCP connection on the given socket, returning the new socket of the connection
pub fn tcp_accept(server: &TCPsocket) -> Option<TCPsocket> {
    unsafe {
        let socket =  ffi::SDLNet_TCP_Accept(server.opaquePtr);
        if socket as *const _TCPsocket != ptr::null() {
            Some(TCPsocket { opaquePtr: socket})
        } else {
            None
        }
    }
}

pub fn tcp_get_peer_address(sock: &TCPsocket) -> Box<*mut IPaddress> {
    unsafe {
        Box::new(ffi::SDLNet_TCP_GetPeerAddress(sock.opaquePtr))
    }
}

// Writes the data out
pub fn tcp_send(sock: &TCPsocket, data: &[u8]) -> () {
    unsafe {
        ffi::SDLNet_TCP_Send(sock.opaquePtr, data.as_ptr() as *const c_void, data.len() as i32);
    }
}

// Receives incoming data
pub fn tcp_recv(sock: &TCPsocket, data: *mut u8, maxlen: i32) -> i32 {//Vec<u8> {
    //let mut data: Vec<u8> = Vec::with_capacity(maxlen as usize);
    let mut read_amnt = 0;
    unsafe {
        read_amnt = ffi::SDLNet_TCP_Recv(sock.opaquePtr, data as *mut c_void, maxlen as i32);
        //data.set_len(read_ammnt as usize);
    }
    //data
    read_amnt
}

// Allocates a socket set to hold the given number of sockets
pub fn alloc_socket_set(maxsockets: i32) -> SocketSet {
    unsafe {
        SocketSet { opaquePtr: ffi::SDLNet_AllocSocketSet(maxsockets) }
    }
}

// Frees the given socket set
pub fn free_socket_set(set: &SocketSet) -> () {
    unsafe {
        ffi::SDLNet_FreeSocketSet(set.opaquePtr);
    }
}

// Adds a given socket to the given socket set
pub fn add_socket(set: &SocketSet, sock: &TCPsocket) -> i32 {
    unsafe {
        ffi::SDLNet_AddSocket(set.opaquePtr, sock.opaquePtr)
    }
}

// Maybe should take in the box here as it may get deleted.... not sure
pub fn del_socket(set: &SocketSet, sock: &TCPsocket) -> i32 {
    unsafe {
        ffi::SDLNet_DelSocket(set.opaquePtr, sock.opaquePtr)
    }
}

// Returns the incoming data amount  on the given socketset
pub fn check_sockets(set: &SocketSet, timeout: u32) -> i32 {
    unsafe {
        ffi::SDLNet_CheckSockets(set.opaquePtr, timeout)
    }
}

pub fn socket_ready(sock: &TCPsocket) -> bool {
    unsafe {
        (std::mem::transmute::<*mut ffi::_TCPsocket,&CustTCPSocket>(sock.opaquePtr)).ready != 0
    }
}
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![crate_name = "lolog"]

///
/// Work in progress, don't use it.
///
///     lolog::init(log::LogLevel::Info, std::io::stderr());
///
extern crate log;
extern crate time;

use std::io;

use log::{LogRecord, LogLevel, LogMetadata, SetLoggerError};
use std::sync::{Arc, Mutex};

pub struct Logger<Writer: io::Write + Send> {
    max_level: LogLevel,
    output: Arc<Mutex<Writer>>,
}

impl<W: io::Write + Send> log::Log for Logger<W> {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.max_level
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            let o = self.output.clone();
            let mut f = o.lock().unwrap();

            let line = format!("{} {}", time::now().rfc3339(), record.args());
            f.write_all(line.as_bytes())
             .expect("Couldn't write to log file");
        }
    }
}

impl<W: io::Write + Send> Logger<W> {
    pub fn new(max_level: LogLevel, writer: W) -> Self {
        Logger {
            max_level: max_level,
            output: Arc::new(Mutex::new(writer)),
        }
    }
}

pub fn install<W: 'static + io::Write + Send>(logger: Logger<W>) -> Result<(), SetLoggerError> {
    log::set_logger(move |max_log_level| {
        max_log_level.set(logger.max_level.to_log_level_filter());
        Box::new(logger)
    })
}

pub fn init<W: 'static + io::Write + Send>(level: LogLevel,
                                           output: W)
                                           -> Result<(), SetLoggerError> {
    log::set_logger(move |max_log_level| {
        max_log_level.set(level.to_log_level_filter());
        Box::new(Logger::new(level, output))
    })
}

#[cfg(test)]
mod test {
    #[test]
    fn it_works() {}
}
<commit_msg>Add formatter to logger<commit_after>#![crate_type = "lib"]
#![crate_name = "lolog"]

///
/// Work in progress, don't use it.
///
///     lolog::init(log::LogLevel::Info, std::io::stderr());
///
extern crate log;
extern crate time;

use std::io;

use log::{LogRecord, LogLevel, LogMetadata, SetLoggerError};
use std::sync::{Arc, Mutex};

type Formatter = Fn(&LogRecord) -> String + Send + Sync;

pub struct Logger<Writer: io::Write + Send> {
    max_level: LogLevel,
    output: Arc<Mutex<Writer>>,
    formatter: Box<Formatter>,
}

impl<W: io::Write + Send> log::Log for Logger<W> {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.max_level
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            let o = self.output.clone();
            let mut f = o.lock().unwrap();

            // let line = format!("{} {}", time::now().rfc3339(), record.args());
            let line = (self.formatter)(record);
            f.write_all(line.as_bytes())
             .expect("Couldn't write to log file");
        }
    }
}

pub fn default_formatter(record: &LogRecord) -> String {
    match record.target() {
        "" => {
            format!("{} {} {}",
                    time::now().rfc3339(),
                    record.level(),
                    record.args())
        }
        _ => {
            format!("{} {} {} {}",
                    time::now().rfc3339(),
                    record.target(),
                    record.level(),
                    record.args())
        }
    }
}

impl<W: io::Write + Send> Logger<W> {
    pub fn new(max_level: LogLevel, writer: W) -> Self {
        Logger {
            max_level: max_level,
            output: Arc::new(Mutex::new(writer)),
            formatter: Box::new(default_formatter),
        }
    }
}

pub fn install<W: 'static + io::Write + Send>(logger: Logger<W>) -> Result<(), SetLoggerError> {
    log::set_logger(move |max_log_level| {
        max_log_level.set(logger.max_level.to_log_level_filter());
        Box::new(logger)
    })
}

pub fn init<W: 'static + io::Write + Send>(level: LogLevel,
                                           output: W)
                                           -> Result<(), SetLoggerError> {
    log::set_logger(move |max_log_level| {
        max_log_level.set(level.to_log_level_filter());
        Box::new(Logger::new(level, output))
    })
}

#[cfg(test)]
mod test {
    #[test]
    fn it_works() {}
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A Glutin window back-end for the Piston game engine.

extern crate glutin;
extern crate gl;
extern crate window;
extern crate shader_version;
extern crate input;
#[macro_use]
extern crate quack;

// External crates.
use input::{
    keyboard,
    MouseButton,
    Button,
    Input,
    Motion,
};
use window::{
    WindowSettings,
    ShouldClose, Size, PollEvent, SwapBuffers,
    CaptureCursor, DrawSize, Title,
    ExitOnEsc
};
use shader_version::opengl::OpenGL;

/// Contains stuff for game window.
pub struct GlutinWindow {
    /// The window.
    pub window: glutin::Window,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
    // The back-end does not remember the title.
    title: String,
    exit_on_esc: bool,
}

impl GlutinWindow {
    /// Creates a new game window for GLFW.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlutinWindow {
        let (major, minor) = opengl.get_major_minor();
        let mut builder = glutin::WindowBuilder::new()
            .with_dimensions(settings.size[0], settings.size[1])
            .with_gl_version((major as u32, minor as u32))
            .with_title(settings.title.clone())
            .with_multisampling(settings.samples as u16);
        if settings.fullscreen {
            builder = builder.with_fullscreen(glutin::get_primary_monitor());
        }
        let window = builder
            .build().unwrap();
        unsafe { window.make_current(); }

        // Load the OpenGL function pointers
        gl::load_with(|s| window.get_proc_address(s));

        GlutinWindow {
            window: window,
            last_mouse_pos: None,
            title: settings.title,
            exit_on_esc: settings.exit_on_esc,
        }
    }

    fn poll_event(&mut self) -> Option<Input> {
        use glutin::Event as E;
        use input::Input;

        if let Some((x, y)) = self.last_mouse_pos {
            self.last_mouse_pos = None;
            return Some(Input::Move(input::Motion::MouseRelative(x, y)));
        }

        match self.window.poll_events().next() {
            None => None,
            Some(E::Resized(w, h)) =>
                Some(Input::Resize(w, h)),
            Some(E::ReceivedCharacter(ch)) =>
                Some(Input::Text(ch.to_string())),
            Some(E::Focused(focused)) =>
                Some(Input::Focus(focused)),
            Some(E::KeyboardInput(glutin::ElementState::Pressed,
                _, Some(key))) =>
                Some(Input::Press(Button::Keyboard(map_key(key)))),
            Some(E::KeyboardInput(glutin::ElementState::Released,
                _, Some(key))) =>
                Some(Input::Release(Button::Keyboard(map_key(key)))),
            Some(E::MouseMoved((x, y))) => {
                self.last_mouse_pos = Some((x as f64, y as f64));
                Some(Input::Move(
                    Motion::MouseCursor(x as f64, y as f64)))
            }
            Some(E::MouseWheel(y)) =>
                Some(Input::Move(
                    Motion::MouseScroll(0.0, y as f64))),
            Some(E::MouseInput(glutin::ElementState::Pressed, button)) =>
                Some(Input::Press(Button::Mouse(map_mouse(button)))),
            Some(E::MouseInput(glutin::ElementState::Released, button)) =>
                Some(Input::Release(Button::Mouse(map_mouse(button)))),
            _ => None,
        }
    }

    /*
    fn capture_cursor(&mut self, enabled: bool) {

    }
    */
}

quack! {
obj: GlutinWindow[]
get:
    fn () -> Size [] {
        if let Some((w, h)) = obj.window.get_outer_size() {
            Size([w, h])
        } else {
            Size([0, 0])
        }
    }
    fn () -> ShouldClose [] { ShouldClose(obj.window.should_close()) }
    fn () -> DrawSize [] {
        if let Some((w, h)) = obj.window.get_inner_size() {
            DrawSize([w, h])
        } else {
            DrawSize([0, 0])
        }
    }
    fn () -> Title [] { Title(obj.title.clone()) }
    fn () -> ExitOnEsc [] { ExitOnEsc(obj.exit_on_esc) }
set:
    // fn (val: CaptureCursor) [] {}
    // fn (val: ShouldClose) [] {}
    fn (val: Title) [] {
        obj.title = val.0;
        obj.window.set_title(&obj.title[]);
    }
    fn (val: ExitOnEsc) [] { obj.exit_on_esc = val.0; }
action:
    fn (__: PollEvent) -> Option<Input> [] { obj.poll_event() }
    fn (__: SwapBuffers) -> () [] { obj.window.swap_buffers(); }
}

/// Maps Glutin's key to Piston's key.
pub fn map_key(keycode: glutin::VirtualKeyCode) -> keyboard::Key {
    use input::keyboard::Key;
    use glutin::VirtualKeyCode as K;

    match keycode {
        K::Key0 => Key::D0,
        K::Key1 => Key::D1,
        K::Key2 => Key::D2,
        K::Key3 => Key::D3,
        K::Key4 => Key::D4,
        K::Key5 => Key::D5,
        K::Key6 => Key::D6,
        K::Key7 => Key::D7,
        K::Key8 => Key::D8,
        K::Key9 => Key::D9,
        K::A => Key::A,
        K::B => Key::B,
        K::C => Key::C,
        K::D => Key::D,
        K::E => Key::E,
        K::F => Key::F,
        K::G => Key::G,
        K::H => Key::H,
        K::I => Key::I,
        K::J => Key::J,
        K::K => Key::K,
        K::L => Key::L,
        K::M => Key::M,
        K::N => Key::N,
        K::O => Key::O,
        K::P => Key::P,
        K::Q => Key::Q,
        K::R => Key::R,
        K::S => Key::S,
        K::T => Key::T,
        K::U => Key::U,
        K::V => Key::V,
        K::W => Key::W,
        K::X => Key::X,
        K::Y => Key::Y,
        K::Z => Key::Z,
        K::Apostrophe => Key::Unknown,
        K::Backslash => Key::Backslash,
        K::Back => Key::Backspace,
        // K::CapsLock => Key::CapsLock,
        K::Delete => Key::Delete,
        K::Comma => Key::Comma,
        K::Down => Key::Down,
        K::End => Key::End,
        K::Return => Key::Return,
        K::Equals => Key::Equals,
        K::Escape => Key::Escape,
        K::F1 => Key::F1,
        K::F2 => Key::F2,
        K::F3 => Key::F3,
        K::F4 => Key::F4,
        K::F5 => Key::F5,
        K::F6 => Key::F6,
        K::F7 => Key::F7,
        K::F8 => Key::F8,
        K::F9 => Key::F9,
        K::F10 => Key::F10,
        K::F11 => Key::F11,
        K::F12 => Key::F12,
        K::F13 => Key::F13,
        K::F14 => Key::F14,
        K::F15 => Key::F15,
        // K::F16 => Key::F16,
        // K::F17 => Key::F17,
        // K::F18 => Key::F18,
        // K::F19 => Key::F19,
        // K::F20 => Key::F20,
        // K::F21 => Key::F21,
        // K::F22 => Key::F22,
        // K::F23 => Key::F23,
        // K::F24 => Key::F24,
        // Possibly next code.
        // K::F25 => Key::Unknown,
        K::Numpad0 => Key::NumPad0,
        K::Numpad1 => Key::NumPad1,
        K::Numpad2 => Key::NumPad2,
        K::Numpad3 => Key::NumPad3,
        K::Numpad4 => Key::NumPad4,
        K::Numpad5 => Key::NumPad5,
        K::Numpad6 => Key::NumPad6,
        K::Numpad7 => Key::NumPad7,
        K::Numpad8 => Key::NumPad8,
        K::Numpad9 => Key::NumPad9,
        K::NumpadComma => Key::NumPadDecimal,
        K::Divide => Key::NumPadDivide,
        K::Multiply => Key::NumPadMultiply,
        K::Subtract => Key::NumPadMinus,
        K::Add => Key::NumPadPlus,
        K::NumpadEnter => Key::NumPadEnter,
        K::NumpadEquals => Key::NumPadEquals,
        K::LShift => Key::LShift,
        K::LControl => Key::LCtrl,
        K::LAlt => Key::LAlt,
        K::LMenu => Key::LGui,
        K::RShift => Key::RShift,
        K::RControl => Key::RCtrl,
        K::RAlt => Key::RAlt,
        K::RMenu => Key::RGui,
        // Map to backslash?
        // K::GraveAccent => Key::Unknown,
        K::Home => Key::Home,
        K::Insert => Key::Insert,
        K::Left => Key::Left,
        K::LBracket => Key::LeftBracket,
        // K::Menu => Key::Menu,
        K::Minus => Key::Minus,
        K::Numlock => Key::NumLockClear,
        K::PageDown => Key::PageDown,
        K::PageUp => Key::PageUp,
        K::Pause => Key::Pause,
        K::Period => Key::Period,
        // K::PrintScreen => Key::PrintScreen,
        K::Right => Key::Right,
        K::RBracket => Key::RightBracket,
        // K::ScrollLock => Key::ScrollLock,
        K::Semicolon => Key::Semicolon,
        K::Slash => Key::Slash,
        K::Space => Key::Space,
        K::Tab => Key::Tab,
        K::Up => Key::Up,
        // K::World1 => Key::Unknown,
        // K::World2 => Key::Unknown,
        _ => Key::Unknown,
    }
}

/// Maps Glutin's mouse button to Piston's mouse button.
pub fn map_mouse(mouse_button: glutin::MouseButton) -> MouseButton {
    use glutin::MouseButton as M;

    match mouse_button {
        M::Left => MouseButton::Left,
        M::Right => MouseButton::Right,
        M::Middle => MouseButton::Middle,
        M::Other(0) => MouseButton::X1,
        M::Other(1) => MouseButton::X2,
        M::Other(2) => MouseButton::Button6,
        M::Other(3) => MouseButton::Button7,
        M::Other(4) => MouseButton::Button8,
        _ => MouseButton::Unknown
    }
}
<commit_msg>Added optional close on escape behaviour<commit_after>#![deny(missing_docs)]

//! A Glutin window back-end for the Piston game engine.

extern crate glutin;
extern crate gl;
extern crate window;
extern crate shader_version;
extern crate input;
#[macro_use]
extern crate quack;

// External crates.
use input::{
    keyboard,
    MouseButton,
    Button,
    Input,
    Motion,
};
use window::{
    WindowSettings,
    ShouldClose, Size, PollEvent, SwapBuffers,
    //CaptureCursor,
    DrawSize, Title,
    ExitOnEsc
};
use shader_version::opengl::OpenGL;

/// Contains stuff for game window.
pub struct GlutinWindow {
    /// The window.
    pub window: glutin::Window,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
    // The back-end does not remember the title.
    title: String,
    exit_on_esc: bool,
    should_close: bool,
}

impl GlutinWindow {
    /// Creates a new game window for GLFW.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlutinWindow {
        let (major, minor) = opengl.get_major_minor();
        let mut builder = glutin::WindowBuilder::new()
            .with_dimensions(settings.size[0], settings.size[1])
            .with_gl_version((major as u32, minor as u32))
            .with_title(settings.title.clone())
            .with_multisampling(settings.samples as u16);
        if settings.fullscreen {
            builder = builder.with_fullscreen(glutin::get_primary_monitor());
        }
        let window = builder
            .build().unwrap();
        unsafe { window.make_current(); }

        // Load the OpenGL function pointers
        gl::load_with(|s| window.get_proc_address(s));

        GlutinWindow {
            window: window,
            last_mouse_pos: None,
            title: settings.title,
            exit_on_esc: settings.exit_on_esc,
            should_close: false,
        }
    }

    fn poll_event(&mut self) -> Option<Input> {
        use glutin::Event as E;
        use input::Input;

        if let Some((x, y)) = self.last_mouse_pos {
            self.last_mouse_pos = None;
            return Some(Input::Move(input::Motion::MouseRelative(x, y)));
        }

        match self.window.poll_events().next() {
            None => None,
            Some(E::Resized(w, h)) =>
                Some(Input::Resize(w, h)),
            Some(E::ReceivedCharacter(ch)) =>
                Some(Input::Text(ch.to_string())),
            Some(E::Focused(focused)) =>
                Some(Input::Focus(focused)),
            Some(E::KeyboardInput(glutin::ElementState::Pressed, _, Some(key))) => {
                let piston_key = map_key(key);
                if let (true, input::keyboard::Key::Escape) = (self.exit_on_esc, piston_key) {
                    self.should_close = true;
                }
                Some(Input::Press(Button::Keyboard(piston_key)))
            },
            Some(E::KeyboardInput(glutin::ElementState::Released, _, Some(key))) =>
                Some(Input::Release(Button::Keyboard(map_key(key)))),
            Some(E::MouseMoved((x, y))) => {
                self.last_mouse_pos = Some((x as f64, y as f64));
                Some(Input::Move(
                    Motion::MouseCursor(x as f64, y as f64)))
            }
            Some(E::MouseWheel(y)) =>
                Some(Input::Move(
                    Motion::MouseScroll(0.0, y as f64))),
            Some(E::MouseInput(glutin::ElementState::Pressed, button)) =>
                Some(Input::Press(Button::Mouse(map_mouse(button)))),
            Some(E::MouseInput(glutin::ElementState::Released, button)) =>
                Some(Input::Release(Button::Mouse(map_mouse(button)))),
            _ => None,
        }
    }

    /*
    fn capture_cursor(&mut self, enabled: bool) {

    }
    */
}

quack! {
obj: GlutinWindow[]
get:
    fn () -> Size [] {
        if let Some((w, h)) = obj.window.get_outer_size() {
            Size([w, h])
        } else {
            Size([0, 0])
        }
    }
    fn () -> ShouldClose [] { ShouldClose(obj.window.should_close() || obj.should_close) }
    fn () -> DrawSize [] {
        if let Some((w, h)) = obj.window.get_inner_size() {
            DrawSize([w, h])
        } else {
            DrawSize([0, 0])
        }
    }
    fn () -> Title [] { Title(obj.title.clone()) }
    fn () -> ExitOnEsc [] { ExitOnEsc(obj.exit_on_esc) }
set:
    // fn (val: CaptureCursor) [] {}
    // fn (val: ShouldClose) [] {}
    fn (val: Title) [] {
        obj.title = val.0;
        obj.window.set_title(&obj.title);
    }
    fn (val: ExitOnEsc) [] { obj.exit_on_esc = val.0; }
action:
    fn (__: PollEvent) -> Option<Input> [] { obj.poll_event() }
    fn (__: SwapBuffers) -> () [] { obj.window.swap_buffers(); }
}

/// Maps Glutin's key to Piston's key.
pub fn map_key(keycode: glutin::VirtualKeyCode) -> keyboard::Key {
    use input::keyboard::Key;
    use glutin::VirtualKeyCode as K;

    match keycode {
        K::Key0 => Key::D0,
        K::Key1 => Key::D1,
        K::Key2 => Key::D2,
        K::Key3 => Key::D3,
        K::Key4 => Key::D4,
        K::Key5 => Key::D5,
        K::Key6 => Key::D6,
        K::Key7 => Key::D7,
        K::Key8 => Key::D8,
        K::Key9 => Key::D9,
        K::A => Key::A,
        K::B => Key::B,
        K::C => Key::C,
        K::D => Key::D,
        K::E => Key::E,
        K::F => Key::F,
        K::G => Key::G,
        K::H => Key::H,
        K::I => Key::I,
        K::J => Key::J,
        K::K => Key::K,
        K::L => Key::L,
        K::M => Key::M,
        K::N => Key::N,
        K::O => Key::O,
        K::P => Key::P,
        K::Q => Key::Q,
        K::R => Key::R,
        K::S => Key::S,
        K::T => Key::T,
        K::U => Key::U,
        K::V => Key::V,
        K::W => Key::W,
        K::X => Key::X,
        K::Y => Key::Y,
        K::Z => Key::Z,
        K::Apostrophe => Key::Unknown,
        K::Backslash => Key::Backslash,
        K::Back => Key::Backspace,
        // K::CapsLock => Key::CapsLock,
        K::Delete => Key::Delete,
        K::Comma => Key::Comma,
        K::Down => Key::Down,
        K::End => Key::End,
        K::Return => Key::Return,
        K::Equals => Key::Equals,
        K::Escape => Key::Escape,
        K::F1 => Key::F1,
        K::F2 => Key::F2,
        K::F3 => Key::F3,
        K::F4 => Key::F4,
        K::F5 => Key::F5,
        K::F6 => Key::F6,
        K::F7 => Key::F7,
        K::F8 => Key::F8,
        K::F9 => Key::F9,
        K::F10 => Key::F10,
        K::F11 => Key::F11,
        K::F12 => Key::F12,
        K::F13 => Key::F13,
        K::F14 => Key::F14,
        K::F15 => Key::F15,
        // K::F16 => Key::F16,
        // K::F17 => Key::F17,
        // K::F18 => Key::F18,
        // K::F19 => Key::F19,
        // K::F20 => Key::F20,
        // K::F21 => Key::F21,
        // K::F22 => Key::F22,
        // K::F23 => Key::F23,
        // K::F24 => Key::F24,
        // Possibly next code.
        // K::F25 => Key::Unknown,
        K::Numpad0 => Key::NumPad0,
        K::Numpad1 => Key::NumPad1,
        K::Numpad2 => Key::NumPad2,
        K::Numpad3 => Key::NumPad3,
        K::Numpad4 => Key::NumPad4,
        K::Numpad5 => Key::NumPad5,
        K::Numpad6 => Key::NumPad6,
        K::Numpad7 => Key::NumPad7,
        K::Numpad8 => Key::NumPad8,
        K::Numpad9 => Key::NumPad9,
        K::NumpadComma => Key::NumPadDecimal,
        K::Divide => Key::NumPadDivide,
        K::Multiply => Key::NumPadMultiply,
        K::Subtract => Key::NumPadMinus,
        K::Add => Key::NumPadPlus,
        K::NumpadEnter => Key::NumPadEnter,
        K::NumpadEquals => Key::NumPadEquals,
        K::LShift => Key::LShift,
        K::LControl => Key::LCtrl,
        K::LAlt => Key::LAlt,
        K::LMenu => Key::LGui,
        K::RShift => Key::RShift,
        K::RControl => Key::RCtrl,
        K::RAlt => Key::RAlt,
        K::RMenu => Key::RGui,
        // Map to backslash?
        // K::GraveAccent => Key::Unknown,
        K::Home => Key::Home,
        K::Insert => Key::Insert,
        K::Left => Key::Left,
        K::LBracket => Key::LeftBracket,
        // K::Menu => Key::Menu,
        K::Minus => Key::Minus,
        K::Numlock => Key::NumLockClear,
        K::PageDown => Key::PageDown,
        K::PageUp => Key::PageUp,
        K::Pause => Key::Pause,
        K::Period => Key::Period,
        // K::PrintScreen => Key::PrintScreen,
        K::Right => Key::Right,
        K::RBracket => Key::RightBracket,
        // K::ScrollLock => Key::ScrollLock,
        K::Semicolon => Key::Semicolon,
        K::Slash => Key::Slash,
        K::Space => Key::Space,
        K::Tab => Key::Tab,
        K::Up => Key::Up,
        // K::World1 => Key::Unknown,
        // K::World2 => Key::Unknown,
        _ => Key::Unknown,
    }
}

/// Maps Glutin's mouse button to Piston's mouse button.
pub fn map_mouse(mouse_button: glutin::MouseButton) -> MouseButton {
    use glutin::MouseButton as M;

    match mouse_button {
        M::Left => MouseButton::Left,
        M::Right => MouseButton::Right,
        M::Middle => MouseButton::Middle,
        M::Other(0) => MouseButton::X1,
        M::Other(1) => MouseButton::X2,
        M::Other(2) => MouseButton::Button6,
        M::Other(3) => MouseButton::Button7,
        M::Other(4) => MouseButton::Button8,
        _ => MouseButton::Unknown
    }
}
<|endoftext|>