<commit_before>//! A library for using the Monzo API
//!
//! This library wraps over the Monzo API in a future aware manner.
//!
//! Example usage:
//!
//! ```rust,no_run
//! extern crate monzo;
//! extern crate tokio_core;
//!
//! let mut core = tokio_core::reactor::Core::new().unwrap();
//! let monzo = monzo::Client::new(&core.handle(), "<access_token>");
//! let work = monzo.balance("<account_id>".into());
//! let response = core.run(work).unwrap();
//! println!("Balance: {} {}", response.balance, response.currency);
//! println!("Spent today: {}", response.spend_today);
//! ```

#![crate_name = "monzo"]
#![deny(missing_docs,
        missing_debug_implementations,
        missing_copy_implementations,
        trivial_casts,
        trivial_numeric_casts,
        unsafe_code,
        unused_extern_crates,
        unused_import_braces,
        unused_qualifications)]

#[macro_use]
extern crate error_chain;
extern crate chrono;
extern crate futures;
extern crate hyper;
extern crate serde;
extern crate hyper_tls;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;
extern crate url;

use chrono::DateTime;
use chrono::offset::Utc;
use futures::{Future, Stream};
use hyper::{Body, Method, Request, Uri, Chunk, StatusCode};
use hyper::header::{Authorization, Bearer};
use serde::de;
use serde::de::Deserialize;
use serde::de::Deserializer;
use serde::de::Visitor;
use std::collections::HashMap;
use std::str::FromStr;
use std::string::String;
use tokio_core::reactor::Handle;
use url::Url;

/// Identifier for an account.
pub type AccountId = String;
/// Identifier for a transaction.
pub type TransactionId = String;
/// Identifier of a merchant.
pub type MerchantId = String;
/// Holds an ISO 4217 currency code.
pub type Currency = String;

/// Accounts represent a store of funds, and have a list of transactions.
#[derive(Debug, Deserialize)]
pub struct Account {
    /// The account id.
    pub id: AccountId,
    /// Description of the account.
    pub description: String,
    /// The timestamp when the account was created.
    pub created: DateTime<Utc>,
}

/// Response to the list accounts future.
#[derive(Debug, Deserialize)]
pub struct Accounts {
    /// List of accounts owned by the currenty authorized user.
    pub accounts: Vec<Account>,
}

/// Response to the balance future if successful.
#[derive(Debug, Deserialize)]
pub struct Balance {
    /// The currently available balance of the account, as a 64bit integer in minor units of the
    /// currency, eg. pennies for GBP, or cents for EUR and USD.
    pub balance: i64,
    /// The ISO 4217 currency code.
    pub currency: Currency,
    /// The amount spent from this account today (considered from approx 4am onwards), in minor
    /// units of the currency.
    pub spend_today: i64,
}

/// Deserializes a string but returns None on empty string.
fn none_for_empty_string<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
    T: Deserialize<'de> + FromStr,
    D: Deserializer<'de>,
{
    // This is a Visitor that forwards string types to T's `FromStr` impl if the string is
    // non-empty The `PhantomData` is to keep the compiler from complaining about T being an unused
    // generic type parameter. We need T in order to know the Value type for the Visitor impl.
    struct NonEmptyString<T>(std::marker::PhantomData<Option<T>>);

    impl<'de, T> Visitor<'de> for NonEmptyString<T>
    where
        T: Deserialize<'de> + FromStr,
    {
        type Value = Option<T>;

        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
            formatter.write_str("string")
        }

        fn visit_str<E>(self, value: &str) -> Result<Option<T>, E>
        where
            E: de::Error,
        {
            if value.is_empty() {
                return Ok(None);
            } else {
                let res = FromStr::from_str(value);
                match res {
                    Ok(good) => Ok(Some(good)),
                    // TODO: Find a way to propagate the error.
                    Err(_) => Err(de::Error::custom("could not parse string")),
                }
            }
        }

        fn visit_string<E>(self, value: String) -> Result<Option<T>, E>
        where
            E: de::Error,
        {
            self.visit_str(&value)
        }
    }

    deserializer.deserialize_any(NonEmptyString(std::marker::PhantomData))
}

/// Describes a transaction.
#[derive(Debug, Deserialize)]
pub struct Transaction {
    /// Balance in the account after the transaction.
    pub account_balance: i64,
    /// The amount of the transaction in minor units of currency. For example pennies in the case
    /// of GBP. A negative amount indicates a debit (most card transactions will have a negative
    /// amount).
    pub amount: i64,
    /// The timestamp in when the transaction was created.
    pub created: DateTime<Utc>,
    /// The ISO 4217 currency code.
    pub currency: Currency,
    /// Description of the transaction.
    pub description: String,
    /// The transaction id.
    pub id: TransactionId,
    /// This contains the merchant_id of the merchant that this transaction was made at.
    pub merchant: Option<MerchantId>,
    /// Key-value annotations made for transaction. Metadata is private to your application.
    pub metadata: HashMap<String, String>,
    /// Notes attached to the transaction.
    pub notes: String,
    /// Top-ups to an account are represented as transactions with a positive amount and
    /// is_load = true. Other transactions such as refunds, reversals or chargebacks may have a
    /// positive amount but is_load = false
    pub is_load: bool,
    /// The timestamp in UTC (RFC 3339) at which the transaction settled. In most cases, this
    /// happens 24-48 hours after created. If this field is not present, the transaction is
    /// authorised but not yet “complete”.
    ///
    /// Bug: Even though the Monzo documentation says the field is not present when not authorised,
    /// in practice they send an empty string. See https://github.com/monzo/docs/pull/59.
    #[serde(deserialize_with = "none_for_empty_string")]
    pub settled: Option<DateTime<Utc>>,
    /// The category can be set for each transaction by the user. Over time we learn which merchant
    /// goes in which category and auto-assign the category of a transaction. If the user hasn’t
    /// set a category, we’ll return the default category of the merchant on this transactions.
    /// Top-ups have category mondo. Valid values are general, eating_out, expenses, transport,
    /// cash, bills, entertainment, shopping, holidays, groceries.
    pub category: String,
    /// This is only present on declined transactions! Valid values are INSUFFICIENT_FUNDS,
    /// CARD_INACTIVE, CARD_BLOCKED or OTHER.
    // TODO: Make this an enum?
    pub decline_reason: Option<String>,
}

/// Response to the transactions future if successful.
#[derive(Debug, Deserialize)]
pub struct Transactions {
    /// List of transactions.
    pub transactions: Vec<Transaction>,
}

/// Response to the transaction future if successful.
#[derive(Debug, Deserialize)]
pub struct TransactionResponse {
    /// A single transaction.
    pub transaction: Transaction,
}

/// Response to the futures in case of an error.
#[derive(Debug, Deserialize)]
pub struct Error {
    /// The HTTP response code.
    pub code: Option<String>,
    /// Short description of the error.
    // TODO; Maybe make this an enum since the documentation says it can only contain a certain set
    // of values.
    pub error: Option<String>,
    /// Longer description of the error.
    pub error_description: Option<String>,
    /// Additional information.
    pub message: Option<String>,
}

const ACCOUNT_ID: &'static str = "account_id";

/// Errors for this crate using `error_chain`.
pub mod errors {
    error_chain! {
        errors {
            #[doc = "When the Monzo API returns an error response code with more detailed \
            information."]
            BadResponse(statuscode: ::hyper::StatusCode, error: ::Error)
        }
        foreign_links {
            BadJsonResponse(::serde_json::Error)
            #[doc = "When the Monzo API returns invalid or unexpected json content."];
            NetworkError(::hyper::Error) #[doc = "Returned on network failure."];
        }
    }
}

/// The main interface for this crate.
#[derive(Debug)]
pub struct Client {
    client: hyper::client::Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>,
    access_token: String,
    base_url: Url,
}

/// The main interface for this crate.
impl Client {
    /// Creates a new Monzo client.
    pub fn new(handle: &Handle, access_token: &str) -> Client {
        Client::new_with_base_url(
            handle,
            access_token,
            "https://api.monzo.com".parse().unwrap(),
        )
    }

    /// Creates a new Monzo client with another base url. Useful for tests.
    pub fn new_with_base_url(handle: &Handle, access_token: &str, base_url: Url) -> Client {
        Client {
            client: ::hyper::Client::configure()
                .connector(::hyper_tls::HttpsConnector::new(4, handle).unwrap())
                .build(handle),
            access_token: access_token.into(),
            base_url: base_url,
        }
    }

    fn create_request(&self, uri: Uri) -> Request<Body> {
        let mut req: Request<Body> = Request::new(Method::Get, uri);
        req.headers_mut().set(Authorization(
            Bearer { token: self.access_token.clone() },
        ));
        req
    }

    fn make_request<T: 'static, F: 'static>(
        &self,
        uri: Uri,
        response_handler: F,
    ) -> Box<Future<Item = T, Error = errors::Error>>
    where
        F: Fn(Chunk) -> Result<T, errors::Error>,
    {
        let request = self.create_request(uri);
        let response: hyper::client::FutureResponse = self.client.request(request);
        let future = response
            .map_err(|err: hyper::Error| -> errors::Error { err.into() })
            .and_then(|res| {
                let status = res.status();
                res.body()
                    .concat2()
                    .map_err(|err: hyper::Error| err.into())
                    .and_then(move |body: Chunk| {
                        match status {
                            StatusCode::Ok => {}
                            _ => {
                                let error: Error = serde_json::from_slice(&body)?;
                                return Err(errors::ErrorKind::BadResponse(status, error).into());
                            }
                        };
                        response_handler(body)
                    })
            });

        Box::new(future)
    }

    /// Returns a list of accounts owned by the currently authorised user.
    pub fn accounts(&self) -> Box<Future<Item = Accounts, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("accounts");
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let a: Accounts = serde_json::from_slice(&body)?;
            Ok(a)
        })
    }

    /// Retrieve information about an account’s balance.
    pub fn balance(
        &self,
        account_id: AccountId,
    ) -> Box<Future<Item = Balance, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("balance");
        url.query_pairs_mut().append_pair(ACCOUNT_ID, &account_id);
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let b: Balance = serde_json::from_slice(&body)?;
            Ok(b)
        })
    }

    /// Returns a list of transactions on the user’s account.
    pub fn transactions(
        &self,
        account_id: AccountId,
    ) -> Box<Future<Item = Transactions, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("transactions");
        url.query_pairs_mut().append_pair(ACCOUNT_ID, &account_id);
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let t: Transactions = serde_json::from_slice(&body)?;
            Ok(t)
        })
    }

    /// Returns a list of transactions on the user’s account.
    pub fn transaction(
        &self,
        account_id: AccountId,
        transaction_id: TransactionId,
    ) -> Box<Future<Item = TransactionResponse, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("transactions");
        url.path_segments_mut().unwrap().push(&transaction_id);
        url.query_pairs_mut().append_pair(ACCOUNT_ID, &account_id);
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let t: TransactionResponse = serde_json::from_slice(&body)?;
            Ok(t)
        })
    }
}
<commit_msg>Change constant to an associated constant<commit_after>//! A library for using the Monzo API
//!
//! This library wraps over the Monzo API in a future aware manner.
//!
//! Example usage:
//!
//! ```rust,no_run
//! extern crate monzo;
//! extern crate tokio_core;
//!
//! let mut core = tokio_core::reactor::Core::new().unwrap();
//! let monzo = monzo::Client::new(&core.handle(), "<access_token>");
//! let work = monzo.balance("<account_id>".into());
//! let response = core.run(work).unwrap();
//! println!("Balance: {} {}", response.balance, response.currency);
//! println!("Spent today: {}", response.spend_today);
//! ```

#![crate_name = "monzo"]
#![deny(missing_docs,
        missing_debug_implementations,
        missing_copy_implementations,
        trivial_casts,
        trivial_numeric_casts,
        unsafe_code,
        unused_extern_crates,
        unused_import_braces,
        unused_qualifications)]

#[macro_use]
extern crate error_chain;
extern crate chrono;
extern crate futures;
extern crate hyper;
extern crate serde;
extern crate hyper_tls;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;
extern crate url;

use chrono::DateTime;
use chrono::offset::Utc;
use futures::{Future, Stream};
use hyper::{Body, Method, Request, Uri, Chunk, StatusCode};
use hyper::header::{Authorization, Bearer};
use serde::de;
use serde::de::Deserialize;
use serde::de::Deserializer;
use serde::de::Visitor;
use std::collections::HashMap;
use std::str::FromStr;
use std::string::String;
use tokio_core::reactor::Handle;
use url::Url;

/// Identifier for an account.
pub type AccountId = String;
/// Identifier for a transaction.
pub type TransactionId = String;
/// Identifier of a merchant.
pub type MerchantId = String;
/// Holds an ISO 4217 currency code.
pub type Currency = String;

/// Accounts represent a store of funds, and have a list of transactions.
#[derive(Debug, Deserialize)]
pub struct Account {
    /// The account id.
    pub id: AccountId,
    /// Description of the account.
    pub description: String,
    /// The timestamp when the account was created.
    pub created: DateTime<Utc>,
}

/// Response to the list accounts future.
#[derive(Debug, Deserialize)]
pub struct Accounts {
    /// List of accounts owned by the currenty authorized user.
    pub accounts: Vec<Account>,
}

/// Response to the balance future if successful.
#[derive(Debug, Deserialize)]
pub struct Balance {
    /// The currently available balance of the account, as a 64bit integer in minor units of the
    /// currency, eg. pennies for GBP, or cents for EUR and USD.
    pub balance: i64,
    /// The ISO 4217 currency code.
    pub currency: Currency,
    /// The amount spent from this account today (considered from approx 4am onwards), in minor
    /// units of the currency.
    pub spend_today: i64,
}

/// Deserializes a string but returns None on empty string.
fn none_for_empty_string<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
    T: Deserialize<'de> + FromStr,
    D: Deserializer<'de>,
{
    // This is a Visitor that forwards string types to T's `FromStr` impl if the string is
    // non-empty The `PhantomData` is to keep the compiler from complaining about T being an unused
    // generic type parameter. We need T in order to know the Value type for the Visitor impl.
    struct NonEmptyString<T>(std::marker::PhantomData<Option<T>>);

    impl<'de, T> Visitor<'de> for NonEmptyString<T>
    where
        T: Deserialize<'de> + FromStr,
    {
        type Value = Option<T>;

        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
            formatter.write_str("string")
        }

        fn visit_str<E>(self, value: &str) -> Result<Option<T>, E>
        where
            E: de::Error,
        {
            if value.is_empty() {
                return Ok(None);
            } else {
                let res = FromStr::from_str(value);
                match res {
                    Ok(good) => Ok(Some(good)),
                    // TODO: Find a way to propagate the error.
                    Err(_) => Err(de::Error::custom("could not parse string")),
                }
            }
        }

        fn visit_string<E>(self, value: String) -> Result<Option<T>, E>
        where
            E: de::Error,
        {
            self.visit_str(&value)
        }
    }

    deserializer.deserialize_any(NonEmptyString(std::marker::PhantomData))
}

/// Describes a transaction.
#[derive(Debug, Deserialize)]
pub struct Transaction {
    /// Balance in the account after the transaction.
    pub account_balance: i64,
    /// The amount of the transaction in minor units of currency. For example pennies in the case
    /// of GBP. A negative amount indicates a debit (most card transactions will have a negative
    /// amount).
    pub amount: i64,
    /// The timestamp in when the transaction was created.
    pub created: DateTime<Utc>,
    /// The ISO 4217 currency code.
    pub currency: Currency,
    /// Description of the transaction.
    pub description: String,
    /// The transaction id.
    pub id: TransactionId,
    /// This contains the merchant_id of the merchant that this transaction was made at.
    pub merchant: Option<MerchantId>,
    /// Key-value annotations made for transaction. Metadata is private to your application.
    pub metadata: HashMap<String, String>,
    /// Notes attached to the transaction.
    pub notes: String,
    /// Top-ups to an account are represented as transactions with a positive amount and
    /// is_load = true. Other transactions such as refunds, reversals or chargebacks may have a
    /// positive amount but is_load = false
    pub is_load: bool,
    /// The timestamp in UTC (RFC 3339) at which the transaction settled. In most cases, this
    /// happens 24-48 hours after created. If this field is not present, the transaction is
    /// authorised but not yet “complete”.
    ///
    /// Bug: Even though the Monzo documentation says the field is not present when not authorised,
    /// in practice they send an empty string. See https://github.com/monzo/docs/pull/59.
    #[serde(deserialize_with = "none_for_empty_string")]
    pub settled: Option<DateTime<Utc>>,
    /// The category can be set for each transaction by the user. Over time we learn which merchant
    /// goes in which category and auto-assign the category of a transaction. If the user hasn’t
    /// set a category, we’ll return the default category of the merchant on this transactions.
    /// Top-ups have category mondo. Valid values are general, eating_out, expenses, transport,
    /// cash, bills, entertainment, shopping, holidays, groceries.
    pub category: String,
    /// This is only present on declined transactions! Valid values are INSUFFICIENT_FUNDS,
    /// CARD_INACTIVE, CARD_BLOCKED or OTHER.
    // TODO: Make this an enum?
    pub decline_reason: Option<String>,
}

/// Response to the transactions future if successful.
#[derive(Debug, Deserialize)]
pub struct Transactions {
    /// List of transactions.
    pub transactions: Vec<Transaction>,
}

/// Response to the transaction future if successful.
#[derive(Debug, Deserialize)]
pub struct TransactionResponse {
    /// A single transaction.
    pub transaction: Transaction,
}

/// Response to the futures in case of an error.
#[derive(Debug, Deserialize)]
pub struct Error {
    /// The HTTP response code.
    pub code: Option<String>,
    /// Short description of the error.
    // TODO; Maybe make this an enum since the documentation says it can only contain a certain set
    // of values.
    pub error: Option<String>,
    /// Longer description of the error.
    pub error_description: Option<String>,
    /// Additional information.
    pub message: Option<String>,
}

/// Errors for this crate using `error_chain`.
pub mod errors {
    error_chain! {
        errors {
            #[doc = "When the Monzo API returns an error response code with more detailed \
            information."]
            BadResponse(statuscode: ::hyper::StatusCode, error: ::Error)
        }
        foreign_links {
            BadJsonResponse(::serde_json::Error)
            #[doc = "When the Monzo API returns invalid or unexpected json content."];
            NetworkError(::hyper::Error) #[doc = "Returned on network failure."];
        }
    }
}

/// The main interface for this crate.
#[derive(Debug)]
pub struct Client {
    client: hyper::client::Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>,
    access_token: String,
    base_url: Url,
}

/// The main interface for this crate.
impl Client {
    // The account_id param on requests.
    const ACCOUNT_ID: &'static str = "account_id";

    /// Creates a new Monzo client.
    pub fn new(handle: &Handle, access_token: &str) -> Client {
        Client::new_with_base_url(
            handle,
            access_token,
            "https://api.monzo.com".parse().unwrap(),
        )
    }

    /// Creates a new Monzo client with another base url. Useful for tests.
    pub fn new_with_base_url(handle: &Handle, access_token: &str, base_url: Url) -> Client {
        Client {
            client: ::hyper::Client::configure()
                .connector(::hyper_tls::HttpsConnector::new(4, handle).unwrap())
                .build(handle),
            access_token: access_token.into(),
            base_url: base_url,
        }
    }

    fn create_request(&self, uri: Uri) -> Request<Body> {
        let mut req: Request<Body> = Request::new(Method::Get, uri);
        req.headers_mut().set(Authorization(
            Bearer { token: self.access_token.clone() },
        ));
        req
    }

    fn make_request<T: 'static, F: 'static>(
        &self,
        uri: Uri,
        response_handler: F,
    ) -> Box<Future<Item = T, Error = errors::Error>>
    where
        F: Fn(Chunk) -> Result<T, errors::Error>,
    {
        let request = self.create_request(uri);
        let response: hyper::client::FutureResponse = self.client.request(request);
        let future = response
            .map_err(|err: hyper::Error| -> errors::Error { err.into() })
            .and_then(|res| {
                let status = res.status();
                res.body()
                    .concat2()
                    .map_err(|err: hyper::Error| err.into())
                    .and_then(move |body: Chunk| {
                        match status {
                            StatusCode::Ok => {}
                            _ => {
                                let error: Error = serde_json::from_slice(&body)?;
                                return Err(errors::ErrorKind::BadResponse(status, error).into());
                            }
                        };
                        response_handler(body)
                    })
            });

        Box::new(future)
    }

    /// Returns a list of accounts owned by the currently authorised user.
    pub fn accounts(&self) -> Box<Future<Item = Accounts, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("accounts");
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let a: Accounts = serde_json::from_slice(&body)?;
            Ok(a)
        })
    }

    /// Retrieve information about an account’s balance.
    pub fn balance(
        &self,
        account_id: AccountId,
    ) -> Box<Future<Item = Balance, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("balance");
        url.query_pairs_mut().append_pair(Client::ACCOUNT_ID, &account_id);
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let b: Balance = serde_json::from_slice(&body)?;
            Ok(b)
        })
    }

    /// Returns a list of transactions on the user’s account.
    pub fn transactions(
        &self,
        account_id: AccountId,
    ) -> Box<Future<Item = Transactions, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("transactions");
        url.query_pairs_mut().append_pair(Client::ACCOUNT_ID, &account_id);
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let t: Transactions = serde_json::from_slice(&body)?;
            Ok(t)
        })
    }

    /// Returns a list of transactions on the user’s account.
    pub fn transaction(
        &self,
        account_id: AccountId,
        transaction_id: TransactionId,
    ) -> Box<Future<Item = TransactionResponse, Error = errors::Error>> {
        let mut url = self.base_url.clone();
        url.path_segments_mut().unwrap().push("transactions");
        url.path_segments_mut().unwrap().push(&transaction_id);
        url.query_pairs_mut().append_pair(Client::ACCOUNT_ID, &account_id);
        let uri: Uri = url.into_string().parse().unwrap();

        self.make_request(uri, |body| {
            let t: TransactionResponse = serde_json::from_slice(&body)?;
            Ok(t)
        })
    }
}
<|endoftext|>


<commit_before>#![experimental]
#![feature(slicing_syntax)]
#![feature(macro_rules)]

use std::mem;

/// Calculate the crc64 checksum of the given data, starting with the given crc.
///
/// Implements the CRC64 used by Redis, which is the variant with "Jones" coefficients and init value of 0.
///
/// Specification of this CRC64 variant follows:
///
/// ```text
/// Name: crc-64-jones
/// Width: 64 bites
/// Poly: 0xad93d23594c935a9
/// Reflected In: True
/// Xor_In: 0xffffffffffffffff
/// Reflected_Out: True
/// Xor_Out: 0x0
/// Check("123456789"): 0xe9c6d914c4b8d9ca
/// ```
///
/// Example:
///
/// ```rust
/// let table = crc64::crc64_init();
/// crc64::crc64(table, 0, "123456789".as_bytes());
/// ```

fn crc_reflect(data: u64, len: uint) -> u64 {
    let mut data = data;
    let mut ret = data & 0x01;

    let mut i = 1u;
    while i < len {
        data >>= 1;
        ret = (ret << 1) | (data & 0x01);
        i+=1;
    }

    ret
}

fn crc64_trivial(crc: u64, in_data: &[u8]) -> u64 {
    let mut crc = crc;
    let len = in_data.len();

    let poly : u64 = 0xad93d23594c935a9;

    let mut bit : bool;

    let mut offset = 0u;

    while offset < len {
        let c = in_data[offset];
        let mut i = 0x01;
        while i & 0xff != 0x0 {
            bit = crc & 0x8000000000000000 != 0x0;
            if c & i != 0x0 {
                bit = !bit;
            }
            crc <<= 1;
            if bit {
                crc ^= poly;
            }
            i <<= 1;
        }
        crc &= 0xffffffffffffffff;
        offset+=1;
    }
    crc = crc & 0xffffffffffffffff;

    return crc_reflect(crc, 64) ^ 0x0000000000000000;
}

pub fn crc64_init() -> Vec<Vec<u64>> {
    let mut crc : u64;

    let mut table : Vec<Vec<u64>> = Vec::with_capacity(8);

    for _ in range(0, 8u) {
        table.push(Vec::with_capacity(256));
    };

    for n in range(0, 256u) {
        table[0].push(crc64_trivial(0, vec![n as u8].as_slice()));
        table[1].push(0);
        table[2].push(0);
        table[3].push(0);
        table[4].push(0);
        table[5].push(0);
        table[6].push(0);
        table[7].push(0);
    }

    for n in range(0, 256) {
        crc = table[0][n];
        for k in range(1, 8) {
            let idx  = (crc as uint) & 0xff;
            crc = table[0][idx] ^ (crc >> 8);
            table[k][n] = crc;
        }
    };

    table
}

// transmute slice of 8 u8 values to one u64 (drop the length)
macro_rules! slice_to_long {
    ($curVec:expr) => {
        {
            unsafe {
                let (tmp, _) : (*const u64, u64) = mem::transmute($curVec);
                *tmp
            }
        }
    }
}

pub fn crc64(table: Vec<Vec<u64>>, crc: u64, data: &[u8]) -> u64 {
    let mut crc = crc;
    let mut len = data.len();
    let mut offset = 0u;

    while len >= 8 {
        crc ^= slice_to_long!(data[offset..(offset+8)]);
        crc = table[7][(crc & 0xff) as uint] ^
              table[6][((crc >> 8) & 0xff) as uint] ^
              table[5][((crc >> 16) & 0xff) as uint] ^
              table[4][((crc >> 24) & 0xff) as uint] ^
              table[3][((crc >> 32) & 0xff) as uint] ^
              table[2][((crc >> 40) & 0xff) as uint] ^
              table[1][((crc >> 48) & 0xff) as uint] ^
              table[0][(crc >> 56) as uint];

        offset += 8;
        len -= 8;
    }

    while len > 0 {
        crc = table[0][((crc ^ data[offset] as u64) & 0xff) as uint] ^ (crc >> 8);
        offset += 1;
        len -= 1;
    }

    crc
}

#[test]
fn test_crc64_works() {
    let table = crc64_init();
    assert_eq!(0xe9c6d914c4b8d9ca, crc64(table, 0, "123456789".as_bytes()))
}
<commit_msg>Use new usize instead of uint<commit_after>#![experimental]
#![feature(slicing_syntax)]

use std::mem;

/// Calculate the crc64 checksum of the given data, starting with the given crc.
///
/// Implements the CRC64 used by Redis, which is the variant with "Jones" coefficients and init value of 0.
///
/// Specification of this CRC64 variant follows:
///
/// ```text
/// Name: crc-64-jones
/// Width: 64 bites
/// Poly: 0xad93d23594c935a9
/// Reflected In: True
/// Xor_In: 0xffffffffffffffff
/// Reflected_Out: True
/// Xor_Out: 0x0
/// Check("123456789"): 0xe9c6d914c4b8d9ca
/// ```
///
/// Example:
///
/// ```rust
/// let table = crc64::crc64_init();
/// crc64::crc64(table, 0, "123456789".as_bytes());
/// ```

fn crc_reflect(data: u64, len: usize) -> u64 {
    let mut data = data;
    let mut ret = data & 0x01;

    let mut i = 1us;
    while i < len {
        data >>= 1;
        ret = (ret << 1) | (data & 0x01);
        i+=1;
    }

    ret
}

fn crc64_trivial(crc: u64, in_data: &[u8]) -> u64 {
    let mut crc = crc;
    let len = in_data.len();

    let poly : u64 = 0xad93d23594c935a9;

    let mut bit : bool;

    let mut offset = 0us;

    while offset < len {
        let c = in_data[offset];
        let mut i = 0x01;
        while i & 0xff != 0x0 {
            bit = crc & 0x8000000000000000 != 0x0;
            if c & i != 0x0 {
                bit = !bit;
            }
            crc <<= 1;
            if bit {
                crc ^= poly;
            }
            i <<= 1;
        }
        crc &= 0xffffffffffffffff;
        offset+=1;
    }
    crc = crc & 0xffffffffffffffff;

    return crc_reflect(crc, 64) ^ 0x0000000000000000;
}

pub fn crc64_init() -> Vec<Vec<u64>> {
    let mut crc : u64;

    let mut table : Vec<Vec<u64>> = Vec::with_capacity(8);

    for _ in range(0, 8us) {
        table.push(Vec::with_capacity(256));
    };

    for n in range(0, 256us) {
        table[0].push(crc64_trivial(0, vec![n as u8].as_slice()));
        table[1].push(0);
        table[2].push(0);
        table[3].push(0);
        table[4].push(0);
        table[5].push(0);
        table[6].push(0);
        table[7].push(0);
    }

    for n in range(0, 256) {
        crc = table[0][n];
        for k in range(1, 8) {
            let idx  = (crc as usize) & 0xff;
            crc = table[0][idx] ^ (crc >> 8);
            table[k][n] = crc;
        }
    };

    table
}

// transmute slice of 8 u8 values to one u64 (drop the length)
macro_rules! slice_to_long {
    ($curVec:expr) => {
        {
            unsafe {
                let (tmp, _) : (*const u64, u64) = mem::transmute(&$curVec);
                *tmp
            }
        }
    }
}

pub fn crc64(table: Vec<Vec<u64>>, crc: u64, data: &[u8]) -> u64 {
    let mut crc = crc;
    let mut len = data.len();
    let mut offset = 0us;

    while len >= 8 {
        crc ^= slice_to_long!(data[offset..(offset+8)]);
        crc = table[7][(crc & 0xff) as usize] ^
              table[6][((crc >> 8) & 0xff) as usize] ^
              table[5][((crc >> 16) & 0xff) as usize] ^
              table[4][((crc >> 24) & 0xff) as usize] ^
              table[3][((crc >> 32) & 0xff) as usize] ^
              table[2][((crc >> 40) & 0xff) as usize] ^
              table[1][((crc >> 48) & 0xff) as usize] ^
              table[0][(crc >> 56) as usize];

        offset += 8;
        len -= 8;
    }

    while len > 0 {
        crc = table[0][((crc ^ data[offset] as u64) & 0xff) as usize] ^ (crc >> 8);
        offset += 1;
        len -= 1;
    }

    crc
}

#[test]
fn test_crc64_works() {
    let table = crc64_init();
    assert_eq!(0xe9c6d914c4b8d9ca, crc64(table, 0, "123456789".as_bytes()))
}
<|endoftext|>


<commit_before>use std::slice;

#[no_mangle]
pub extern fn mse_c (obs_pointer: *const f64,
    sim_pointer: *const f64, arr_size: usize
) -> f64 {

    let obs_arr = unsafe {
            std::slice::from_raw_parts(
                obs_pointer as *const f64,
                arr_size as usize)
    };
    let sim_arr = unsafe {
            std::slice::from_raw_parts(
                sim_pointer as *const f64,
                arr_size as usize)
    };

    return mse( obs_arr, sim_arr);
}

#[no_mangle]
pub extern fn rmse_c (obs_pointer: *const f64,
    sim_pointer: *const f64, arr_size: usize
) -> f64 {

    let obs_arr = unsafe {
            std::slice::from_raw_parts(
                obs_pointer as *const f64,
                arr_size as usize)
    };
    let sim_arr = unsafe {
            std::slice::from_raw_parts(
                sim_pointer as *const f64,
                arr_size as usize)
    };

    return rmse( obs_arr, sim_arr);
}

fn mse(obs: &[f64], sim: &[f64]) -> f64 {
    let mut sum_y: f64 = 0.0;

    for (o, s) in obs.iter().zip(sim.iter()) {
        let delta = s - o;
        sum_y += delta.powf(2.0);
    }
    let len: f64 = obs.len() as f64;
    return sum_y / len;
}

fn rmse(obs: &[f64], sim: &[f64]) -> f64 {
    return mse(obs, sim).sqrt();
}

#[test]
fn test_rmse() {
    let test_obs = &[13.,17.,18.,20.,24.];
    let test_sim = &[12.,15.,20.,22.,24.];

    let result = rmse(test_obs, test_sim);
    assert_eq!(result, (2.6 as f64).sqrt());
}

#[test]
fn test_rmse_perfect() {
    let test_obs = &[1.,2.,3.,4.,5.];
    let test_sim = &[1.,2.,3.,4.,5.];

    let result = rmse(test_obs, test_sim);
    assert_eq!(result, (0 as f64));
}

#[test]
fn test_rmse_bad() {
    let obs: [f64; 5] = [1.,2.,3.,4.,5.];

    let sum: f64 = obs.iter().fold((0 as f64), std::ops::Add::add);
    let m = sum / (obs.len() as f64);
    let sim = [m, m, m, m, m];
    let result = rmse(
        &[1.,2.,3.,4.,5.],
        &sim
    );

    assert_eq!(result, (2.0 as f64).sqrt());
}

#[test]
fn test_mse() {
    let test_obs = &[13.,17.,18.,20.,24.];
    let test_sim = &[12.,15.,20.,22.,24.];

    let result = mse(test_obs, test_sim);
    assert_eq!(result, 2.6);
}

#[test]
fn test_mse_perfect() {
    let result = mse(&[1.,2.,3.,4.,5.],
                  &[1.,2.,3.,4.,5.]);

    assert_eq!(result, 0.0);
}

#[test]
fn test_mse_bad() {
    let obs: [f64; 5] = [1.,2.,3.,4.,5.];

    // Hard coded because I haven't worked out how to sum Vec in rust successfully
    let sum: f64 = 15.0;
    let m = sum / (obs.len() as f64);
    let sim = [m, m, m, m, m];
    let result = mse(
        &[1.,2.,3.,4.,5.],
        &sim
    );

    assert_eq!(result, 2.0);
}
<commit_msg>Actually sum instead of using hard coded value<commit_after>use std::slice;

#[no_mangle]
pub extern fn mse_c (obs_pointer: *const f64,
    sim_pointer: *const f64, arr_size: usize
) -> f64 {

    let obs_arr = unsafe {
            std::slice::from_raw_parts(
                obs_pointer as *const f64,
                arr_size as usize)
    };
    let sim_arr = unsafe {
            std::slice::from_raw_parts(
                sim_pointer as *const f64,
                arr_size as usize)
    };

    return mse( obs_arr, sim_arr);
}

#[no_mangle]
pub extern fn rmse_c (obs_pointer: *const f64,
    sim_pointer: *const f64, arr_size: usize
) -> f64 {

    let obs_arr = unsafe {
            std::slice::from_raw_parts(
                obs_pointer as *const f64,
                arr_size as usize)
    };
    let sim_arr = unsafe {
            std::slice::from_raw_parts(
                sim_pointer as *const f64,
                arr_size as usize)
    };

    return rmse( obs_arr, sim_arr);
}

fn mse(obs: &[f64], sim: &[f64]) -> f64 {
    let mut sum_y: f64 = 0.0;

    for (o, s) in obs.iter().zip(sim.iter()) {
        let delta = s - o;
        sum_y += delta.powf(2.0);
    }
    let len: f64 = obs.len() as f64;
    return sum_y / len;
}

fn rmse(obs: &[f64], sim: &[f64]) -> f64 {
    return mse(obs, sim).sqrt();
}

#[test]
fn test_rmse() {
    let test_obs = &[13.,17.,18.,20.,24.];
    let test_sim = &[12.,15.,20.,22.,24.];

    let result = rmse(test_obs, test_sim);
    assert_eq!(result, (2.6 as f64).sqrt());
}

#[test]
fn test_rmse_perfect() {
    let test_obs = &[1.,2.,3.,4.,5.];
    let test_sim = &[1.,2.,3.,4.,5.];

    let result = rmse(test_obs, test_sim);
    assert_eq!(result, (0 as f64));
}

#[test]
fn test_rmse_bad() {
    let obs: [f64; 5] = [1.,2.,3.,4.,5.];

    let sum: f64 = obs.iter().fold(0f64, std::ops::Add::add);
    let m = sum / (obs.len() as f64);
    let sim = [m, m, m, m, m];
    let result = rmse(
        &[1.,2.,3.,4.,5.],
        &sim
    );

    assert_eq!(result, (2.0 as f64).sqrt());
}

#[test]
fn test_mse() {
    let test_obs = &[13.,17.,18.,20.,24.];
    let test_sim = &[12.,15.,20.,22.,24.];

    let result = mse(test_obs, test_sim);
    assert_eq!(result, 2.6);
}

#[test]
fn test_mse_perfect() {
    let result = mse(&[1.,2.,3.,4.,5.],
                  &[1.,2.,3.,4.,5.]);

    assert_eq!(result, 0.0);
}

#[test]
fn test_mse_bad() {
    let obs: [f64; 5] = [1.,2.,3.,4.,5.];

    let sum: f64 = obs.iter().fold(0f64, std::ops::Add::add);
    let m = sum / (obs.len() as f64);
    let sim = [m, m, m, m, m];
    let result = mse(
        &[1.,2.,3.,4.,5.],
        &sim
    );

    assert_eq!(result, 2.0);
}
<|endoftext|>


<commit_before>
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Vacant, Occupied};

#[derive(Clone, Copy, Eq, PartialEq, Hash)]
struct ObjectUid(u64);
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
struct ObjectTableIndex(u32);

pub trait Encodable<ECX> {

    fn encode<'encodable, 'sess>(&'encodable self,
                                         session: &mut EncodingSession<'sess, ECX>)
        where 'encodable: 'sess;
}

pub trait EncodableObject<ECX> : Encodable<ECX> {
    fn object_uid(&self) -> ObjectUid;
    fn encode_contents<'encodable, 'sess>(&'encodable self,
                                          session: &mut EncodingSession<'sess, ECX>)
        where 'encodable: 'sess;
}

pub trait Encoder {
    fn emit_u32(&mut self, x: u32);
    fn position(&self) -> u64;
    fn finalize(self: Box<Self>, four_cc: [u8; 4], object_table_address: u64);
}

pub struct EncodingSession<'sess, ECX: 'sess> {
    encoder: Box<Encoder>,
    object_table_indices: HashMap<ObjectUid, ObjectTableIndex>,
    object_table: Vec<u64>,
    queued_objects: Vec<(&'sess EncodableObject<ECX>, ObjectTableIndex)>,
    pub context: ECX
}

impl<'sess, ECX: 'sess> EncodingSession<'sess, ECX> {

    pub fn encoder(&mut self) -> &mut Encoder {
        &mut *self.encoder
    }

    pub fn encode_object<'object, O>(&mut self, object: &'object O)
        where O: EncodableObject<ECX>,
              'object: 'sess
    {
        let object_uid = EncodableObject::object_uid(object);
        let (object_table_index, is_new) = self.get_object_table_index(object_uid);

        self.encoder().emit_u32(object_table_index.0);

        if is_new {
            self.enqueue_object_encoding(object_table_index,
                                         object as &'sess EncodableObject<ECX>);
        }
    }

    pub fn finalize(self, four_cc: [u8; 4]) {
        let object_table_address = self.encoder.position();

        // TODO: write object table

        self.encoder.finalize(four_cc, object_table_address);
    }

    fn get_object_table_index(&mut self, object_uid: ObjectUid) -> (ObjectTableIndex, bool) {
        match self.object_table_indices.entry(object_uid) {
            Occupied(occupied) => (*occupied.get(), false),
            Vacant(vacant) => {
                // TODO: make this a safe conversion
                let index = self.object_table.len() as u32;
                self.object_table.push(u64::max_value());
                (ObjectTableIndex(index), true)
            }
        }
    }

    fn write_enqueued_objects(&mut self) {
        loop {
            // encoding objects might add more to this queue, so we can't do
            // this in a for loop
            let item = self.queued_objects.pop();

            match item {
                Some((object, object_table_index)) => {
                    let position = self.encoder.position();
                    let queue_index = self.queued_objects.len();
                    object.encode_contents(self);
                    // Now that we know the address, write it to the table
                    self.object_table[object_table_index.0 as usize] = position;
                },
                None => break,
            }
        }
    }

    fn enqueue_object_encoding(&mut self,
                               object_table_index: ObjectTableIndex,
                               encodable: &'sess EncodableObject<ECX>) {
        self.queued_objects.push((encodable, object_table_index));
    }
}

pub struct EncodingSessionRef<'sess, ECX: 'sess> {
    session: EncodingSession<'sess, ECX>
}

impl<'sess, ECX: 'sess> EncodingSessionRef<'sess, ECX> {

    pub fn new<E: Encoder+'static>(encoder: E, ecx: ECX) -> EncodingSessionRef<'sess, ECX> {
        EncodingSessionRef {
            session: EncodingSession {
                encoder: Box::new(encoder),
                object_table_indices: HashMap::new(),
                object_table: Vec::new(),
                queued_objects: Vec::new(),
                context: ecx
            }
        }
    }

    pub fn encode<'encodable: 'sess, T: Encodable<ECX>>(&mut self,
                                                        encodable: &'encodable T) {
        encodable.encode(&mut self.session);
        self.session.write_enqueued_objects();
    }
}

pub trait Decodable<DCX> {
    fn decode(session: &mut DecodingSession<DCX>) -> Self;
}

pub trait DecodableObject<DCX> : Decodable<DCX> {
    fn decode_contents(session: &mut DecodingSession<DCX>) -> Self;
}

pub trait Decoder {
    fn set_position(&mut self, position: u64);
    fn position(&self) -> u64;
    fn read_u32(&mut self) -> u32;
}

pub struct DecodingSession<D: Decoder, DCX> {
    decoder: D,
    context: DCX,
    object_table: Vec<u64>
}

impl<DCX> DecodingSession<DCX> {

    pub fn decode_object<T:DecodableObject<DCX>>(&mut self) -> T {
        let object_table_index = self.decoder.read_u32();

        let address = self.object_table[object_table_index];

        let current_position = self.decoder.position();
        self.decoder.set_position(address);

        let object = DecodableObject::decode_contents(self);

        self.decoder.set_position(current_position);

        object
    }
}

pub struct DecodingSessionRef<D: Decoder, DCX> {
    session: DecodingSession<D, DCX>
}

impl<D: Decoder, DCX> DecodingSessionRef<D, DCX> {

    pub fn decode<T: Decodable<DCX>>(&mut self) -> T {
        Decodable::decode(self.session)
    }
}
<commit_msg>add a description of the framework<commit_after>
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Vacant, Occupied};

//! A serialization framework supporting the following features:
//!
//! - Arbitrary types can implement the `Encodable` and `Decodable` traits
//!   to support serialization
//! - Serialization can be "context-aware", that is, `Encodables` and
//!   `Decodables` can specify what kind of context they need to be serialized
//!   or deserialized. For example, certain values may always need to be
//!   interned at runtime. Such a value would implement `Decodable` with a
//!   context from which the needed interner is reachable.
//! - The framework supports "objects", that is, types can implement the
//!   `EncodableObject` and `DecodableObject` traits, which will make their
//!   actual data only be emitted once within some encoded dataset. Other
//!   `Encodables` only store a reference to where the objects data is located.
//! - `Encodables` do not need to know there encoded size beforehand and can
//!   indeed be of variable size. This allows for space-efficient encodings
//!   like using the LEB128 format for integers.
//! - Encoding and decoding generally does not need to do dynamic memory
//!   allocation.
//! - The API is designed in a way that should allow for easily auto-generating
//!   serialization and deserialization code.
//! - Completely safe implementation (no `unsafe` used).

#[derive(Clone, Copy, Eq, PartialEq, Hash)]
pub struct ObjectUid(u64);
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
pub struct ObjectTableIndex(u32);

/// Something that can be encoded given a certain context ECX.
pub trait Encodable<ECX> {
    fn encode<'ecx, 'encodable>(&'encodable self,
                                session: &mut EncodingContext<'ecx, ECX>)
        where 'encodable: 'ecx;
}

/// Values implementing this trait will only be emitted once during an
/// EncodingSession. Other values referencing them only store an address where
/// actual object can be found within the encoded data.
pub trait EncodableObject<ECX> : Encodable<ECX> {
    fn object_uid(&self) -> ObjectUid;

    fn encode_contents<'encodable, 'ecx>(&'encodable self,
                                         session: &mut EncodingContext<'ecx, ECX>)
        where 'encodable: 'ecx;
}

pub trait Encoder {
    fn emit_u32(&mut self, value: u32);
    fn emit_u64(&mut self, value: u64);
    fn position(&self) -> u64;
    fn finalize(self: Box<Self>, four_cc: [u8; 4], object_table_address: u64);
}

pub struct EncodingContext<'ctx, ECX: 'ctx> {
    encoder: &'ctx mut Encoder,
    object_table_indices: &'ctx mut HashMap<ObjectUid, ObjectTableIndex>,
    object_table: &'ctx mut Vec<u64>,
    delayed_writes: &'ctx mut Vec<(&'ctx EncodableObject<ECX>, ObjectTableIndex)>,
    pub extra: &'ctx mut ECX
}

impl<'sess, ECX: 'sess> EncodingContext<'sess, ECX> {

    pub fn encoder(&mut self) -> &mut Encoder {
        &mut *self.encoder
    }

    pub fn encode_object<'object, O>(&mut self, object: &'object O)
        where O: EncodableObject<ECX>,
              'object: 'sess
    {
        let object_uid = EncodableObject::object_uid(object);
        let (object_table_index, is_new) = self.get_object_table_index(object_uid);

        self.encoder().emit_u32(object_table_index.0);

        if is_new {
            self.enqueue_object_encoding(object_table_index,
                                         object as &'sess EncodableObject<ECX>);
        }
    }

    fn get_object_table_index(&mut self, object_uid: ObjectUid) -> (ObjectTableIndex, bool) {
        match self.object_table_indices.entry(object_uid) {
            Occupied(occupied) => (*occupied.get(), false),
            Vacant(vacant) => {
                // TODO: make this a safe conversion
                let index = ObjectTableIndex(self.object_table.len() as u32);
                vacant.insert(index);
                self.object_table.push(u64::max_value());
                (index, true)
            }
        }
    }

    fn write_enqueued_objects(&mut self) {
        loop {
            // encoding objects might add more to this queue, so we can't do
            // this in a for loop
            let item = self.delayed_writes.pop();

            match item {
                Some((object, object_table_index)) => {
                    let position = self.encoder.position();
                    object.encode_contents(self);
                    // Now that we know the address, write it to the table
                    self.object_table[object_table_index.0 as usize] = position;
                },
                None => break,
            }
        }
    }

    fn enqueue_object_encoding(&mut self,
                               object_table_index: ObjectTableIndex,
                               encodable: &'sess EncodableObject<ECX>) {
        self.delayed_writes.push((encodable, object_table_index));
    }
}

pub struct EncodingSession<ECX> {
    encoder: Box<Encoder>,
    object_table_indices: HashMap<ObjectUid, ObjectTableIndex>,
    object_table: Vec<u64>,
    pub context: ECX
}

impl<ECX> EncodingSession<ECX> {

    pub fn new<E: Encoder+'static>(encoder: E, ecx: ECX) -> EncodingSession<ECX> {
        EncodingSession {
            encoder: Box::new(encoder),
            object_table_indices: HashMap::new(),
            object_table: Vec::new(),
            context: ecx
        }
    }

    pub fn encode<T: Encodable<ECX>>(&mut self, encodable: &T) {
        let mut delayed_writes = Vec::new();

        let mut context = EncodingContext {
            encoder: &mut *self.encoder,
            object_table_indices: &mut self.object_table_indices,
            object_table: &mut self.object_table,
            delayed_writes: &mut delayed_writes,
            extra: &mut self.context,
        };

        encodable.encode(&mut context);
        context.write_enqueued_objects();
    }

    pub fn finalize(mut self, four_cc: [u8; 4]) {
        let object_table_address = self.encoder.position();

        for object_table_entry in self.object_table {
            self.encoder.emit_u64(object_table_entry);
        }

        self.encoder.finalize(four_cc, object_table_address);
    }
}

pub trait Decodable<DCX> {
    fn decode(context: &mut DecodingContext<DCX>) -> Self;
}

pub trait DecodableObject<DCX> : Decodable<DCX> {
    fn decode_contents(context: &mut DecodingContext<DCX>) -> Self;
}

pub trait Decoder {
    fn set_position(&mut self, position: u64);
    fn position(&self) -> u64;
    fn read_u32(&mut self) -> u32;
}

pub struct DecodingContext<'ctx, DCX> {
    decoder: &'ctx mut Decoder,
    object_table: Vec<u64>,
    pub extra: DCX,
}

impl<'ctx, DCX> DecodingContext<'ctx, DCX> {

    pub fn decoder(&mut self) -> &mut Decoder {
        self.decoder
    }

    pub fn decode_object<T:DecodableObject<DCX>>(&mut self) -> T {
        let object_table_index = self.decoder.read_u32();

        let address = self.object_table[object_table_index as usize];

        let current_position = self.decoder.position();
        self.decoder.set_position(address);

        let object = DecodableObject::decode_contents(self);

        self.decoder.set_position(current_position);

        object
    }
}

pub struct DecodingSession<'ctx, DCX> {
    context: DecodingContext<'ctx, DCX>
}

impl<'ctx, DCX> DecodingSession<'ctx, DCX> {

    pub fn decode<T: Decodable<DCX>>(&mut self) -> T {
        Decodable::decode(&mut self.context)
    }
}
<|endoftext|>


<commit_before>// TODO: deny missing docs
#![allow(missing_docs)]
// for mem::discriminant_value
#![feature(discriminant_value)]

extern crate futures;
extern crate tokio_core;
extern crate trust_dns;

use futures::Future;
use futures::future::join_all;
use std::net::{IpAddr, SocketAddr};
use std::str::FromStr;
use tokio_core::reactor::Handle;
use trust_dns::client::{ClientFuture, ClientHandle};
use trust_dns::rr::domain;
use trust_dns::rr::{DNSClass, Record, RecordType};
use trust_dns::udp::UdpClientStream;

#[derive(Debug)]
pub struct DnsResponse {
    pub server: IpAddr,
    pub answers: Vec<Record>,
}

pub type Result = std::result::Result<DnsResponse, Box<std::error::Error>>;

pub fn lookup<T: Into<SocketAddr>>(
    loop_handle: &Handle,
    domain_name: &str,
    server: T,
    record_type: RecordType
) -> Box<Future<Item=Result, Error=()>> {
    let socket_address = server.into();
    let (stream, sender) = UdpClientStream::new(socket_address, loop_handle);
    let mut client = ClientFuture::new(stream, sender, loop_handle, None);
    let domain_name = domain::Name::from_str(domain_name).unwrap();

    Box::new(
        client
            .query(domain_name, DNSClass::IN, record_type)
            .map(move |mut response| {
                Ok(DnsResponse { server: socket_address.ip(), answers: response.take_answers() })
            })
            .map_err(move |_| ()),
    )
}

pub fn multiple_lookup<T: Into<SocketAddr>>(
    loop_handle: &Handle,
    domain_name: &str,
    servers: Vec<T>,
    record_type: RecordType ,
) -> Box<Future<Item=Vec<Result>, Error=()>> {
    let futures: Vec<_> = servers
        .into_iter()
        .map(|server| lookup(loop_handle, domain_name, server, record_type))
        .collect();

    Box::new(join_all(futures))
}

#[cfg(test)]
mod test {
    use super::*;
    use tokio_core::reactor::Core;
    use std::mem;

    #[test]
    fn lookup_with_google() {
        let mut io_loop = Core::new().unwrap();
        let host = "example.com";
        let server = (Ipv4Addr::from_str("8.8.8.8").unwrap(), 53);

        let lookup = lookup(&io_loop.handle(), host, server, RecordType::A);
        let result = io_loop.run(lookup).unwrap();
        let response: DnsResponse = result.unwrap();

        assert_eq!(response.server, Ipv4Addr::from_str("8.8.8.8").unwrap());
        assert_eq!(response.answers.len(), 1);
        assert!(is_A_record(response.answers[0].rdata()));
        if let RData::A(ip) = *response.answers[0].rdata() {
            assert_eq!(ip, Ipv4Addr::new(93, 184, 216, 34));
        }
    }

    #[test]
    fn multiple_lookup_with_google() {
        let mut io_loop = Core::new().unwrap();
        let host = "example.com";
        let servers = vec![
            (Ipv4Addr::from_str("8.8.8.8").unwrap(), 53),
            (Ipv4Addr::from_str("8.8.4.4").unwrap(), 53),
        ];

        let lookup = multiple_lookup(&io_loop.handle(), host, servers, RecordType::A);
        let mut responses: Vec<_> = io_loop.run(lookup).unwrap();
        assert_eq!(responses.len(), 2);

        let response = responses.pop().unwrap().unwrap();
        assert_eq!(response.server, Ipv4Addr::from_str("8.8.4.4").unwrap());
        assert_eq!(response.answers.len(), 1);
        assert!(is_A_record(response.answers[0].rdata()));
        if let RData::A(ip) = *response.answers[0].rdata() {
            assert_eq!(ip, Ipv4Addr::new(93, 184, 216, 34));
        }

        let response = responses.pop().unwrap().unwrap();
        assert_eq!(response.server, Ipv4Addr::from_str("8.8.8.8").unwrap());
        assert_eq!(response.answers.len(), 1);
        assert!(is_A_record(response.answers[0].rdata()));
        if let RData::A(ip) = *response.answers[0].rdata() {
            assert_eq!(ip, Ipv4Addr::new(93, 184, 216, 34));
        }
    }

    #[allow(non_snake_case)]
    fn is_A_record(rdata: &RData) -> bool {
        mem::discriminant(rdata) == mem::discriminant(&RData::A(Ipv4Addr::new(127, 0, 0, 1)))
    }
}
<commit_msg>Fixed tests<commit_after>// TODO: deny missing docs
#![allow(missing_docs)]
// for mem::discriminant_value
#![feature(discriminant_value)]

extern crate futures;
extern crate tokio_core;
extern crate trust_dns;

use futures::Future;
use futures::future::join_all;
use std::net::{IpAddr, SocketAddr};
use std::str::FromStr;
use tokio_core::reactor::Handle;
use trust_dns::client::{ClientFuture, ClientHandle};
use trust_dns::rr::domain;
use trust_dns::rr::{DNSClass, Record, RecordType};
use trust_dns::udp::UdpClientStream;

#[derive(Debug)]
pub struct DnsResponse {
    pub server: IpAddr,
    pub answers: Vec<Record>,
}

pub type Result = std::result::Result<DnsResponse, Box<std::error::Error>>;

pub fn lookup<T: Into<SocketAddr>>(
    loop_handle: &Handle,
    domain_name: &str,
    server: T,
    record_type: RecordType
) -> Box<Future<Item=Result, Error=()>> {
    let socket_address = server.into();
    let (stream, sender) = UdpClientStream::new(socket_address, loop_handle);
    let mut client = ClientFuture::new(stream, sender, loop_handle, None);
    let domain_name = domain::Name::from_str(domain_name).unwrap();

    Box::new(
        client
            .query(domain_name, DNSClass::IN, record_type)
            .map(move |mut response| {
                Ok(DnsResponse { server: socket_address.ip(), answers: response.take_answers() })
            })
            .map_err(move |_| ()),
    )
}

pub fn multiple_lookup<T: Into<SocketAddr>>(
    loop_handle: &Handle,
    domain_name: &str,
    servers: Vec<T>,
    record_type: RecordType ,
) -> Box<Future<Item=Vec<Result>, Error=()>> {
    let futures: Vec<_> = servers
        .into_iter()
        .map(|server| lookup(loop_handle, domain_name, server, record_type))
        .collect();

    Box::new(join_all(futures))
}

#[cfg(test)]
mod test {
    use super::*;
    use std::mem;
    use std::net::Ipv4Addr;
    use tokio_core::reactor::Core;
    use trust_dns::rr::{RData, RecordType};

    #[test]
    fn lookup_with_google() {
        let mut io_loop = Core::new().unwrap();
        let host = "example.com";
        let server = (Ipv4Addr::from_str("8.8.8.8").unwrap(), 53);

        let lookup = lookup(&io_loop.handle(), host, server, RecordType::A);
        let result = io_loop.run(lookup).unwrap();
        let response: DnsResponse = result.unwrap();

        assert_eq!(response.server, Ipv4Addr::from_str("8.8.8.8").unwrap());
        assert_eq!(response.answers.len(), 1);
        assert!(is_A_record(response.answers[0].rdata()));
        if let RData::A(ip) = *response.answers[0].rdata() {
            assert_eq!(ip, Ipv4Addr::new(93, 184, 216, 34));
        }
    }

    #[test]
    fn multiple_lookup_with_google() {
        let mut io_loop = Core::new().unwrap();
        let host = "example.com";
        let servers = vec![
            (Ipv4Addr::from_str("8.8.8.8").unwrap(), 53),
            (Ipv4Addr::from_str("8.8.4.4").unwrap(), 53),
        ];

        let lookup = multiple_lookup(&io_loop.handle(), host, servers, RecordType::A);
        let mut responses: Vec<_> = io_loop.run(lookup).unwrap();
        assert_eq!(responses.len(), 2);

        let response = responses.pop().unwrap().unwrap();
        assert_eq!(response.server, Ipv4Addr::from_str("8.8.4.4").unwrap());
        assert_eq!(response.answers.len(), 1);
        assert!(is_A_record(response.answers[0].rdata()));
        if let RData::A(ip) = *response.answers[0].rdata() {
            assert_eq!(ip, Ipv4Addr::new(93, 184, 216, 34));
        }

        let response = responses.pop().unwrap().unwrap();
        assert_eq!(response.server, Ipv4Addr::from_str("8.8.8.8").unwrap());
        assert_eq!(response.answers.len(), 1);
        assert!(is_A_record(response.answers[0].rdata()));
        if let RData::A(ip) = *response.answers[0].rdata() {
            assert_eq!(ip, Ipv4Addr::new(93, 184, 216, 34));
        }
    }

    #[allow(non_snake_case)]
    fn is_A_record(rdata: &RData) -> bool {
        mem::discriminant(rdata) == mem::discriminant(&RData::A(Ipv4Addr::new(127, 0, 0, 1)))
    }
}
<|endoftext|>


<commit_before>#![feature(rust_2018_preview, uniform_paths)]
//! Simple efficient composable primitives for pretty printing.
//!
//! The implementation is derived from the paper ["A New Approach to Optimal Code Formatting"](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44667.pdf)
//! by Phillip M. Yelland.

extern crate unicode_width;

mod knot_column;
mod knot_set;
mod linear_value;
mod resolved_layout;
mod shared_string;

use std::collections as col;
use std::fmt;
use std::rc;

use shared_string::SharedString;

const OVERFLOW_COST: f32 = 100.0;
const NEWLINE_COST: f32 = 1.0;

/// The primary representation of pretty-printed text. Logically, it represents a set of
/// possible permissible layouts of text.
///
/// Layouts are constructed with four different primitives:
///
/// 1. Text
///
///    A literal string which is laid out as written. Its length is obtained using the
///    `unicode-width` package.
///
/// 2. Stack
///
///    Vertically stacks two layouts. The left margins of the two layouts will be
///    aligned.
///
/// 3. Juxtapose
///
///    Horizontally juxtapose two layouts. The left margin of the second layout
///    will be aligned with the end of the first layout's last line.
///
/// 4. Choice
///
///    Creates a choice between two or more layouts. The choice is made at layout
///    time based on the cost of each possible layout. See the `layout` method.
#[derive(Clone)]
pub struct Layout(rc::Rc<LayoutContents>);

impl Layout {
  fn with_contents(contents: LayoutContents) -> Layout {
    Layout(rc::Rc::new(contents))
  }

  fn contents(&self) -> &LayoutContents {
    &*self.0
  }

  /// Create a text layout value. This is a literal string with no layout variance.
  pub fn text(lit_text: impl Into<String>) -> Layout {
    Layout::with_contents(LayoutContents::Text(lit_text.into().into()))
  }

  fn choice_pair(first: &Layout, second: &Layout) -> Layout {
    // We should canonicalize this so that the choices are always in the same order.
    Layout::with_contents(LayoutContents::Choice(first.clone(), second.clone()))
  }

  fn stack_pair(top: &Layout, bottom: &Layout) -> Layout {
    Layout::with_contents(LayoutContents::Stack(top.clone(), bottom.clone()))
  }

  /// Create a layout that is the juxtaposition of two other layouts.
  ///
  /// This lays out the latter layout immediately to the right of the last line
  /// of the left layout.
  pub fn juxtapose_pair(left: &Layout, right: &Layout) -> Layout {
    let mut builder = JuxtaposeBuilder::new(right);
    builder.juxtapose(left)
  }

  /// Creates a layout that is the lowest-cost choice of layouts provided.
  pub fn choices<'a>(items: impl AsRef<[&'a Layout]>) -> Layout {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].clone();
    for item in &items[1..] {
      curr_layout = Layout::choice_pair(&curr_layout, item);
    }

    curr_layout
  }

  /// Create a stack of the layouts, where each of the layouts are
  /// vertically stacked on top of each other in the order provided.
  pub fn stack<'a>(items: impl AsRef<[&'a Layout]>) -> Layout {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].clone();
    for item in &items[1..] {
      curr_layout = Layout::stack_pair(&curr_layout, item);
    }
    curr_layout
  }

  /// Creates a juxtoposition of layouts, with each layout immediately
  /// following the last line of the previous layout.
  pub fn juxtapose<'a>(items: impl AsRef<[&'a Layout]>) -> Layout {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].clone();
    for item in &items[1..] {
      curr_layout = Layout::juxtapose_pair(&curr_layout, item);
    }
    curr_layout
  }

  /// Lays out the contents of this layout for a text buffer of width margin.
  pub fn layout(&self, margin: u16) -> String {
    self.layout_with_costs(margin, OVERFLOW_COST, NEWLINE_COST)
  }

  /// Lays out the contents of this layout for a text buffer of width margin, and with
  /// newline costs and overflow costs as provided.
  ///
  /// For each character over the margin width, the overflow cost is incurred. For each
  /// newline in the result, the newline cost is incurred. The layout chosen is that with
  /// the smallest overall cost.
  pub fn layout_with_costs(&self, margin: u16, overflow_cost: f32, newline_cost: f32) -> String {
    let final_layout = knot_set::do_layout(self, overflow_cost, newline_cost, margin);
    return final_layout.to_text(0);
  }

  #[doc(hidden)]
  pub fn debug_num_nodes(&self) -> usize {
    let mut counter = NodeCounter::new();
    counter.visit_node(self);
    counter.get_count()
  }
}

impl fmt::Debug for Layout {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    <LayoutContents as fmt::Debug>::fmt(&*self.0, f)
  }
}

#[derive(Debug)]
enum LayoutContents {
  Text(SharedString),
  Choice(Layout, Layout),
  Stack(Layout, Layout),
  Juxtapose(SharedString, Layout),
}

struct JuxtaposeBuilder {
  right: Layout,
  memo: col::BTreeMap<*const LayoutContents, Layout>,
}

impl JuxtaposeBuilder {
  fn new(right: &Layout) -> Self {
    JuxtaposeBuilder {
      right: right.clone(),
      memo: col::BTreeMap::new(),
    }
  }

  fn juxtapose(&mut self, left: &Layout) -> Layout {
    if let Some(v) = self.memo.get(&(left.contents() as *const LayoutContents)) {
      return v.clone();
    }

    let new_layout = match left.contents() {
      LayoutContents::Text(t) => {
        Layout::with_contents(LayoutContents::Juxtapose(t.clone(), self.right.clone()))
      }
      LayoutContents::Choice(first, second) => Layout::with_contents(LayoutContents::Choice(
        self.juxtapose(first),
        self.juxtapose(second),
      )),
      LayoutContents::Stack(top, bottom) => {
        Layout::with_contents(LayoutContents::Stack(top.clone(), self.juxtapose(bottom)))
      }
      LayoutContents::Juxtapose(text, jux_right) => Layout::with_contents(
        LayoutContents::Juxtapose(text.clone(), self.juxtapose(jux_right)),
      ),
    };

    self
      .memo
      .insert(left.contents() as *const LayoutContents, new_layout.clone());
    new_layout
  }
}

struct NodeCounter {
  seen: col::BTreeSet<*const LayoutContents>,
}

impl NodeCounter {
  fn new() -> Self {
    NodeCounter {
      seen: col::BTreeSet::new(),
    }
  }
  fn visit_node(&mut self, layout: &Layout) {
    if self.seen.insert(layout.contents() as *const LayoutContents) {
      use LayoutContents::*;
      match layout.contents() {
        Text(_) => {}
        Choice(first, second) => {
          self.visit_node(first);
          self.visit_node(second);
        }
        Stack(top, bottom) => {
          self.visit_node(top);
          self.visit_node(bottom);
        }
        Juxtapose(_left, right) => {
          self.visit_node(right);
        }
      }
    }
  }

  fn get_count(&self) -> usize {
    self.seen.len()
  }
}

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

  #[test]
  fn test_simple_set() {
    let foo = Layout::text("foo");
    let pair = Layout::juxtapose(&[&foo, &foo]);
    assert_eq!(pair.layout(10), "foofoo");
  }

  #[test]
  fn test_simple_stack() {
    let foo = Layout::text("foo");
    let pair = Layout::stack(&[&foo, &foo]);
    assert_eq!(pair.layout(10), "foo\nfoo");
  }

  #[test]
  fn text_simple_choice() {
    let foo = Layout::text("foo");
    let pair = Layout::choices(&[
      &Layout::juxtapose(&[&foo, &foo]),
      &Layout::stack(&[&foo, &foo]),
    ]);
    assert_eq!(pair.layout(10), "foofoo");
    assert_eq!(pair.layout(4), "foo\nfoo");
  }

  #[test]
  #[ignore]
  fn text_large_stack() {
    let foo = Layout::text("foo");
    let bar = Layout::text("bar");
    let foo_stack = Layout::stack(&[&foo, &bar]);
    let foo_jux = Layout::juxtapose(&[&foo, &bar]);
    let foo_choice = Layout::choices(&[&foo_stack, &foo_jux]);

    let choice = Layout::juxtapose(&vec![&foo_choice; 1000]);

    println!("Done creating layout.");
    println!("Num nodes: {}", choice.debug_num_nodes());

    choice.layout(500);
  }
}
<commit_msg>Fix link sizing<commit_after>#![feature(rust_2018_preview, uniform_paths)]
//! Simple efficient composable primitives for pretty printing.
//!
//! The implementation is derived from the paper ["A New Approach to Optimal Code Formatting"][pp-paper]
//! by Phillip M. Yelland.
//!
//! [pp-paper]: https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44667.pdf

extern crate unicode_width;

mod knot_column;
mod knot_set;
mod linear_value;
mod resolved_layout;
mod shared_string;

use std::collections as col;
use std::fmt;
use std::rc;

use shared_string::SharedString;

const OVERFLOW_COST: f32 = 100.0;
const NEWLINE_COST: f32 = 1.0;

/// The primary representation of pretty-printed text. Logically, it represents a set of
/// possible permissible layouts of text.
///
/// Layouts are constructed with four different primitives:
///
/// 1. Text
///
///    A literal string which is laid out as written. Its length is obtained using the
///    `unicode-width` package.
///
/// 2. Stack
///
///    Vertically stacks two layouts. The left margins of the two layouts will be
///    aligned.
///
/// 3. Juxtapose
///
///    Horizontally juxtapose two layouts. The left margin of the second layout
///    will be aligned with the end of the first layout's last line.
///
/// 4. Choice
///
///    Creates a choice between two or more layouts. The choice is made at layout
///    time based on the cost of each possible layout. See the `layout` method.
#[derive(Clone)]
pub struct Layout(rc::Rc<LayoutContents>);

impl Layout {
  fn with_contents(contents: LayoutContents) -> Layout {
    Layout(rc::Rc::new(contents))
  }

  fn contents(&self) -> &LayoutContents {
    &*self.0
  }

  /// Create a text layout value. This is a literal string with no layout variance.
  pub fn text(lit_text: impl Into<String>) -> Layout {
    Layout::with_contents(LayoutContents::Text(lit_text.into().into()))
  }

  fn choice_pair(first: &Layout, second: &Layout) -> Layout {
    // We should canonicalize this so that the choices are always in the same order.
    Layout::with_contents(LayoutContents::Choice(first.clone(), second.clone()))
  }

  fn stack_pair(top: &Layout, bottom: &Layout) -> Layout {
    Layout::with_contents(LayoutContents::Stack(top.clone(), bottom.clone()))
  }

  /// Create a layout that is the juxtaposition of two other layouts.
  ///
  /// This lays out the latter layout immediately to the right of the last line
  /// of the left layout.
  pub fn juxtapose_pair(left: &Layout, right: &Layout) -> Layout {
    let mut builder = JuxtaposeBuilder::new(right);
    builder.juxtapose(left)
  }

  /// Creates a layout that is the lowest-cost choice of layouts provided.
  pub fn choices<'a>(items: impl AsRef<[&'a Layout]>) -> Layout {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].clone();
    for item in &items[1..] {
      curr_layout = Layout::choice_pair(&curr_layout, item);
    }

    curr_layout
  }

  /// Create a stack of the layouts, where each of the layouts are
  /// vertically stacked on top of each other in the order provided.
  pub fn stack<'a>(items: impl AsRef<[&'a Layout]>) -> Layout {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].clone();
    for item in &items[1..] {
      curr_layout = Layout::stack_pair(&curr_layout, item);
    }
    curr_layout
  }

  /// Creates a juxtoposition of layouts, with each layout immediately
  /// following the last line of the previous layout.
  pub fn juxtapose<'a>(items: impl AsRef<[&'a Layout]>) -> Layout {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].clone();
    for item in &items[1..] {
      curr_layout = Layout::juxtapose_pair(&curr_layout, item);
    }
    curr_layout
  }

  /// Lays out the contents of this layout for a text buffer of width margin.
  pub fn layout(&self, margin: u16) -> String {
    self.layout_with_costs(margin, OVERFLOW_COST, NEWLINE_COST)
  }

  /// Lays out the contents of this layout for a text buffer of width margin, and with
  /// newline costs and overflow costs as provided.
  ///
  /// For each character over the margin width, the overflow cost is incurred. For each
  /// newline in the result, the newline cost is incurred. The layout chosen is that with
  /// the smallest overall cost.
  pub fn layout_with_costs(&self, margin: u16, overflow_cost: f32, newline_cost: f32) -> String {
    let final_layout = knot_set::do_layout(self, overflow_cost, newline_cost, margin);
    return final_layout.to_text(0);
  }

  #[doc(hidden)]
  pub fn debug_num_nodes(&self) -> usize {
    let mut counter = NodeCounter::new();
    counter.visit_node(self);
    counter.get_count()
  }
}

impl fmt::Debug for Layout {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    <LayoutContents as fmt::Debug>::fmt(&*self.0, f)
  }
}

#[derive(Debug)]
enum LayoutContents {
  Text(SharedString),
  Choice(Layout, Layout),
  Stack(Layout, Layout),
  Juxtapose(SharedString, Layout),
}

struct JuxtaposeBuilder {
  right: Layout,
  memo: col::BTreeMap<*const LayoutContents, Layout>,
}

impl JuxtaposeBuilder {
  fn new(right: &Layout) -> Self {
    JuxtaposeBuilder {
      right: right.clone(),
      memo: col::BTreeMap::new(),
    }
  }

  fn juxtapose(&mut self, left: &Layout) -> Layout {
    if let Some(v) = self.memo.get(&(left.contents() as *const LayoutContents)) {
      return v.clone();
    }

    let new_layout = match left.contents() {
      LayoutContents::Text(t) => {
        Layout::with_contents(LayoutContents::Juxtapose(t.clone(), self.right.clone()))
      }
      LayoutContents::Choice(first, second) => Layout::with_contents(LayoutContents::Choice(
        self.juxtapose(first),
        self.juxtapose(second),
      )),
      LayoutContents::Stack(top, bottom) => {
        Layout::with_contents(LayoutContents::Stack(top.clone(), self.juxtapose(bottom)))
      }
      LayoutContents::Juxtapose(text, jux_right) => Layout::with_contents(
        LayoutContents::Juxtapose(text.clone(), self.juxtapose(jux_right)),
      ),
    };

    self
      .memo
      .insert(left.contents() as *const LayoutContents, new_layout.clone());
    new_layout
  }
}

struct NodeCounter {
  seen: col::BTreeSet<*const LayoutContents>,
}

impl NodeCounter {
  fn new() -> Self {
    NodeCounter {
      seen: col::BTreeSet::new(),
    }
  }
  fn visit_node(&mut self, layout: &Layout) {
    if self.seen.insert(layout.contents() as *const LayoutContents) {
      use LayoutContents::*;
      match layout.contents() {
        Text(_) => {}
        Choice(first, second) => {
          self.visit_node(first);
          self.visit_node(second);
        }
        Stack(top, bottom) => {
          self.visit_node(top);
          self.visit_node(bottom);
        }
        Juxtapose(_left, right) => {
          self.visit_node(right);
        }
      }
    }
  }

  fn get_count(&self) -> usize {
    self.seen.len()
  }
}

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

  #[test]
  fn test_simple_set() {
    let foo = Layout::text("foo");
    let pair = Layout::juxtapose(&[&foo, &foo]);
    assert_eq!(pair.layout(10), "foofoo");
  }

  #[test]
  fn test_simple_stack() {
    let foo = Layout::text("foo");
    let pair = Layout::stack(&[&foo, &foo]);
    assert_eq!(pair.layout(10), "foo\nfoo");
  }

  #[test]
  fn text_simple_choice() {
    let foo = Layout::text("foo");
    let pair = Layout::choices(&[
      &Layout::juxtapose(&[&foo, &foo]),
      &Layout::stack(&[&foo, &foo]),
    ]);
    assert_eq!(pair.layout(10), "foofoo");
    assert_eq!(pair.layout(4), "foo\nfoo");
  }

  #[test]
  #[ignore]
  fn text_large_stack() {
    let foo = Layout::text("foo");
    let bar = Layout::text("bar");
    let foo_stack = Layout::stack(&[&foo, &bar]);
    let foo_jux = Layout::juxtapose(&[&foo, &bar]);
    let foo_choice = Layout::choices(&[&foo_stack, &foo_jux]);

    let choice = Layout::juxtapose(&vec![&foo_choice; 1000]);

    println!("Done creating layout.");
    println!("Num nodes: {}", choice.debug_num_nodes());

    choice.layout(500);
  }
}
<|endoftext|>


<commit_before>//! The `sentinel_list` crate provides a simple sentinel based list implementation.
//! Once you insert element to the list you are given back a handle into this list.
//! This handle allows you to remove element from the list in O(1) time.
//!
//! # Examples
//!
//! ```rust
//! extern crate sentinel_list;
//! use sentinel_list::*;
//!
//! fn main() {
//!	 let l = &mut List::new();
//!	 let h1 = l.push_head(1);
//!	 let h2 = l.push_tail(2);
//!	 let h3 = l.push_tail(3);
//!	 {
//!		assert_eq!(&1, (&h1).as_ref());
//!		assert_eq!(&1, l.peek_head().unwrap());
//!		assert_eq!(&3, l.peek_tail().unwrap());
//!	 }
//!	 let e1 = h1.unlink();
//!	 assert_eq!(&2, l.peek_head().unwrap());
//!	 let e3 = h3.unlink();
//!	 assert_eq!(&2, l.peek_tail().unwrap());
//!	 let e2 = h2.unlink();
//!	 assert_eq!(None, l.peek_tail());
//!	 assert_eq!(None, l.peek_head());
//!	 assert_eq!(1, e1);
//!	 assert_eq!(2, e2);
//!	 assert_eq!(3, e3);
//! }
//! ```

#![feature(conservative_impl_trait)]

use std::ptr;
use std::fmt;
use std::ops::Deref;

pub trait ListHandle<T>
{
	fn unlink(self) -> T;
	fn as_ref(&self) -> &T;
}

pub struct Iter<'a, T: 'a>
{
	next: &'a Link<T>,
}

pub struct IterMut<'a, T: 'a>
{
	next: Option<&'a mut Link<T>>,
}

pub struct List<T>
{
	sentinel: Handle<T>,
}

impl<T> List<T>
{
	pub fn new() -> Self
	{
		List {
			sentinel: new_sentinel(),
		}
	}

	pub fn push_head(&mut self, e: T) -> impl ListHandle<T>
	{
		let mut h = new_handle(e);
		insert_after(&mut self.sentinel, &mut h);
		h
	}

	pub fn push_tail(&mut self, e: T) -> impl ListHandle<T>
	{
		let mut h = new_handle(e);
		insert_after(unsafe {&mut *self.sentinel.prev}, &mut h);
		h
	}

	pub fn peek_head(&self) -> Option<&T>
	{
		let link = unsafe { &*self.sentinel.next };
		link.value.as_ref()
	}

	pub fn peek_head_mut(&mut self) -> Option<&mut T>
	{
		let link = unsafe { &mut *self.sentinel.next };
		link.value.as_mut()
	}

	pub fn peek_tail(&self) -> Option<&T>
	{
		let link = unsafe { &*self.sentinel.prev };
		link.value.as_ref()
	}

	pub fn peek_tail_mut(&mut self) -> Option<&mut T>
	{
		let link = unsafe { &mut *self.sentinel.prev };
		link.value.as_mut()
	}

	pub fn iter(&self) -> Iter<T>
	{
		Iter { next: unsafe {&*self.sentinel.next} }
	}

	pub fn iter_mut(&mut self) -> IterMut<T>
	{
		let next = Some(unsafe {&mut *self.sentinel.next});
		let inext = next.map(|v| {
			v
		});
		IterMut { next: inext }
	}
}

impl<'a, T> Iterator for Iter<'a, T>
{
	type Item = &'a T;

	fn next(&mut self) -> Option<Self::Item>
	{
		self.next.value.as_ref().and_then(|v| {
			self.next = unsafe {&*self.next.next};
			Some(v)
		})
	}
}

impl<'a, T> Iterator for IterMut<'a, T>
{
	type Item = &'a mut T;

	fn next(&mut self) -> Option<Self::Item>
	{
		self.next.take().and_then(|link| {
			self.next = Some(unsafe {&mut *link.next});
			link.value.as_mut().map(|v| {
				v
			})
		})
	}
}

#[derive(PartialEq)]
struct Link<T>
{
	pub next: *mut Link<T>,
	pub prev: *mut Link<T>,
	pub value: Option<T>,
}

type Handle<T> = Box<Link<T>>;

impl<T> Link<T>
{
	fn new(v: T) -> Link<T>
	{
		Link {
			prev: ptr::null_mut(),
			next: ptr::null_mut(),
			value: Some(v),
		}
	}
}

impl<T: fmt::Debug> fmt::Debug for Link<T>
{
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Link {{ prev: {:p}, next: {:p}, value: {:?} }}", self.prev, self.next, self.value)
	}
}

impl<T> ListHandle<T> for Handle<T>
{
	fn unlink(self) -> T
	{
		// if you call it on the sentinel
		// you deserve to get what's coming
		unlink(self).unwrap()
	}

	fn as_ref(&self) -> &T
	{
		&self
	}
}

impl<T> Deref for Link<T>
{
	type Target = T;
	fn deref(&self) -> &Self::Target
	{
		// if you call it on the sentinel
		// you deserve to get what's coming
		self.value.as_ref().unwrap()
	}
}

fn new_sentinel<T>() -> Handle<T>
{
	let mut h = Box::new(
		Link {
			prev: ptr::null_mut(),
			next: ptr::null_mut(),
			value: None,
		}
	);
	h.prev = &mut *h;
	h.next = &mut *h;
	h
}

fn new_handle<T>(v: T) -> Handle<T>
{
	Box::new(Link::new(v))
}

fn insert_after<T>(after: &mut Link<T>, h: &mut Link<T>)
{
	let n: *mut _ = after.next;

	h.prev = &mut *after;
	h.next = n;

	after.next = &mut *h;

	let n = unsafe { &mut *h.next };
	n.prev = &mut *h;
}

fn unlink<T>(h: Handle<T>) -> Option<T>
{
	let prev = unsafe { &mut *h.prev };
	let next = unsafe { &mut *h.next };
	next.prev = prev;
	prev.next = next;
	h.value
}

#[cfg(test)]
fn debug_print<T: fmt::Debug>(s: &mut Handle<T>)
{
	let mut h = s.next;
	while h != &mut **s {
		let n = unsafe { &*h };
		println!("{:?}", n);
		h = n.next;
	}
}

#[cfg(test)]
#[test]
fn link_unlink()
{
	let mut s = new_sentinel();
	let mut h1 = new_handle(1);
	let mut h2 = new_handle(2);
	let mut h3 = new_handle(3);

	insert_after(&mut s,  &mut h1);
	insert_after(&mut h1, &mut h2);
	insert_after(&mut h2, &mut h3);

	assert_eq!(unsafe {&*s.next}, &*h1);
	assert_eq!(unsafe {&*h1.prev}, &*s);

	assert_eq!(unsafe {&*h1.next}, &*h2);
	assert_eq!(unsafe {&*h2.prev}, &*h1);

	assert_eq!(unsafe {&*h2.next}, &*h3);
	assert_eq!(unsafe {&*h3.prev}, &*h2);

	assert_eq!(unsafe {&*h3.next}, &*s);
	assert_eq!(unsafe {&*s.prev}, &*h3);

	unlink(h2);

	assert_eq!(unsafe {&*s.next}, &*h1);
	assert_eq!(unsafe {&*h1.prev}, &*s);

	assert_eq!(unsafe {&*h1.next}, &*h3);
	assert_eq!(unsafe {&*h3.prev}, &*h1);

	assert_eq!(unsafe {&*h3.next}, &*s);
	assert_eq!(unsafe {&*s.prev}, &*h3);

	let mut h2 = new_handle(2);
	insert_after(&mut h1, &mut h2);

	unlink(h1);
	assert_eq!(unsafe {&*s.next}, &*h2);
	unlink(h2);
	assert_eq!(unsafe {&*s.next}, &*h3);
	assert_eq!(unsafe {&*s.prev}, &*h3);
	assert_eq!(unsafe {&*h3.prev}, &*s);
	assert_eq!(unsafe {&*h3.next}, &*s);
	unlink(h3);
	assert_eq!(unsafe {&*s.prev}, &*s);
	assert_eq!(unsafe {&*s.next}, &*s);

	unlink(s);
}

#[cfg(test)]
#[test]
fn iter_test()
{
	let l = &mut List::new();
	let h1 = l.push_head(1);
	let h2 = l.push_tail(2);
	let h3 = l.push_tail(3);

	let mut i = l.iter();
	assert_eq!(Some(&1), i.next());
	assert_eq!(Some(&2), i.next());
	assert_eq!(Some(&3), i.next());
	assert_eq!(None, i.next());
}

#[cfg(test)]
#[test]
fn iter_mut_test()
{
	let l = &mut List::new();
	let h1 = l.push_head(1);
	let h2 = l.push_tail(2);
	let h3 = l.push_tail(3);

	{
	let mut i = l.iter_mut();
	assert_eq!(Some(&mut 1), i.next());
	assert_eq!(Some(&mut 2), i.next());
	assert_eq!(Some(&mut 3), i.next());
	assert_eq!(None, i.next());
	}

	l.iter_mut().fold(3, |i, v| {
		*v = i;
		i - 1
	});

	{
	let mut i = l.iter_mut();
	assert_eq!(Some(&mut 3), i.next());
	assert_eq!(Some(&mut 2), i.next());
	assert_eq!(Some(&mut 1), i.next());
	assert_eq!(None, i.next());
	}

	assert_eq!(&3, h1.as_ref());
	assert_eq!(&2, h2.as_ref());
	assert_eq!(&1, h3.as_ref());
}
<commit_msg>cleanup unused variables<commit_after>//! The `sentinel_list` crate provides a simple sentinel based list implementation.
//! Once you insert element to the list you are given back a handle into this list.
//! This handle allows you to remove element from the list in O(1) time.
//!
//! # Examples
//!
//! ```rust
//! extern crate sentinel_list;
//! use sentinel_list::*;
//!
//! fn main() {
//!	 let l = &mut List::new();
//!	 let h1 = l.push_head(1);
//!	 let h2 = l.push_tail(2);
//!	 let h3 = l.push_tail(3);
//!	 {
//!		assert_eq!(&1, (&h1).as_ref());
//!		assert_eq!(&1, l.peek_head().unwrap());
//!		assert_eq!(&3, l.peek_tail().unwrap());
//!	 }
//!	 let e1 = h1.unlink();
//!	 assert_eq!(&2, l.peek_head().unwrap());
//!	 let e3 = h3.unlink();
//!	 assert_eq!(&2, l.peek_tail().unwrap());
//!	 let e2 = h2.unlink();
//!	 assert_eq!(None, l.peek_tail());
//!	 assert_eq!(None, l.peek_head());
//!	 assert_eq!(1, e1);
//!	 assert_eq!(2, e2);
//!	 assert_eq!(3, e3);
//! }
//! ```

#![feature(conservative_impl_trait)]

use std::ptr;
use std::fmt;
use std::ops::Deref;

pub trait ListHandle<T>
{
	fn unlink(self) -> T;
	fn as_ref(&self) -> &T;
}

pub struct Iter<'a, T: 'a>
{
	next: &'a Link<T>,
}

pub struct IterMut<'a, T: 'a>
{
	next: Option<&'a mut Link<T>>,
}

pub struct List<T>
{
	sentinel: Handle<T>,
}

impl<T> List<T>
{
	pub fn new() -> Self
	{
		List {
			sentinel: new_sentinel(),
		}
	}

	pub fn push_head(&mut self, e: T) -> impl ListHandle<T>
	{
		let mut h = new_handle(e);
		insert_after(&mut self.sentinel, &mut h);
		h
	}

	pub fn push_tail(&mut self, e: T) -> impl ListHandle<T>
	{
		let mut h = new_handle(e);
		insert_after(unsafe {&mut *self.sentinel.prev}, &mut h);
		h
	}

	pub fn peek_head(&self) -> Option<&T>
	{
		let link = unsafe { &*self.sentinel.next };
		link.value.as_ref()
	}

	pub fn peek_head_mut(&mut self) -> Option<&mut T>
	{
		let link = unsafe { &mut *self.sentinel.next };
		link.value.as_mut()
	}

	pub fn peek_tail(&self) -> Option<&T>
	{
		let link = unsafe { &*self.sentinel.prev };
		link.value.as_ref()
	}

	pub fn peek_tail_mut(&mut self) -> Option<&mut T>
	{
		let link = unsafe { &mut *self.sentinel.prev };
		link.value.as_mut()
	}

	pub fn iter(&self) -> Iter<T>
	{
		Iter { next: unsafe {&*self.sentinel.next} }
	}

	pub fn iter_mut(&mut self) -> IterMut<T>
	{
		let next = Some(unsafe {&mut *self.sentinel.next});
		let inext = next.map(|v| {
			v
		});
		IterMut { next: inext }
	}
}

impl<'a, T> Iterator for Iter<'a, T>
{
	type Item = &'a T;

	fn next(&mut self) -> Option<Self::Item>
	{
		self.next.value.as_ref().and_then(|v| {
			self.next = unsafe {&*self.next.next};
			Some(v)
		})
	}
}

impl<'a, T> Iterator for IterMut<'a, T>
{
	type Item = &'a mut T;

	fn next(&mut self) -> Option<Self::Item>
	{
		self.next.take().and_then(|link| {
			self.next = Some(unsafe {&mut *link.next});
			link.value.as_mut().map(|v| {
				v
			})
		})
	}
}

#[derive(PartialEq)]
struct Link<T>
{
	pub next: *mut Link<T>,
	pub prev: *mut Link<T>,
	pub value: Option<T>,
}

type Handle<T> = Box<Link<T>>;

impl<T> Link<T>
{
	fn new(v: T) -> Link<T>
	{
		Link {
			prev: ptr::null_mut(),
			next: ptr::null_mut(),
			value: Some(v),
		}
	}
}

impl<T: fmt::Debug> fmt::Debug for Link<T>
{
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Link {{ prev: {:p}, next: {:p}, value: {:?} }}", self.prev, self.next, self.value)
	}
}

impl<T> ListHandle<T> for Handle<T>
{
	fn unlink(self) -> T
	{
		// if you call it on the sentinel
		// you deserve to get what's coming
		unlink(self).unwrap()
	}

	fn as_ref(&self) -> &T
	{
		&self
	}
}

impl<T> Deref for Link<T>
{
	type Target = T;
	fn deref(&self) -> &Self::Target
	{
		// if you call it on the sentinel
		// you deserve to get what's coming
		self.value.as_ref().unwrap()
	}
}

fn new_sentinel<T>() -> Handle<T>
{
	let mut h = Box::new(
		Link {
			prev: ptr::null_mut(),
			next: ptr::null_mut(),
			value: None,
		}
	);
	h.prev = &mut *h;
	h.next = &mut *h;
	h
}

fn new_handle<T>(v: T) -> Handle<T>
{
	Box::new(Link::new(v))
}

fn insert_after<T>(after: &mut Link<T>, h: &mut Link<T>)
{
	let n: *mut _ = after.next;

	h.prev = &mut *after;
	h.next = n;

	after.next = &mut *h;

	let n = unsafe { &mut *h.next };
	n.prev = &mut *h;
}

fn unlink<T>(h: Handle<T>) -> Option<T>
{
	let prev = unsafe { &mut *h.prev };
	let next = unsafe { &mut *h.next };
	next.prev = prev;
	prev.next = next;
	h.value
}

#[allow(dead_code)]
#[cfg(test)]
fn debug_print<T: fmt::Debug>(s: &mut Handle<T>)
{
	let mut h = s.next;
	while h != &mut **s {
		let n = unsafe { &*h };
		println!("{:?}", n);
		h = n.next;
	}
}

#[cfg(test)]
#[test]
fn link_unlink()
{
	let mut s = new_sentinel();
	let mut h1 = new_handle(1);
	let mut h2 = new_handle(2);
	let mut h3 = new_handle(3);

	insert_after(&mut s,  &mut h1);
	insert_after(&mut h1, &mut h2);
	insert_after(&mut h2, &mut h3);

	assert_eq!(unsafe {&*s.next}, &*h1);
	assert_eq!(unsafe {&*h1.prev}, &*s);

	assert_eq!(unsafe {&*h1.next}, &*h2);
	assert_eq!(unsafe {&*h2.prev}, &*h1);

	assert_eq!(unsafe {&*h2.next}, &*h3);
	assert_eq!(unsafe {&*h3.prev}, &*h2);

	assert_eq!(unsafe {&*h3.next}, &*s);
	assert_eq!(unsafe {&*s.prev}, &*h3);

	unlink(h2);

	assert_eq!(unsafe {&*s.next}, &*h1);
	assert_eq!(unsafe {&*h1.prev}, &*s);

	assert_eq!(unsafe {&*h1.next}, &*h3);
	assert_eq!(unsafe {&*h3.prev}, &*h1);

	assert_eq!(unsafe {&*h3.next}, &*s);
	assert_eq!(unsafe {&*s.prev}, &*h3);

	let mut h2 = new_handle(2);
	insert_after(&mut h1, &mut h2);

	unlink(h1);
	assert_eq!(unsafe {&*s.next}, &*h2);
	unlink(h2);
	assert_eq!(unsafe {&*s.next}, &*h3);
	assert_eq!(unsafe {&*s.prev}, &*h3);
	assert_eq!(unsafe {&*h3.prev}, &*s);
	assert_eq!(unsafe {&*h3.next}, &*s);
	unlink(h3);
	assert_eq!(unsafe {&*s.prev}, &*s);
	assert_eq!(unsafe {&*s.next}, &*s);

	unlink(s);
}

#[cfg(test)]
#[test]
fn iter_test()
{
	let l = &mut List::new();
	let h1 = l.push_head(1);
	let h2 = l.push_tail(2);
	let h3 = l.push_tail(3);

	let mut i = l.iter();
	assert_eq!(Some(&1), i.next());
	assert_eq!(Some(&2), i.next());
	assert_eq!(Some(&3), i.next());
	assert_eq!(None, i.next());

    h1.unlink();
    h2.unlink();
    h3.unlink();
}

#[cfg(test)]
#[test]
fn iter_mut_test()
{
	let l = &mut List::new();
	let h1 = l.push_head(1);
	let h2 = l.push_tail(2);
	let h3 = l.push_tail(3);

	{
	let mut i = l.iter_mut();
	assert_eq!(Some(&mut 1), i.next());
	assert_eq!(Some(&mut 2), i.next());
	assert_eq!(Some(&mut 3), i.next());
	assert_eq!(None, i.next());
	}

	l.iter_mut().fold(3, |i, v| {
		*v = i;
		i - 1
	});

	{
	let mut i = l.iter_mut();
	assert_eq!(Some(&mut 3), i.next());
	assert_eq!(Some(&mut 2), i.next());
	assert_eq!(Some(&mut 1), i.next());
	assert_eq!(None, i.next());
	}

	assert_eq!(&3, h1.as_ref());
	assert_eq!(&2, h2.as_ref());
	assert_eq!(&1, h3.as_ref());
}
<|endoftext|>