<commit_before>pub mod prelude;

#[macro_export] macro_rules! lisp {
    // special forms
    ((lambda (($(($argn:ident $argt:ty))*) $ret:ty) $($body:tt)*)) => {
        // regular lambda
        |$($argn:$argt),*| -> $ret { $(lisp!($body));* }
    };
    ((lambda $s:ident (($(($argn:ident $argt:ty))*) $ret:ty) $($body:tt)*)) => {{
        // recursive lambda
        // $s MUST be "self"
        // recurse by calling (self ...)
        struct F;
        impl FnOnce<($($argt,)*)> for F {
            type Output = $ret;
            extern "rust-call" fn call_once($s, ($($argn,)*): ($($argt,)*)) -> $ret {
                $(lisp!($body));*
            }
        }
        impl FnMut<($($argt,)*)> for F {
            extern "rust-call" fn call_mut(&mut $s, ($($argn,)*): ($($argt,)*)) -> $ret {
                $(lisp!($body));*
            }
        }
        impl Fn<($($argt,)*)> for F {
            extern "rust-call" fn call(&$s, ($($argn,)*): ($($argt,)*)) -> $ret {
                $(lisp!($body));*
            }
        }
        F
    }};
    ((defn $name:ident (($(($argn:ident $argt:ty))*) $ret:ty) $($body:tt)*)) => {
        fn $name($($argn:$argt),*) -> $ret { $(lisp!($body));* }
    };
    ((_if $cond:tt $yes:tt $no:tt)) => {
        if lisp!($cond) { lisp!($yes) } else { lisp!($no) }
    };
    ((_while $cond:tt $($body:tt)*)) => {
        while lisp!($cond) { $(lisp!($body));* }
    };
    ((_match $var:tt $(($cond:tt $arm:tt))*)) => {
        match lisp!($var) {
            $(lisp!(__PAT__ $cond) => lisp!($arm)),*
        }
    };
    ((_prn $($arg:tt)*)) => {
        println!($(lisp!($arg)),*)
    };

    // variables
    ((_let mut $var:ident $val:tt)) => {
        let mut $var = lisp!($val);
    };
    ((_let $var:ident $val:tt)) => {
        let $var = lisp!($val);
    };
    ((_set $var:ident $val:tt)) => {
        $var = lisp!($val);
    };

    // escape hatch
    ((_rust $body:block)) => {
        { $body }
    };

    // list parsing
    (($($elem:tt)*)) => {
        lisp!(__LIST__ $($elem),*)
    };

    // parsers for unary and binary operators
    (__LIST__ -,    $arg:tt   ) => { lisp!(__UNARY_OP__  _neg,   $arg   ) };
    (__LIST__ !,    $arg:tt   ) => { lisp!(__UNARY_OP__  _not,   $arg   ) };
    (__LIST__ +,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _add, $($arg),*) };
    (__LIST__ &,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _and, $($arg),*) };
    (__LIST__ |,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _or,  $($arg),*) };
    (__LIST__ ^,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _xor, $($arg),*) };
    (__LIST__ /,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _div, $($arg),*) };
    (__LIST__ *,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _mul, $($arg),*) };
    (__LIST__ %,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _rem, $($arg),*) };
    (__LIST__ <<, $($arg:tt),*) => { lisp!(__BINARY_OP__ _shl, $($arg),*) };
    (__LIST__ >>, $($arg:tt),*) => { lisp!(__BINARY_OP__ _shr, $($arg),*) };
    (__LIST__ -,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _sub, $($arg),*) };
    (__LIST__ ==, $($arg:tt),*) => { lisp!(__BINARY_OP__ _eq,  $($arg),*) };
    (__LIST__ !=, $($arg:tt),*) => { lisp!(__BINARY_OP__ _ne,  $($arg),*) };
    (__LIST__ >,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _gt,  $($arg),*) };
    (__LIST__ <,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _lt,  $($arg),*) };
    (__LIST__ >=, $($arg:tt),*) => { lisp!(__BINARY_OP__ _ge,  $($arg),*) };
    (__LIST__ <=, $($arg:tt),*) => { lisp!(__BINARY_OP__ _le,  $($arg),*) };

    // generically turn unary/binary operators into function calls
    // binary operators can be used as n-ary operators through __REDUCE__
    (__UNARY_OP__  $op:ident, $a:tt)        => { lisp!(__LIST__ $op, $a)      };
    (__BINARY_OP__ $op:ident, $a:tt, $b:tt) => { lisp!(__LIST__ $op, $a, $b)  };
    (__BINARY_OP__ $op:ident, $a:tt, $b:tt, $($rest:tt),+) =>
                                               { lisp!(__REDUCE__ $op,
                                                                  ($op $a $b),
                                                                  $($rest),+) };

    // reduce implementation
    (__REDUCE__ $op:ident, $acc:tt)                       => { lisp!($acc)                     };
    (__REDUCE__ $op:ident, $acc:tt, $a:tt)                => { lisp!(__REDUCE__ $op,
                                                                                ($op $acc $a)) };
    (__REDUCE__ $op:ident, $acc:tt, $a:tt, $($rest:tt),+) => { lisp!(__REDUCE__ $op,
                                                                                ($op $acc $a),
                                                                                $($rest),+)    };

    // function calls
    (__LIST__ $name:expr) => {
        lisp!($name)()
    };
    (__LIST__ $name:expr, $($arg:tt),*) => {
        lisp!($name)($(lisp!($arg)),*)
    };

    // one expression
    ($e:expr) => ($e);
    (__PAT__ $p:pat) => ($p);

    // empty
    () => (());
}

<commit_msg>FnMut and FnOnce delegate to Fn<commit_after>pub mod prelude;

#[macro_export] macro_rules! lisp {
    // special forms
    ((lambda (($(($argn:ident $argt:ty))*) $ret:ty) $($body:tt)*)) => {
        // regular lambda
        |$($argn:$argt),*| -> $ret { $(lisp!($body));* }
    };
    ((lambda $s:ident (($(($argn:ident $argt:ty))*) $ret:ty) $($body:tt)*)) => {{
        // recursive lambda
        // $s MUST be "self"
        // recurse by calling (self ...)
        struct F;
        impl FnOnce<($($argt,)*)> for F {
            type Output = $ret;
            extern "rust-call" fn call_once($s, ($($argn,)*): ($($argt,)*)) -> $ret {
                $s.call(($($argn,)*))
            }
        }
        impl FnMut<($($argt,)*)> for F {
            extern "rust-call" fn call_mut(&mut $s, ($($argn,)*): ($($argt,)*)) -> $ret {
                $s.call(($($argn,)*))
            }
        }
        impl Fn<($($argt,)*)> for F {
            extern "rust-call" fn call(&$s, ($($argn,)*): ($($argt,)*)) -> $ret {
                $(lisp!($body));*
            }
        }
        F
    }};
    ((defn $name:ident (($(($argn:ident $argt:ty))*) $ret:ty) $($body:tt)*)) => {
        fn $name($($argn:$argt),*) -> $ret { $(lisp!($body));* }
    };
    ((_if $cond:tt $yes:tt $no:tt)) => {
        if lisp!($cond) { lisp!($yes) } else { lisp!($no) }
    };
    ((_while $cond:tt $($body:tt)*)) => {
        while lisp!($cond) { $(lisp!($body));* }
    };
    ((_match $var:tt $(($cond:tt $arm:tt))*)) => {
        match lisp!($var) {
            $(lisp!(__PAT__ $cond) => lisp!($arm)),*
        }
    };
    ((_prn $($arg:tt)*)) => {
        println!($(lisp!($arg)),*)
    };

    // variables
    ((_let mut $var:ident $val:tt)) => {
        let mut $var = lisp!($val);
    };
    ((_let $var:ident $val:tt)) => {
        let $var = lisp!($val);
    };
    ((_set $var:ident $val:tt)) => {
        $var = lisp!($val);
    };

    // escape hatch
    ((_rust $body:block)) => {
        { $body }
    };

    // list parsing
    (($($elem:tt)*)) => {
        lisp!(__LIST__ $($elem),*)
    };

    // parsers for unary and binary operators
    (__LIST__ -,    $arg:tt   ) => { lisp!(__UNARY_OP__  _neg,   $arg   ) };
    (__LIST__ !,    $arg:tt   ) => { lisp!(__UNARY_OP__  _not,   $arg   ) };
    (__LIST__ +,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _add, $($arg),*) };
    (__LIST__ &,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _and, $($arg),*) };
    (__LIST__ |,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _or,  $($arg),*) };
    (__LIST__ ^,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _xor, $($arg),*) };
    (__LIST__ /,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _div, $($arg),*) };
    (__LIST__ *,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _mul, $($arg),*) };
    (__LIST__ %,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _rem, $($arg),*) };
    (__LIST__ <<, $($arg:tt),*) => { lisp!(__BINARY_OP__ _shl, $($arg),*) };
    (__LIST__ >>, $($arg:tt),*) => { lisp!(__BINARY_OP__ _shr, $($arg),*) };
    (__LIST__ -,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _sub, $($arg),*) };
    (__LIST__ ==, $($arg:tt),*) => { lisp!(__BINARY_OP__ _eq,  $($arg),*) };
    (__LIST__ !=, $($arg:tt),*) => { lisp!(__BINARY_OP__ _ne,  $($arg),*) };
    (__LIST__ >,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _gt,  $($arg),*) };
    (__LIST__ <,  $($arg:tt),*) => { lisp!(__BINARY_OP__ _lt,  $($arg),*) };
    (__LIST__ >=, $($arg:tt),*) => { lisp!(__BINARY_OP__ _ge,  $($arg),*) };
    (__LIST__ <=, $($arg:tt),*) => { lisp!(__BINARY_OP__ _le,  $($arg),*) };

    // generically turn unary/binary operators into function calls
    // binary operators can be used as n-ary operators through __REDUCE__
    (__UNARY_OP__  $op:ident, $a:tt)        => { lisp!(__LIST__ $op, $a)      };
    (__BINARY_OP__ $op:ident, $a:tt, $b:tt) => { lisp!(__LIST__ $op, $a, $b)  };
    (__BINARY_OP__ $op:ident, $a:tt, $b:tt, $($rest:tt),+) =>
                                               { lisp!(__REDUCE__ $op,
                                                                  ($op $a $b),
                                                                  $($rest),+) };

    // reduce implementation
    (__REDUCE__ $op:ident, $acc:tt)                       => { lisp!($acc)                     };
    (__REDUCE__ $op:ident, $acc:tt, $a:tt)                => { lisp!(__REDUCE__ $op,
                                                                                ($op $acc $a)) };
    (__REDUCE__ $op:ident, $acc:tt, $a:tt, $($rest:tt),+) => { lisp!(__REDUCE__ $op,
                                                                                ($op $acc $a),
                                                                                $($rest),+)    };

    // function calls
    (__LIST__ $name:expr) => {
        lisp!($name)()
    };
    (__LIST__ $name:expr, $($arg:tt),*) => {
        lisp!($name)($(lisp!($arg)),*)
    };

    // one expression
    ($e:expr) => ($e);
    (__PAT__ $p:pat) => ($p);

    // empty
    () => (());
}

<|endoftext|>


<commit_before>#![crate_id = "persistent"]
#![license = "MIT"]
//#![deny(missing_doc)]
#![deny(unused_result, unused_result, unnecessary_qualification,
        non_camel_case_types, unused_variable, unnecessary_typecast)]

extern crate iron;

pub use persistent::Persistent;
pub use shared::Shared;

pub mod persistent;
pub mod shared;
pub mod mixin;

<commit_msg>(doc) Documented crate and modules.<commit_after>#![crate_id = "persistent"]
#![license = "MIT"]
#![deny(missing_doc)]
#![deny(unused_result, unused_result, unnecessary_qualification,
        non_camel_case_types, unused_variable, unnecessary_typecast)]

//! A set of middleware for sharing data between requests in the Iron
//! framework.

extern crate iron;

pub use persistent::Persistent;
pub use shared::Shared;

/// Exposes the `Persistent` middleware, for sharing a single piece of data
/// between requests.
pub mod persistent;

/// Exposes the `Shared` middleware, which wraps `ShareableMiddleware` so that
/// they are not cloned for each request and improves performance by removing
/// unnecessary cloning of immutable data.
pub mod shared;

/// Exposes a `link_shared` method on `Chain` objects, providing a convenient
/// way to add shared middleware using `Shared`.
pub mod mixin;

<|endoftext|>


<commit_before>#[macro_use]
extern crate derive_builder;

#[cfg(feature = "markup")]
extern crate serde;
#[cfg(feature = "markup")]
#[macro_use]
extern crate serde_derive;

pub mod development;
pub mod members;
pub mod layout;
pub mod ids;
pub mod traits;
pub mod types;
pub mod utils;

#[cfg(feature = "markup")]
pub mod markup;

//pub use std::fmt::{Result as FmtResult, Formatter, Debug};

<commit_msg>Cleanup<commit_after>#[macro_use]
extern crate derive_builder;

#[cfg(feature = "markup")]
extern crate serde;
#[cfg(feature = "markup")]
#[macro_use]
extern crate serde_derive;

pub mod development;
pub mod members;
pub mod layout;
pub mod ids;
pub mod traits;
pub mod types;
pub mod utils;

#[cfg(feature = "markup")]
pub mod markup;
<|endoftext|>


<commit_before>//! Temporal quantification using floating-point quantities.
//!
//! This crate provides quantification for spans of time. Unlike the standard
//! [std::time](https://doc.rust-lang.org/std/time/index.html) or the
//! [chrono](https://crates.io/crates/chrono) crate, this crate aims
//! to provide a fully featured Duration type which exposes and uses floating-point
//! values instead of integer ones.
//!
//! The existing solutions for time spans are high precision and good for displaying
//! and storing time values, but they are less than convenient to use in simulations or
//! mathematical contexts where a single fractional value in some unit is needed. Thus,
//! this crate was developed in order to fill that need while being maximally compatible
//! with the existing time libraries and not re-inventing the wheel. The interface aims to
//! be very similar to these libraries, just using floating point values so it may be
//! used as a near drop-in replacement for existing programs that
//! would benefit from floating point durations.
//!
//! The goal is to provide a type with the same set of features and flexibility as
//! `std::chrono::duration` in C++ while being "Rusty" in design.
//!
//! # Usage
//! Put this in your `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! float_duration = "0.1"
//! ```
//! # Overview
//!
//! This crate provides a single primary type:
//! [`FloatDuration`](duration/struct.FloatDuration.html) which represents an
//! arbitrary distance in time with no defined start or end point.
//! Internally, it stores a single `f64` holding the number of seconds the duration
//! represents, which can be negative for a "backward" duration. It provides accessors
//! methods to create and read the value in various units, as well as `impl`s for many
//! arithmetic operators in `std::ops`.
//!
//! ```rust
//! # use float_duration::*;
//! let timespan = FloatDuration::hours(2.5) + FloatDuration::seconds(30.0);
//! assert_eq!(timespan, FloatDuration::seconds(9030.0));
//! assert_eq!(timespan, FloatDuration::minutes(150.5));
//! ```
//! Additionally, a [`TimePoint`](duration/trait.TimePoint.html) trait is provided
//! for computing a `FloatDuration` between two objects representing a point in time.
//!
//! # Example Usage
//!
//! Compute the number of blocks in a larger interval:
//!
//! ```rust
//! use float_duration::FloatDuration;
//!
//! let time_block = FloatDuration::minutes(5.0);
//! let blocks_per_hour = FloatDuration::hours(1.0) / time_block;
//!
//! assert_eq!(blocks_per_hour, 12.0);
//! ```
//!
//! Perform a basic numerical integration of a mass on a spring:
//!
//! ```rust
//! use float_duration::FloatDuration;
//!
//! fn acceleration(m: f64, x: f64, t: FloatDuration) -> f64 {
//!     0.5*m*x*x
//! }
//!
//! fn main() {
//!     let mut sim_time = FloatDuration::zero();
//!     let end_time = FloatDuration::minutes(2.0);
//!     let dt = FloatDuration::milliseconds(50.0);
//!
//!     let mut x = 2.0;
//!     let mut v = 0.0;
//!     let m = 1.0;
//!
//!     while sim_time < end_time {
//!         let acc = acceleration(m, x, sim_time);
//!         v += acc*dt.as_seconds();
//!         x += v*dt.as_seconds();
//!         sim_time += dt;
//!     }
//! }
//! ```
//!
//! # Library Support
//!
//! Currently **float_duration** can be compiled without any dependencies, but it
//! provides optional features for interfacing with other libraries.
//!
//! ## std::time
//! The `std::time` module is supported and `FloatDuration`
//! can be used directly with `SystemTime` and `Instant`:
//!
//! ```rust
//! // TimePoint needed for `float_duration_since`.
//! use float_duration::{FloatDuration, TimePoint};
//! use std::time::{Instant, SystemTime};
//!
//!
//! let start_time = Instant::now();
//! //Do lengthy operation...
//! let end_time = Instant::now();
//!
//! println!("Took {}.", end_time.float_duration_since(start_time).unwrap());
//! ```
//!
//! `FloatDuration` may also be converted to/from `std::time::Duration` via the
//! `to_std` and `from_std` methods.
//!
//! ## [approx](https://crates.io/crates/approx)
//! `FloatDuration` provides an implementation of `approx::ApproxEq`
//! for near-equality comparisons of `FloatDuration` if the `approx` feature is enabled.
//! Since `FloatDuration` uses floating point values, this should be the
//! preferred way to establish equality between two duration objects.
//!
//! ## chrono
//!
//! Similar to `std::time` computing a `FloatDuration` between two times in the chrono
//! library is supported. Additionally, `FloatDuration` objects can be converted to/from
//! `chrono::Duration` objects via the `to_chrono` and `from_chrono` methods.

#[cfg(feature = "chrono")]
extern crate chrono;
#[cfg(feature = "time")]
extern crate time;
#[cfg(feature = "approx")]
extern crate approx;

pub mod duration;
pub mod error;

pub use duration::{FloatDuration, TimePoint};
pub use duration::{NANOS_PER_SEC, MICROS_PER_SEC, MILLIS_PER_SEC, SECS_PER_MINUTE, SECS_PER_DAY,
                   SECS_PER_YEAR};
<commit_msg>Removed constants from top-level module.<commit_after>//! Temporal quantification using floating-point quantities.
//!
//! This crate provides quantification for spans of time. Unlike the standard
//! [std::time](https://doc.rust-lang.org/std/time/index.html) or the
//! [chrono](https://crates.io/crates/chrono) crate, this crate aims
//! to provide a fully featured Duration type which exposes and uses floating-point
//! values instead of integer ones.
//!
//! The existing solutions for time spans are high precision and good for displaying
//! and storing time values, but they are less than convenient to use in simulations or
//! mathematical contexts where a single fractional value in some unit is needed. Thus,
//! this crate was developed in order to fill that need while being maximally compatible
//! with the existing time libraries and not re-inventing the wheel. The interface aims to
//! be very similar to these libraries, just using floating point values so it may be
//! used as a near drop-in replacement for existing programs that
//! would benefit from floating point durations.
//!
//! The goal is to provide a type with the same set of features and flexibility as
//! `std::chrono::duration` in C++ while being "Rusty" in design.
//!
//! # Usage
//! Put this in your `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! float_duration = "0.1"
//! ```
//! # Overview
//!
//! This crate provides a single primary type:
//! [`FloatDuration`](duration/struct.FloatDuration.html) which represents an
//! arbitrary distance in time with no defined start or end point.
//! Internally, it stores a single `f64` holding the number of seconds the duration
//! represents, which can be negative for a "backward" duration. It provides accessors
//! methods to create and read the value in various units, as well as `impl`s for many
//! arithmetic operators in `std::ops`.
//!
//! ```rust
//! # use float_duration::*;
//! let timespan = FloatDuration::hours(2.5) + FloatDuration::seconds(30.0);
//! assert_eq!(timespan, FloatDuration::seconds(9030.0));
//! assert_eq!(timespan, FloatDuration::minutes(150.5));
//! ```
//! Additionally, a [`TimePoint`](duration/trait.TimePoint.html) trait is provided
//! for computing a `FloatDuration` between two objects representing a point in time.
//!
//! # Example Usage
//!
//! Compute the number of blocks in a larger interval:
//!
//! ```rust
//! use float_duration::FloatDuration;
//!
//! let time_block = FloatDuration::minutes(5.0);
//! let blocks_per_hour = FloatDuration::hours(1.0) / time_block;
//!
//! assert_eq!(blocks_per_hour, 12.0);
//! ```
//!
//! Perform a basic numerical integration of a mass on a spring:
//!
//! ```rust
//! use float_duration::FloatDuration;
//!
//! fn acceleration(m: f64, x: f64, t: FloatDuration) -> f64 {
//!     0.5*m*x*x
//! }
//!
//! fn main() {
//!     let mut sim_time = FloatDuration::zero();
//!     let end_time = FloatDuration::minutes(2.0);
//!     let dt = FloatDuration::milliseconds(50.0);
//!
//!     let mut x = 2.0;
//!     let mut v = 0.0;
//!     let m = 1.0;
//!
//!     while sim_time < end_time {
//!         let acc = acceleration(m, x, sim_time);
//!         v += acc*dt.as_seconds();
//!         x += v*dt.as_seconds();
//!         sim_time += dt;
//!     }
//! }
//! ```
//!
//! # Library Support
//!
//! Currently **float_duration** can be compiled without any dependencies, but it
//! provides optional features for interfacing with other libraries.
//!
//! ## std::time
//! The `std::time` module is supported and `FloatDuration`
//! can be used directly with `SystemTime` and `Instant`:
//!
//! ```rust
//! // TimePoint needed for `float_duration_since`.
//! use float_duration::{FloatDuration, TimePoint};
//! use std::time::{Instant, SystemTime};
//!
//!
//! let start_time = Instant::now();
//! //Do lengthy operation...
//! let end_time = Instant::now();
//!
//! println!("Took {}.", end_time.float_duration_since(start_time).unwrap());
//! ```
//!
//! `FloatDuration` may also be converted to/from `std::time::Duration` via the
//! `to_std` and `from_std` methods.
//!
//! ## [approx](https://crates.io/crates/approx)
//! `FloatDuration` provides an implementation of `approx::ApproxEq`
//! for near-equality comparisons of `FloatDuration` if the `approx` feature is enabled.
//! Since `FloatDuration` uses floating point values, this should be the
//! preferred way to establish equality between two duration objects.
//!
//! ## chrono
//!
//! Similar to `std::time` computing a `FloatDuration` between two times in the chrono
//! library is supported. Additionally, `FloatDuration` objects can be converted to/from
//! `chrono::Duration` objects via the `to_chrono` and `from_chrono` methods.

#[cfg(feature = "chrono")]
extern crate chrono;
#[cfg(feature = "time")]
extern crate time;
#[cfg(feature = "approx")]
extern crate approx;

pub mod duration;
pub mod error;

pub use duration::{FloatDuration, TimePoint};
<|endoftext|>


<commit_before>#![feature(lang_items)]
#![feature(const_fn)]
#![feature(unique)]
#![feature(custom_attribute)]
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(asm)]
#![feature(step_by)]
#![feature(alloc)]
#![no_std]

#[macro_use]
extern crate bitflags;
extern crate rlibc;
extern crate spin;
extern crate x86;
extern crate alloc;

#[macro_use]
mod vga_buffer;
mod multiboot2;
// mod memory;
mod common;
mod cap;
// mod paging;

use memory::{AreaFrameAllocator, FrameAllocator};

#[no_mangle]
pub extern fn rust_main(multiboot_information_address: usize) {
    enable_nxe_bit();
    enable_write_protect_bit();

    vga_buffer::clear_screen();

    let boot_info = unsafe { multiboot2::load(multiboot_information_address) };
    let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");
    let elf_sections_tag = boot_info.elf_sections_tag().expect("Elf-sections tag required");

    println!("Memory areas:");
    for area in memory_map_tag.memory_areas() {
        println!("    start: 0x{:x}, length: 0x{:x}", area.base_addr, area.length);
    }

    let kernel_start = elf_sections_tag.sections().map(|s| s.addr).min().unwrap();
    let kernel_end = elf_sections_tag.sections().map(|s| s.addr + s.size).max().unwrap();

    let multiboot_start = multiboot_information_address;
    let multiboot_end = multiboot_start + (boot_info.total_size as usize);

    println!("Kernel start: 0x{:x}, end: 0x{:x}", kernel_start, kernel_end);
    println!("Multiboot start: 0x{:x}, end: 0x{:x}", multiboot_start, multiboot_end);

    println!("Kernel sections:");
    for section in elf_sections_tag.sections() {
        println!("    addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}",
                 section.addr, section.size, section.flags);
    }

    let mut frame_allocator = AreaFrameAllocator::new(
        kernel_start as usize, kernel_end as usize,
        multiboot_start, multiboot_end, memory_map_tag.memory_areas());

    memory::remap_kernel(&mut frame_allocator, boot_info);
    println!("Yeah, the kernel did not crash!");

    loop{}
}

fn stack_overflow(i: usize) {
    stack_overflow(i+1)
}

fn enable_nxe_bit() {
    use x86::msr::{IA32_EFER, rdmsr, wrmsr};

    let nxe_bit = 1 << 11;
    unsafe {
        let efer = rdmsr(IA32_EFER);
        wrmsr(IA32_EFER, efer | nxe_bit);
    }
}

fn enable_write_protect_bit() {
    use x86::controlregs::{cr0, cr0_write};

    let wp_bit = 1 << 16;
    unsafe { cr0_write(cr0() | wp_bit) };
}

#[lang = "eh_personality"] extern fn eh_personality() { }
#[lang = "panic_fmt"]
extern fn panic_fmt(fmt: core::fmt::Arguments, file: &str, line: u32) -> ! {
    println!("\n\nPANIC in {} at line {}:", file, line);
    println!("    {}", fmt);
    loop{}
}
<commit_msg>Add new paging module<commit_after>#![feature(lang_items)]
#![feature(const_fn)]
#![feature(unique)]
#![feature(custom_attribute)]
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(asm)]
#![feature(step_by)]
#![feature(alloc)]
#![no_std]

#[macro_use]
extern crate bitflags;
extern crate rlibc;
extern crate spin;
extern crate x86;
extern crate alloc;

#[macro_use]
mod vga_buffer;
mod multiboot2;
mod memory;
mod common;
mod cap;
mod paging;

use memory::{AreaFrameAllocator, FrameAllocator};

#[no_mangle]
pub extern fn rust_main(multiboot_information_address: usize) {
    enable_nxe_bit();
    enable_write_protect_bit();

    vga_buffer::clear_screen();

    let boot_info = unsafe { multiboot2::load(multiboot_information_address) };
    let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");
    let elf_sections_tag = boot_info.elf_sections_tag().expect("Elf-sections tag required");

    println!("Memory areas:");
    for area in memory_map_tag.memory_areas() {
        println!("    start: 0x{:x}, length: 0x{:x}", area.base_addr, area.length);
    }

    let kernel_start = elf_sections_tag.sections().map(|s| s.addr).min().unwrap();
    let kernel_end = elf_sections_tag.sections().map(|s| s.addr + s.size).max().unwrap();

    let multiboot_start = multiboot_information_address;
    let multiboot_end = multiboot_start + (boot_info.total_size as usize);

    println!("Kernel start: 0x{:x}, end: 0x{:x}", kernel_start, kernel_end);
    println!("Multiboot start: 0x{:x}, end: 0x{:x}", multiboot_start, multiboot_end);

    println!("Kernel sections:");
    for section in elf_sections_tag.sections() {
        println!("    addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}",
                 section.addr, section.size, section.flags);
    }

    let mut frame_allocator = AreaFrameAllocator::new(
        kernel_start as usize, kernel_end as usize,
        multiboot_start, multiboot_end, memory_map_tag.memory_areas());

    memory::remap_kernel(&mut frame_allocator, boot_info);
    println!("Yeah, the kernel did not crash!");

    loop{}
}

fn stack_overflow(i: usize) {
    stack_overflow(i+1)
}

fn enable_nxe_bit() {
    use x86::msr::{IA32_EFER, rdmsr, wrmsr};

    let nxe_bit = 1 << 11;
    unsafe {
        let efer = rdmsr(IA32_EFER);
        wrmsr(IA32_EFER, efer | nxe_bit);
    }
}

fn enable_write_protect_bit() {
    use x86::controlregs::{cr0, cr0_write};

    let wp_bit = 1 << 16;
    unsafe { cr0_write(cr0() | wp_bit) };
}

#[lang = "eh_personality"] extern fn eh_personality() { }
#[lang = "panic_fmt"]
extern fn panic_fmt(fmt: core::fmt::Arguments, file: &str, line: u32) -> ! {
    println!("\n\nPANIC in {} at line {}:", file, line);
    println!("    {}", fmt);
    loop{}
}
<|endoftext|>


<commit_before>#![deny(warnings)]
pub mod persistable;
pub mod types;

mod connection;
mod db_result;
mod query_source;
mod result;
mod row;

#[macro_use]
mod macros;

pub use result::*;
pub use query_source::{QuerySource, Queriable, Table, Column, JoinTo};
pub use connection::Connection;

#[cfg(test)]
mod test_usage_without_compiler_plugins {
    pub use super::*;
    use types::NativeSqlType;

    #[derive(PartialEq, Eq, Debug)]
    struct User {
        id: i32,
        name: String,
        hair_color: Option<String>,
    }

    impl User {
        fn new(id: i32, name: &str) -> Self {
            User { id: id, name: name.to_string(), hair_color: None }
        }
    }

    #[derive(PartialEq, Eq, Debug)]
    struct UserWithoutId {
        name: String,
        hair_color: Option<String>,
    }

    #[derive(PartialEq, Eq, Debug)]
    struct Post {
        id: i32,
        user_id: i32,
        title: String,
    }

    // Compiler plugin will automatically invoke this based on schema
    table! {
        users {
            id -> Serial,
            name -> VarChar,
            hair_color -> Nullable<VarChar>,
        }
    }

    table! {
        posts {
            id -> Serial,
            user_id -> Integer,
            title -> VarChar,
        }
    }

    // Compiler plugin will replace this with #[derive(Queriable)]
    queriable! {
        User {
            id -> i32,
            name -> String,
            hair_color -> Option<String>,
        }
    }

    queriable! {
        UserWithoutId {
            name -> String,
            hair_color -> Option<String>,
        }
    }

    queriable! {
        Post {
            id -> i32,
            user_id -> i32,
            title -> String,
        }
    }

    joinable!(posts -> users (user_id = id));
    belongs_to!(User, users, Post, posts);

    #[test]
    fn selecting_basic_data() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let expected_data = vec![
            (1, "Sean".to_string(), None::<String>),
            (2, "Tess".to_string(), None::<String>),
         ];
        let actual_data: Vec<_> = connection.query_all(&users::table)
            .unwrap().collect();
        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn selecting_a_struct() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let expected_users = vec![
            User::new(1, "Sean"),
            User::new(2, "Tess"),
        ];
        let actual_users: Vec<_> = connection.query_all(&users::table)
            .unwrap().collect();
        assert_eq!(expected_users, actual_users);
    }

    #[test]
    fn with_safe_select() {
        use self::users::columns::*;
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let select_id = users.select(id);
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let select_id = users.select(posts::id);
        let select_name = users.select(name);
        let ids: Vec<_> = connection.query_all(&select_id)
            .unwrap().collect();
        let names: Vec<String> = connection.query_all(&select_name)
            .unwrap().collect();
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let names: Vec<String> = connection.query_all(&select_id)
        //     .unwrap().collect();

        assert_eq!(vec![1, 2], ids);
        assert_eq!(vec!["Sean".to_string(), "Tess".to_string()], names);
    }

    #[test]
    fn selecting_multiple_columns() {
        use self::users::columns::*;
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name, hair_color) VALUES ('Jim', 'Black'), ('Bob', 'Brown')")
            .unwrap();

        let source = users.select((name, hair_color));
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let source = users.select((posts::title, posts::user_id));
        // let source = users.select((posts::title, name));
        let expected_data = vec![
            ("Jim".to_string(), Some("Black".to_string())),
            ("Bob".to_string(), Some("Brown".to_string())),
        ];
        let actual_data: Vec<_> = connection.query_all(&source)
            .unwrap().collect();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn selecting_multiple_columns_into_struct() {
        use self::users::columns::*;
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name, hair_color) VALUES ('Jim', 'Black'), ('Bob', 'Brown')")
            .unwrap();

        let source = users.select((name, hair_color));
        let expected_data = vec![
            UserWithoutId { name: "Jim".to_string(), hair_color: Some("Black".to_string()) },
            UserWithoutId { name: "Bob".to_string(), hair_color: Some("Brown".to_string()) },
        ];
        let actual_data: Vec<_> = connection.query_all(&source)
            .unwrap().collect();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn with_select_sql() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let select_count = users::table.select_sql::<types::BigInt>("COUNT(*)");
        let get_count = || connection.query_one::<_, i64>(&select_count).unwrap();
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let actual_count = connection.query_one::<_, String>(&select_count).unwrap();

        assert_eq!(Some(2), get_count());

        connection.execute("INSERT INTO users (name) VALUES ('Jim')")
            .unwrap();

        assert_eq!(Some(3), get_count());
    }

    #[test]
    fn belongs_to() {
        let connection = connection();
        setup_users_table(&connection);
        setup_posts_table(&connection);

        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();
        connection.execute("INSERT INTO posts (user_id, title) VALUES
            (1, 'Hello'),
            (2, 'World')
        ").unwrap();

        let sean = User::new(1, "Sean");
        let tess = User::new(2, "Tess");
        let seans_post = Post { id: 1, user_id: 1, title: "Hello".to_string() };
        let tess_post = Post { id: 2, user_id: 2, title: "World".to_string() };

        let expected_data = vec![(seans_post, sean), (tess_post, tess)];
        let source = posts::table.inner_join(users::table);
        let actual_data: Vec<_> = connection.query_all(&source).unwrap().collect();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn select_single_from_join() {
        let connection = connection();
        setup_users_table(&connection);
        setup_posts_table(&connection);

        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();
        connection.execute("INSERT INTO posts (user_id, title) VALUES
            (1, 'Hello'),
            (2, 'World')
        ").unwrap();

        let source = posts::table.inner_join(users::table);
        let select_name = source.select(users::name);
        let select_title = source.select(posts::title);

        let expected_names = vec!["Sean".to_string(), "Tess".to_string()];
        let actual_names: Vec<String> = connection.query_all(&select_name).unwrap().collect();

        assert_eq!(expected_names, actual_names);

        let expected_titles = vec!["Hello".to_string(), "World".to_string()];
        let actual_titles: Vec<String> = connection.query_all(&select_title).unwrap().collect();

        assert_eq!(expected_titles, actual_titles);
    }

    #[test]
    fn select_multiple_from_join() {
        let connection = connection();
        setup_users_table(&connection);
        setup_posts_table(&connection);

        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();
        connection.execute("INSERT INTO posts (user_id, title) VALUES
            (1, 'Hello'),
            (2, 'World')
        ").unwrap();

        let source = posts::table.inner_join(users::table)
            .select((users::name, posts::title));

        let expected_data = vec![
            ("Sean".to_string(), "Hello".to_string()),
            ("Tess".to_string(), "World".to_string()),
        ];
        let actual_data: Vec<_> = connection.query_all(&source).unwrap().collect();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn select_only_one_side_of_join() {
        let connection = connection();
        setup_users_table(&connection);
        setup_posts_table(&connection);

        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();
        connection.execute("INSERT INTO posts (user_id, title) VALUES (2, 'Hello')")
            .unwrap();

        let source = users::table.inner_join(posts::table).select(users::star);

        let expected_data = vec![User::new(2, "Tess")];
        let actual_data: Vec<_> = connection.query_all(&source).unwrap().collect();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn find() {
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);

        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        assert_eq!(Ok(Some(User::new(1, "Sean"))), connection.find(&users, &1));
        assert_eq!(Ok(Some(User::new(2, "Tess"))), connection.find(&users, &2));
        assert_eq!(Ok(None::<User>), connection.find(&users, &3));
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // connection.find(&users, &"1").unwrap();
    }

    table! {
        users_with_name_pk (name) {
            name -> VarChar,
        }
    }

    #[test]
    fn find_with_non_serial_pk() {
        use self::users_with_name_pk::table as users;

        let connection = connection();
        connection.execute("CREATE TABLE users_with_name_pk (name VARCHAR PRIMARY KEY)")
            .unwrap();
        connection.execute("INSERT INTO users_with_name_pk (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        assert_eq!(Ok(Some("Sean".to_string())), connection.find(&users, &"Sean"));
        assert_eq!(Ok(Some("Tess".to_string())), connection.find(&users, &"Tess".to_string()));
        assert_eq!(Ok(None::<String>), connection.find(&users, &"Wibble"));
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // connection.find(&users, &1).unwrap();
    }

    fn connection() -> Connection {
        let connection_url = ::std::env::var("DATABASE_URL").ok()
            .expect("DATABASE_URL must be set in order to run tests");
        let result = Connection::establish(&connection_url).unwrap();
        result.execute("BEGIN").unwrap();
        result
    }

    #[test]
    fn insert_records() {
        use self::users::table as users;
        let connection = connection();
        setup_users_table(&connection);

        let new_users = vec![
            NewUser::new("Sean", Some("Black")),
            NewUser::new("Tess", None),
        ];
        let inserted_users: Vec<_> = connection.insert(&users, new_users).unwrap().collect();

        let expected_users = vec![
            User { id: 1, name: "Sean".to_string(), hair_color: Some("Black".to_string()) },
            User { id: 2, name: "Tess".to_string(), hair_color: None },
        ];
        let actual_users: Vec<_> = connection.query_all(&users).unwrap().collect();

        assert_eq!(expected_users, actual_users);
        assert_eq!(expected_users, inserted_users);
    }

    #[test]
    fn insert_with_defaults() {
        use self::users::table as users;
        let connection = connection();
        connection.execute("CREATE TABLE users (
            id SERIAL PRIMARY KEY,
            name VARCHAR NOT NULL,
            hair_color VARCHAR NOT NULL DEFAULT 'Green'
        )").unwrap();
        let new_users = vec![
            NewUser::new("Sean", Some("Black")),
            NewUser::new("Tess", None),
        ];
        let inserted_users: Vec<_> = connection.insert(&users, new_users).unwrap().collect();

        let expected_users = vec![
            User { id: 1, name: "Sean".to_string(), hair_color: Some("Black".to_string()) },
            User { id: 2, name: "Tess".to_string(), hair_color: Some("Green".to_string()) },
        ];
        let actual_users: Vec<_> = connection.query_all(&users).unwrap().collect();

        assert_eq!(expected_users, actual_users);
        assert_eq!(expected_users, inserted_users);
    }

    struct NewUser {
        name: String,
        hair_color: Option<String>,
    }

    impl NewUser {
        fn new(name: &str, hair_color: Option<&str>) -> Self {
            NewUser {
                name: name.to_string(),
                hair_color: hair_color.map(|s| s.to_string()),
            }
        }
    }

    insertable! {
        NewUser -> users {
            name -> String,
            hair_color -> Option<String>,
        }
    }

    fn setup_users_table(connection: &Connection) {
        connection.execute("CREATE TABLE users (
            id SERIAL PRIMARY KEY,
            name VARCHAR NOT NULL,
            hair_color VARCHAR
        )").unwrap();
    }

    fn setup_posts_table(connection: &Connection) {
        connection.execute("CREATE TABLE posts (
            id SERIAL PRIMARY KEY,
            user_id INTEGER NOT NULL,
            title VARCHAR NOT NULL
        )").unwrap();
    }
}
<commit_msg>Add a test for defaults that are never provided<commit_after>#![deny(warnings)]
pub mod persistable;
pub mod types;

mod connection;
mod db_result;
mod query_source;
mod result;
mod row;

#[macro_use]
mod macros;

pub use result::*;
pub use query_source::{QuerySource, Queriable, Table, Column, JoinTo};
pub use connection::Connection;

#[cfg(test)]
mod test_usage_without_compiler_plugins {
    pub use super::*;
    use types::NativeSqlType;

    #[derive(PartialEq, Eq, Debug)]
    struct User {
        id: i32,
        name: String,
        hair_color: Option<String>,
    }

    impl User {
        fn new(id: i32, name: &str) -> Self {
            User { id: id, name: name.to_string(), hair_color: None }
        }
    }

    #[derive(PartialEq, Eq, Debug)]
    struct UserWithoutId {
        name: String,
        hair_color: Option<String>,
    }

    #[derive(PartialEq, Eq, Debug)]
    struct Post {
        id: i32,
        user_id: i32,
        title: String,
    }

    // Compiler plugin will automatically invoke this based on schema
    table! {
        users {
            id -> Serial,
            name -> VarChar,
            hair_color -> Nullable<VarChar>,
        }
    }

    table! {
        posts {
            id -> Serial,
            user_id -> Integer,
            title -> VarChar,
        }
    }

    // Compiler plugin will replace this with #[derive(Queriable)]
    queriable! {
        User {
            id -> i32,
            name -> String,
            hair_color -> Option<String>,
        }
    }

    queriable! {
        UserWithoutId {
            name -> String,
            hair_color -> Option<String>,
        }
    }

    queriable! {
        Post {
            id -> i32,
            user_id -> i32,
            title -> String,
        }
    }

    joinable!(posts -> users (user_id = id));
    belongs_to!(User, users, Post, posts);

    #[test]
    fn selecting_basic_data() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let expected_data = vec![
            (1, "Sean".to_string(), None::<String>),
            (2, "Tess".to_string(), None::<String>),
         ];
        let actual_data: Vec<_> = connection.query_all(&users::table)
            .unwrap().collect();
        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn selecting_a_struct() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let expected_users = vec![
            User::new(1, "Sean"),
            User::new(2, "Tess"),
        ];
        let actual_users: Vec<_> = connection.query_all(&users::table)
            .unwrap().collect();
        assert_eq!(expected_users, actual_users);
    }

    #[test]
    fn with_safe_select() {
        use self::users::columns::*;
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let select_id = users.select(id);
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let select_id = users.select(posts::id);
        let select_name = users.select(name);
        let ids: Vec<_> = connection.query_all(&select_id)
            .unwrap().collect();
        let names: Vec<String> = connection.query_all(&select_name)
            .unwrap().collect();
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let names: Vec<String> = connection.query_all(&select_id)
        //     .unwrap().collect();

        assert_eq!(vec![1, 2], ids);
        assert_eq!(vec!["Sean".to_string(), "Tess".to_string()], names);
    }

    #[test]
    fn selecting_multiple_columns() {
        use self::users::columns::*;
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name, hair_color) VALUES ('Jim', 'Black'), ('Bob', 'Brown')")
            .unwrap();

        let source = users.select((name, hair_color));
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let source = users.select((posts::title, posts::user_id));
        // let source = users.select((posts::title, name));
        let expected_data = vec![
            ("Jim".to_string(), Some("Black".to_string())),
            ("Bob".to_string(), Some("Brown".to_string())),
        ];
        let actual_data: Vec<_> = connection.query_all(&source)
            .unwrap().collect();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn selecting_multiple_columns_into_struct() {
        use self::users::columns::*;
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name, hair_color) VALUES ('Jim', 'Black'), ('Bob', 'Brown')")
            .unwrap();

        let source = users.select((name, hair_color));
        let expected_data = vec![
            UserWithoutId { name: "Jim".to_string(), hair_color: Some("Black".to_string()) },
            UserWithoutId { name: "Bob".to_string(), hair_color: Some("Brown".to_string()) },
        ];
        let actual_data: Vec<_> = connection.query_all(&source)
            .unwrap().collect();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn with_select_sql() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let select_count = users::table.select_sql::<types::BigInt>("COUNT(*)");
        let get_count = || connection.query_one::<_, i64>(&select_count).unwrap();
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let actual_count = connection.query_one::<_, String>(&select_count).unwrap();

        assert_eq!(Some(2), get_count());

        connection.execute("INSERT INTO users (name) VALUES ('Jim')")
            .unwrap();

        assert_eq!(Some(3), get_count());
    }

    #[test]
    fn belongs_to() {
        let connection = connection();
        setup_users_table(&connection);
        setup_posts_table(&connection);

        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();
        connection.execute("INSERT INTO posts (user_id, title) VALUES
            (1, 'Hello'),
            (2, 'World')
        ").unwrap();

        let sean = User::new(1, "Sean");
        let tess = User::new(2, "Tess");
        let seans_post = Post { id: 1, user_id: 1, title: "Hello".to_string() };
        let tess_post = Post { id: 2, user_id: 2, title: "World".to_string() };

        let expected_data = vec![(seans_post, sean), (tess_post, tess)];
        let source = posts::table.inner_join(users::table);
        let actual_data: Vec<_> = connection.query_all(&source).unwrap().collect();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn select_single_from_join() {
        let connection = connection();
        setup_users_table(&connection);
        setup_posts_table(&connection);

        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();
        connection.execute("INSERT INTO posts (user_id, title) VALUES
            (1, 'Hello'),
            (2, 'World')
        ").unwrap();

        let source = posts::table.inner_join(users::table);
        let select_name = source.select(users::name);
        let select_title = source.select(posts::title);

        let expected_names = vec!["Sean".to_string(), "Tess".to_string()];
        let actual_names: Vec<String> = connection.query_all(&select_name).unwrap().collect();

        assert_eq!(expected_names, actual_names);

        let expected_titles = vec!["Hello".to_string(), "World".to_string()];
        let actual_titles: Vec<String> = connection.query_all(&select_title).unwrap().collect();

        assert_eq!(expected_titles, actual_titles);
    }

    #[test]
    fn select_multiple_from_join() {
        let connection = connection();
        setup_users_table(&connection);
        setup_posts_table(&connection);

        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();
        connection.execute("INSERT INTO posts (user_id, title) VALUES
            (1, 'Hello'),
            (2, 'World')
        ").unwrap();

        let source = posts::table.inner_join(users::table)
            .select((users::name, posts::title));

        let expected_data = vec![
            ("Sean".to_string(), "Hello".to_string()),
            ("Tess".to_string(), "World".to_string()),
        ];
        let actual_data: Vec<_> = connection.query_all(&source).unwrap().collect();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn select_only_one_side_of_join() {
        let connection = connection();
        setup_users_table(&connection);
        setup_posts_table(&connection);

        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();
        connection.execute("INSERT INTO posts (user_id, title) VALUES (2, 'Hello')")
            .unwrap();

        let source = users::table.inner_join(posts::table).select(users::star);

        let expected_data = vec![User::new(2, "Tess")];
        let actual_data: Vec<_> = connection.query_all(&source).unwrap().collect();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn find() {
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);

        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        assert_eq!(Ok(Some(User::new(1, "Sean"))), connection.find(&users, &1));
        assert_eq!(Ok(Some(User::new(2, "Tess"))), connection.find(&users, &2));
        assert_eq!(Ok(None::<User>), connection.find(&users, &3));
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // connection.find(&users, &"1").unwrap();
    }

    table! {
        users_with_name_pk (name) {
            name -> VarChar,
        }
    }

    #[test]
    fn find_with_non_serial_pk() {
        use self::users_with_name_pk::table as users;

        let connection = connection();
        connection.execute("CREATE TABLE users_with_name_pk (name VARCHAR PRIMARY KEY)")
            .unwrap();
        connection.execute("INSERT INTO users_with_name_pk (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        assert_eq!(Ok(Some("Sean".to_string())), connection.find(&users, &"Sean"));
        assert_eq!(Ok(Some("Tess".to_string())), connection.find(&users, &"Tess".to_string()));
        assert_eq!(Ok(None::<String>), connection.find(&users, &"Wibble"));
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // connection.find(&users, &1).unwrap();
    }

    fn connection() -> Connection {
        let connection_url = ::std::env::var("DATABASE_URL").ok()
            .expect("DATABASE_URL must be set in order to run tests");
        let result = Connection::establish(&connection_url).unwrap();
        result.execute("BEGIN").unwrap();
        result
    }

    #[test]
    fn insert_records() {
        use self::users::table as users;
        let connection = connection();
        setup_users_table(&connection);

        let new_users = vec![
            NewUser::new("Sean", Some("Black")),
            NewUser::new("Tess", None),
        ];
        let inserted_users: Vec<_> = connection.insert(&users, new_users).unwrap().collect();

        let expected_users = vec![
            User { id: 1, name: "Sean".to_string(), hair_color: Some("Black".to_string()) },
            User { id: 2, name: "Tess".to_string(), hair_color: None },
        ];
        let actual_users: Vec<_> = connection.query_all(&users).unwrap().collect();

        assert_eq!(expected_users, actual_users);
        assert_eq!(expected_users, inserted_users);
    }

    #[test]
    fn insert_with_defaults() {
        use self::users::table as users;
        let connection = connection();
        connection.execute("CREATE TABLE users (
            id SERIAL PRIMARY KEY,
            name VARCHAR NOT NULL,
            hair_color VARCHAR NOT NULL DEFAULT 'Green'
        )").unwrap();
        let new_users = vec![
            NewUser::new("Sean", Some("Black")),
            NewUser::new("Tess", None),
        ];
        let inserted_users: Vec<_> = connection.insert(&users, new_users).unwrap().collect();

        let expected_users = vec![
            User { id: 1, name: "Sean".to_string(), hair_color: Some("Black".to_string()) },
            User { id: 2, name: "Tess".to_string(), hair_color: Some("Green".to_string()) },
        ];
        let actual_users: Vec<_> = connection.query_all(&users).unwrap().collect();

        assert_eq!(expected_users, actual_users);
        assert_eq!(expected_users, inserted_users);
    }

    #[test]
    fn insert_with_defaults_not_provided() {
        use self::users::table as users;
        let connection = connection();
        connection.execute("CREATE TABLE users (
            id SERIAL PRIMARY KEY,
            name VARCHAR NOT NULL,
            hair_color VARCHAR NOT NULL DEFAULT 'Green'
        )").unwrap();
        let new_users = vec![
            BaldUser { name: "Sean".to_string() },
            BaldUser { name: "Tess".to_string() },
        ];
        let inserted_users: Vec<_> = connection.insert(&users, new_users).unwrap().collect();

        let expected_users = vec![
            User { id: 1, name: "Sean".to_string(), hair_color: Some("Green".to_string()) },
            User { id: 2, name: "Tess".to_string(), hair_color: Some("Green".to_string()) },
        ];
        let actual_users: Vec<_> = connection.query_all(&users).unwrap().collect();

        assert_eq!(expected_users, actual_users);
        assert_eq!(expected_users, inserted_users);
    }

    struct NewUser {
        name: String,
        hair_color: Option<String>,
    }

    struct BaldUser {
        name: String,
    }

    impl NewUser {
        fn new(name: &str, hair_color: Option<&str>) -> Self {
            NewUser {
                name: name.to_string(),
                hair_color: hair_color.map(|s| s.to_string()),
            }
        }
    }

    insertable! {
        NewUser -> users {
            name -> String,
            hair_color -> Option<String>,
        }
    }

    insertable! {
        BaldUser -> users {
            name -> String,
        }
    }

    fn setup_users_table(connection: &Connection) {
        connection.execute("CREATE TABLE users (
            id SERIAL PRIMARY KEY,
            name VARCHAR NOT NULL,
            hair_color VARCHAR
        )").unwrap();
    }

    fn setup_posts_table(connection: &Connection) {
        connection.execute("CREATE TABLE posts (
            id SERIAL PRIMARY KEY,
            user_id INTEGER NOT NULL,
            title VARCHAR NOT NULL
        )").unwrap();
    }
}
<|endoftext|>


<commit_before>#![warn(missing_docs)]
//! [TIS-100.superoptimizer](https://github.com/dvberkel/TIS-100.superoptimizer) is a
//!
//! > Supertoptimization for TIS-100 game
//!
//! ## Goal
//! This project contains code that attempts to super-optimize certain
//! programming tasks for TIS-100.
//!
//! ### TIS-100
//! Developed by [Zachary Barth](https://en.wikipedia.org/wiki/Zachary_Barth)
//! under the banner of [Zachtronics Industries](http://www.zachtronics.com/),
//! [TIS-100](http://www.zachtronics.com/tis-100/) is a
//!
//! > open-ended programming game in which you rewrite corrupted code segments to
//! > repair the TIS-100 and unlock its secrets. It’s the assembly language
//! > programming game you never asked for!
//!
//! ### Super-optimization
//! Wikipedia defines
//! [super-optimization](https://en.wikipedia.org/wiki/Superoptimization) as
//!
//! > Superoptimization is the task of finding the optimal code sequence for a
//! > single, loop-free sequence of instructions

#[allow(non_snake_case)]
pub mod TIS_100;
<commit_msg>Stricter linting for missing docs<commit_after>#![deny(missing_docs)]
//! [TIS-100.superoptimizer](https://github.com/dvberkel/TIS-100.superoptimizer) is a
//!
//! > Supertoptimization for TIS-100 game
//!
//! ## Goal
//! This project contains code that attempts to super-optimize certain
//! programming tasks for TIS-100.
//!
//! ### TIS-100
//! Developed by [Zachary Barth](https://en.wikipedia.org/wiki/Zachary_Barth)
//! under the banner of [Zachtronics Industries](http://www.zachtronics.com/),
//! [TIS-100](http://www.zachtronics.com/tis-100/) is a
//!
//! > open-ended programming game in which you rewrite corrupted code segments to
//! > repair the TIS-100 and unlock its secrets. It’s the assembly language
//! > programming game you never asked for!
//!
//! ### Super-optimization
//! Wikipedia defines
//! [super-optimization](https://en.wikipedia.org/wiki/Superoptimization) as
//!
//! > Superoptimization is the task of finding the optimal code sequence for a
//! > single, loop-free sequence of instructions

#[allow(non_snake_case)]
pub mod TIS_100;
<|endoftext|>


<commit_before>//! Holmes
//!
//! Holmes is a Datalog inspired system for binding codependent analyses
//! together.
//!
#![warn(missing_docs)]
#![feature(drop_types_in_const)]
#[macro_use]
extern crate lazy_static;
extern crate sha2;
extern crate postgres;
extern crate fallible_iterator;
extern crate r2d2;
extern crate r2d2_postgres;
extern crate rustc_serialize;
#[macro_use]
extern crate log;
#[macro_use]
extern crate error_chain;
extern crate tokio_core;
extern crate futures;

extern crate env_logger;
extern crate url;

pub mod pg;
pub mod engine;
pub mod edsl;
pub mod simple;

pub use engine::{Engine, Error, ErrorKind, Result};
pub use pg::PgDB;
<commit_msg>Remove no longer needed #[feature]<commit_after>//! Holmes
//!
//! Holmes is a Datalog inspired system for binding codependent analyses
//! together.
//!
#![warn(missing_docs)]
#[macro_use]
extern crate lazy_static;
extern crate sha2;
extern crate postgres;
extern crate fallible_iterator;
extern crate r2d2;
extern crate r2d2_postgres;
extern crate rustc_serialize;
#[macro_use]
extern crate log;
#[macro_use]
extern crate error_chain;
extern crate tokio_core;
extern crate futures;

extern crate env_logger;
extern crate url;

pub mod pg;
pub mod engine;
pub mod edsl;
pub mod simple;

pub use engine::{Engine, Error, ErrorKind, Result};
pub use pg::PgDB;
<|endoftext|>


<commit_before>#![feature(custom_derive, quote, plugin, plugin_registrar, rustc_private)]

#[macro_use]
extern crate rustc;
#[macro_use]
extern crate syntax;

use syntax::ext::base::MultiDecorator;
use syntax::parse::token;
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, Annotatable};
use syntax::ptr::P;
use rustc::plugin::Registry;

fn expand_derive_tojson(ct: &mut ExtCtxt, span: Span, _: &ast::MetaItem,
                        item: &Annotatable, push: &mut FnMut(Annotatable)) {
    if let Annotatable::Item(ref item) = *item {
        if let ast::ItemStruct(ref struct_def, _) = item.node {
            let struct_name = item.ident;
            let conv_body: Vec<P<ast::Expr>> = struct_def.fields().map(|field| {
                if let ast::NamedField(name, _) = field.node.kind {
                    let name_str = name.name.as_str();
                    quote_expr!(ct, {
                        __container.insert($name_str.to_string(), self.$name.to_json());
                    })
                } else {
                    ct.span_fatal(span, "#[derive(ToJson)] doesn't support simple struct for now");
                }
            }).collect();
            let impl_item = quote_item!(ct,
                                        #[automatically_derived]
                                        impl ::rustc_serialize::json::ToJson for $struct_name {
                                            fn to_json(&self) -> ::rustc_serialize::json::Json {
                                                let mut __container = ::std::collections::BTreeMap::new();
                                                $conv_body;
                                                ::rustc_serialize::json::Json::Object(__container)
                                            }
                                        }).unwrap();

            push(Annotatable::Item(impl_item));
        } else {
            ct.span_err(span, "#[derive(ToJson)] is only valid for struct");
        }
    } else {
        ct.span_err(span, "#[derive(ToJson)] is only valid for struct");
    }

}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(
        token::intern("derive_ToJson"),
        MultiDecorator(Box::new(expand_derive_tojson)));
}
<commit_msg>(fix) update for upstream syntax<commit_after>#![feature(custom_derive, quote, plugin, plugin_registrar, rustc_private)]

#[macro_use]
extern crate rustc;
#[macro_use]
extern crate syntax;

use syntax::ext::base::MultiDecorator;
use syntax::parse::token;
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, Annotatable};
use syntax::ptr::P;
use rustc::plugin::Registry;

fn expand_derive_tojson(ct: &mut ExtCtxt, span: Span, _: &ast::MetaItem,
                        item: &Annotatable, push: &mut FnMut(Annotatable)) {
    if let Annotatable::Item(ref item) = *item {
        if let ast::ItemStruct(ref struct_def, _) = item.node {
            let struct_name = item.ident;
            let conv_body: Vec<P<ast::Expr>> = struct_def.fields().iter().map(|field| {
                if let ast::NamedField(name, _) = field.node.kind {
                    let name_str = name.name.as_str();
                    quote_expr!(ct, {
                        __container.insert($name_str.to_string(), self.$name.to_json());
                    })
                } else {
                    ct.span_fatal(span, "#[derive(ToJson)] doesn't support simple struct for now");
                }
            }).collect();
            let impl_item = quote_item!(ct,
                                        #[automatically_derived]
                                        impl ::rustc_serialize::json::ToJson for $struct_name {
                                            fn to_json(&self) -> ::rustc_serialize::json::Json {
                                                let mut __container = ::std::collections::BTreeMap::new();
                                                $conv_body;
                                                ::rustc_serialize::json::Json::Object(__container)
                                            }
                                        }).unwrap();

            push(Annotatable::Item(impl_item));
        } else {
            ct.span_err(span, "#[derive(ToJson)] is only valid for struct");
        }
    } else {
        ct.span_err(span, "#[derive(ToJson)] is only valid for struct");
    }

}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(
        token::intern("derive_ToJson"),
        MultiDecorator(Box::new(expand_derive_tojson)));
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![no_std]

extern crate collections;
use collections::string::String;

#[macro_use(concat_string)]
extern crate concat_string;

extern crate num;
use num::Num;

extern crate vec4;

extern crate regex;
use regex::Regex;

#[inline(always)]
fn to_256_str<T: Num>(value: T) -> String {
    (value * T::from_usize(255usize)).round().to_string()
}

#[inline(always)]
pub fn to_rgb<T: Num>(out: [T; 4]) -> String {
    concat_string!("rgb(", &to_256_str(out[0]), ", ", &to_256_str(out[1]), ", ", &to_256_str(out[2]), ")")
}
#[test]
fn test_to_rgb() {
    assert_eq!(&to_rgb([1.0, 0.5, 0.0, 1.0]), "rgb(255, 128, 0)")
}

#[inline(always)]
pub fn to_rgba<T: Num>(out: [T; 4]) -> String {
    concat_string!("rgba(", &to_256_str(out[0]), ", ", &to_256_str(out[1]), ", ", &to_256_str(out[2]), ", ", &(out[3].to_string()), ")")
}
#[test]
fn test_to_rgba() {
    assert_eq!(&to_rgba([1.0, 0.5, 0.0, 1.0]), "rgba(255, 128, 0, 1)")
}

#[inline(always)]
fn to_number<T: Num>(value: &str) -> T {
    T::from_f64(value.parse::<f64>().unwrap())
}

#[inline(always)]
fn to_256<T: Num>(value: &str) -> T {
    to_number::<T>(value).min(T::from_usize(255usize)) / T::from_usize(255usize)
}

#[inline(always)]
pub fn from_rgba<T: Num>(out: &mut [T; 4], string: String) -> &mut [T; 4] {
    let re = Regex::new(r"^rgba\((?:\s+)?(\d+),(?:\s+)?(\d+),(?:\s+)?(\d+),(?:\s+)?((?:\.)?\d+(?:\.\d+)?)\)$").unwrap();

    match re.captures(&string) {
        Some(matches) => {
            out[0] = to_256((&matches.at(1)).unwrap());
            out[1] = to_256((&matches.at(2)).unwrap());
            out[2] = to_256((&matches.at(3)).unwrap());
            out[3] = to_number::<T>((&matches.at(4).unwrap())).min(T::from_usize(1usize));
        },
        None => {
            vec4::set(out, T::zero(), T::zero(), T::zero(), T::one());
        },
    }
    out
}
#[test]
fn test_from_rgba() {
    let mut v = [0.0, 0.0, 0.0, 1.0];
    from_rgba(&mut v, String::from("rgba( 255, 128, 0, 1)"));
    assert_eq!(v, [1.0, 128.0 / 255.0, 0.0, 1.0])
}

#[inline(always)]
pub fn from_rgb<T: Num>(out: &mut [T; 4], string: String) -> &mut [T; 4] {
    let re = Regex::new(r"^rgb\((?:\s+)?(\d+),(?:\s+)?(\d+),(?:\s+)?(\d+)\)$").unwrap();

    match re.captures(&string) {
        Some(matches) => {
            out[0] = to_256((&matches.at(1)).unwrap());
            out[1] = to_256((&matches.at(2)).unwrap());
            out[2] = to_256((&matches.at(3)).unwrap());
            out[3] = T::one();
        },
        None => {
            vec4::set(out, T::zero(), T::zero(), T::zero(), T::one());
        },
    }

    out
}
#[test]
fn test_from_rgb() {
    let mut v = [0.0, 0.0, 0.0, 1.0];
    from_rgb(&mut v, String::from("rgb( 255, 128, 0)"));
    assert_eq!(v, [1.0, 128.0 / 255.0, 0.0, 1.0])
}
<commit_msg>pub mod bug fix<commit_after>#![feature(collections)]
#![no_std]

extern crate collections;
use collections::string::String;

#[macro_use(concat_string)]
extern crate concat_string;

extern crate num;
use num::Num;

extern crate vec4;

extern crate regex;
use regex::Regex;

#[inline(always)]
fn to_256_str<T: Num>(value: T) -> String {
    (value * T::from_usize(255usize)).round().to_string()
}

#[inline(always)]
pub fn to_rgb<T: Num>(out: [T; 4]) -> String {
    concat_string!("rgb(", &to_256_str(out[0]), ", ", &to_256_str(out[1]), ", ", &to_256_str(out[2]), ")")
}
#[test]
fn test_to_rgb() {
    assert_eq!(&to_rgb([1.0, 0.5, 0.0, 1.0]), "rgb(255, 128, 0)")
}

#[inline(always)]
pub fn to_rgba<T: Num>(out: [T; 4]) -> String {
    concat_string!("rgba(", &to_256_str(out[0]), ", ", &to_256_str(out[1]), ", ", &to_256_str(out[2]), ", ", &(out[3].to_string()), ")")
}
#[test]
fn test_to_rgba() {
    assert_eq!(&to_rgba([1.0, 0.5, 0.0, 1.0]), "rgba(255, 128, 0, 1)")
}

#[inline(always)]
fn to_number<T: Num>(value: &str) -> T {
    T::from_f64(value.parse::<f64>().unwrap())
}

#[inline(always)]
fn to_256<T: Num>(value: &str) -> T {
    to_number::<T>(value).min(T::from_usize(255usize)) / T::from_usize(255usize)
}

#[inline(always)]
pub fn from_rgba<T: Num>(out: &mut [T; 4], string: String) -> &mut [T; 4] {
    let re = Regex::new(r"^rgba\((?:\s+)?(\d+),(?:\s+)?(\d+),(?:\s+)?(\d+),(?:\s+)?((?:\.)?\d+(?:\.\d+)?)\)$").unwrap();

    match re.captures(&string) {
        Some(matches) => {
            out[0] = to_256((&matches.at(1)).unwrap());
            out[1] = to_256((&matches.at(2)).unwrap());
            out[2] = to_256((&matches.at(3)).unwrap());
            out[3] = to_number::<T>((&matches.at(4).unwrap())).min(T::from_usize(1usize));
        },
        None => {
            vec4::set(out, T::zero(), T::zero(), T::zero(), T::one());
        },
    }
    out
}
#[test]
fn test_from_rgba() {
    let mut v = [0.0, 0.0, 0.0, 1.0];
    from_rgba(&mut v, String::from("rgba( 255, 128, 0, 1)"));
    assert_eq!(v, [1.0, 128.0 / 255.0, 0.0, 1.0])
}

#[inline(always)]
pub fn from_rgb<T: Num>(out: &mut [T; 4], string: String) -> &mut [T; 4] {
    let re = Regex::new(r"^rgb\((?:\s+)?(\d+),(?:\s+)?(\d+),(?:\s+)?(\d+)\)$").unwrap();

    match re.captures(&string) {
        Some(matches) => {
            out[0] = to_256((&matches.at(1)).unwrap());
            out[1] = to_256((&matches.at(2)).unwrap());
            out[2] = to_256((&matches.at(3)).unwrap());
            out[3] = T::one();
        },
        None => {
            vec4::set(out, T::zero(), T::zero(), T::zero(), T::one());
        },
    }

    out
}
#[test]
fn test_from_rgb() {
    let mut v = [0.0, 0.0, 0.0, 1.0];
    from_rgb(&mut v, String::from("rgb( 255, 128, 0)"));
    assert_eq!(v, [1.0, 128.0 / 255.0, 0.0, 1.0])
}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(io)]
#![feature(path)]

extern crate "rustc-serialize" as rustc_serialize;
extern crate hyper;
extern crate mime;
extern crate url;
extern crate core;

use core::ops::DerefMut;
use hyper::Url;
use hyper::client::Body;
use hyper::header::{ Accept, Authorization, ContentType, UserAgent, qitem };
use hyper::method::Method;
use mime::{ Attr, Mime, Value };
use mime::TopLevel::Application;
use mime::SubLevel::Json;
use rustc_serialize::{ Decoder, Decodable, json };
use std::collections::HashMap;
use std::fs::{ self, File };
use std::io::prelude::*;
use std::io::{ Cursor, Error };
use std::path::Path;
use std::result;

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

pub struct Client {
  host: String,
  token: Option<String>
}

#[derive(RustcDecodable)]
struct Status {
  ok: bool
}

#[derive(RustcDecodable)]
struct Following {
  following: bool
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct User {
  pub id: u32,
  pub login: String,
  pub avatar: String,
  pub email: Option<String>,
  pub name: Option<String>,
}

#[derive(RustcDecodable)]
struct Users {
  users: Vec<User>
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Crate {
  pub name: String,
  pub description: Option<String>,
  pub max_version: String
}

// RustcDecodable be derived because the key used in json is `crate`,
// a reserved word
struct CrateReq {
  krate: Crate
}

impl Decodable for CrateReq {
  fn decode<D: Decoder>(d: &mut D) -> result::Result<CrateReq, D::Error> {
    d.read_struct("CrateReq", 1usize, |_d| {
      Ok(CrateReq {
        krate: try!(_d.read_struct_field("crate", 0usize, |_d| Decodable::decode(_d)))
      })
    })
  }
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Download {
  pub date: String,
  pub downloads: u32
}

#[derive(RustcDecodable)]
struct VersionDownloads {
  version_downloads: Vec<Download>
}

#[derive(RustcDecodable)]
struct ExtraDownloads {
  extra_downloads: Vec<Download>
}

#[derive(RustcDecodable)]
struct MetaDownloads {
  meta: ExtraDownloads
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Dependency {
  pub crate_id: String,
  pub default_features: bool,
  pub features: String,
  pub kind: String,
  pub optional: bool,
  pub req: String
}

#[derive(RustcDecodable)]
struct Dependencies {
  dependencies: Vec<Dependency>
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Version {
  // crate: String,
  pub created_at: String,
  pub dl_path: String,
  pub downloads: u32,
  pub num: String,
  pub updated_at: String,
  pub yanked: bool
}

#[derive(RustcDecodable)]
struct VersionReq {
  version: Version
}

#[derive(RustcDecodable)]
struct Versions {
  versions: Vec<Version>
}

#[derive(RustcDecodable)]
struct Meta {
  names: Vec<String>
}

#[derive(RustcDecodable)]
struct Authors {
  meta: Meta
}

#[derive(RustcEncodable)]
pub struct NewCrate {
  pub name: String,
  pub vers: String,
  pub deps: Vec<NewCrateDependency>,
  pub features: HashMap<String, Vec<String>>,
  pub authors: Vec<String>,
  pub description: Option<String>,
  pub documentation: Option<String>,
  pub homepage: Option<String>,
  pub readme: Option<String>,
  pub keywords: Vec<String>,
  pub license: Option<String>,
  pub license_file: Option<String>,
  pub repository: Option<String>,
}

#[derive(RustcEncodable)]
pub struct NewCrateDependency {
  pub optional: bool,
  pub default_features: bool,
  pub name: String,
  pub features: Vec<String>,
  pub version_req: String,
  pub target: Option<String>,
  pub kind: String,
}

#[derive(RustcEncodable)]
pub struct OwnersReq<'a> {
  users: &'a [&'a str]
}

#[derive(RustcDecodable)]
struct Crates {
  crates: Vec<Crate>
}

struct Bod<'a> {
 read: &'a mut Box<&'a mut Read>,
 size: u64
}

impl Client {
  pub fn new() -> Client {
    Client::host("https://crates.io")
  }

  pub fn host(addr: &str) -> Client {
    Client {
      host: addr.to_string(),
      token: None
    }
  }

  pub fn token(self, auth: &str) -> Client {
    Client {
      host: self.host,
      token: Some(auth.to_string())
    }
  }

  // todo: sort (downloads|name), by letter/keyword/user_id/following
  pub fn find(&mut self, query: &str) -> Result<Vec<Crate>> {
    let body = try!(self.get(format!("/crates?q={}&sort={}", query, "name")));
    Ok(json::decode::<Crates>(&body).unwrap().crates)
  }

  pub fn named(&mut self, name: &str) -> Result<Crate> {
    let body = try!(self.get(format!("/crates/{}", name)));
    Ok(json::decode::<CrateReq>(&body).unwrap().krate)
  }

  // todo: publish -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L76
  pub fn publish(&mut self, krate: &NewCrate, tarball: &Path) -> Result<()> {
    let json = json::encode(krate).unwrap();
    let stat = try!(fs::metadata(tarball));
    let header = {
      let mut w = Vec::new();
      w.extend([
        (json.len() >>  0) as u8,
        (json.len() >>  8) as u8,
        (json.len() >> 16) as u8,
        (json.len() >> 24) as u8,
      ].iter().cloned());
      w.extend(json.as_bytes().iter().cloned());
      w.extend([
        (stat.len() >>  0) as u8,
        (stat.len() >>  8) as u8,
        (stat.len() >> 16) as u8,
        (stat.len() >> 24) as u8,
      ].iter().cloned());
      w
    };
    let size = stat.len() as usize + header.len();
    let tarball = try!(File::open(tarball));
    let mut body = Cursor::new(header).chain(tarball);
    let _ = try!(self.put("/crates/new".to_string(), Some(Bod { read: &mut Box::new(&mut body), size: size as u64 })));
    Ok(())
  }

  pub fn version(&mut self, name: &str, version: &str) -> Result<Version> {
    let body = try!(self.get(format!("/crates/{}/{}", name, version)));
    Ok(json::decode::<VersionReq>(&body).unwrap().version)
  }

  // todo: version download -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L78

  pub fn dependencies(&mut self, name: &str, version: &str) -> Result<Vec<Dependency>> {
    let body = try!(self.get(format!("/crates/{}/{}/dependencies", name, version)));
    Ok(json::decode::<Dependencies>(&body).unwrap().dependencies)
  }

  pub fn downloads(&mut self, name: &str, version: &str) -> Result<Vec<Download>> {
    let body = try!(self.get(format!("/crates/{}/{}/downloads", name, version)));
    Ok(json::decode::<VersionDownloads>(&body).unwrap().version_downloads)
  }

  pub fn authors(&mut self, name: &str, version: &str) -> Result<Vec<String>> {
    let body = try!(self.get(format!("/crates/{}/{}/authors", name, version)));
    Ok(json::decode::<Authors>(&body).unwrap().meta.names)
  }

  pub fn all_downloads(&mut self, name: &str) -> Result<Vec<Download>> {
    let body = try!(self.get(format!("/crates/{}/downloads", name)));
    Ok(json::decode::<MetaDownloads>(&body).unwrap().meta.extra_downloads)
  }

  pub fn versions(&mut self, name: &str) -> Result<Vec<Version>> {
    let body = try!(self.get(format!("/crates/{}/versions", name)));
    let versions: Vec<Version> = json::decode::<Versions>(&body).unwrap().versions;
    Ok(versions)
  }

  pub fn follow(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.put(format!("/crates/{}/follow", krate), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn unfollow(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.delete(format!("/crates/{}/follow", krate), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn following(&mut self, krate: &str) -> Result<bool> {
    let body = try!(self.get(format!("/crates/{}/following", krate)));
    Ok(json::decode::<Following>(&body).unwrap().following)
  }

  pub fn owners(&mut self, krate: &str) -> Result<Vec<User>> {
    let body = try!(self.get(format!("/crates/{}/owners", krate)));
    Ok(json::decode::<Users>(&body).unwrap().users)
  }

  pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let data = json::encode(&OwnersReq { users: owners }).unwrap();
    let mut bytes = data.as_bytes();
    let body = try!(self.put(format!("/crates/{}/owners", krate),
                             Some(Bod { read: &mut Box::new(&mut bytes), size: bytes.len() as u64 })));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let data = json::encode(&OwnersReq { users: owners }).unwrap();
    let mut bytes = data.as_bytes();
    let body = try!(self.delete(format!("/crates/{}/owners", krate),
                                Some(Bod { read: &mut Box::new(&mut bytes), size: bytes.len() as u64 })));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn yank(&mut self, krate: &str, version: &str) -> Result<()> {
    let body = try!(self.delete(format!("/crates/{}/{}/yank", krate, version), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn unyank(&mut self, krate: &str, version: &str) -> Result<()> {
    let body = try!(self.put(format!("/crates/{}/{}/unyank", krate, version), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn reverse_dependencies(&mut self, krate: &str) -> Result<Vec<Dependency>> {
    let body = try!(self.get(format!("/crates/{}/reverse_dependencies", krate)));
    Ok(json::decode::<Dependencies>(&body).unwrap().dependencies)
  }

  fn get(&mut self, path: String) -> Result<String> {
    self.req(Method::Get, path, None)
  }

  fn delete(&mut self, path: String, body: Option<Bod>) -> Result<String> {
    self.req(Method::Delete, path, body)
  }

  fn put(&mut self, path: String, body: Option<Bod>) -> Result<String> {
    self.req(Method::Put, path, body)
  }

  fn req(&mut self, method: Method, path: String, body: Option<Bod>) -> Result<String> {
    let uri = Url::parse(&format!("{}/api/v1{}", self.host, path)).ok().expect("invalid url");
    let mut client = hyper::Client::new();
    let content_type: Mime = Mime(Application, Json, vec![(Attr::Charset, Value::Utf8)]);
    let bound = client.request(method, uri)
      .header(UserAgent("cargopants/0.1.0".to_string()))
      .header(Accept(vec![qitem(content_type.clone())]))
      .header(ContentType(content_type));
    let authenticated = match self.token.clone() {
      Some(auth) => bound.header(Authorization(auth)),
               _ => bound
    };
    let embodied = match body {
      Some(Bod { read: r, size: l }) => {
        let reader: &mut Read  = *r.deref_mut();
        authenticated.body(Body::SizedBody(reader, l))
      },
      _  => authenticated
    };
    let mut res = match embodied.send() {
      Ok(r)    => r,
      Err(err) => panic!("failed request: {:?}", err)
    };
    let mut body = String::new();
    res.read_to_string(&mut body).map(|_| body)
  }
}

#[test]
fn it_works() {
}
<commit_msg>bootstrap test<commit_after>#![feature(core)]
#![feature(io)]
#![feature(path)]
#![feature(test)]

extern crate core;
extern crate hyper;
extern crate mime;
extern crate "rustc-serialize" as rustc_serialize;
extern crate test;
extern crate url;

use core::ops::DerefMut;
use hyper::Url;
use hyper::client::Body;
use hyper::header::{ Accept, Authorization, ContentType, UserAgent, qitem };
use hyper::method::Method;
use mime::{ Attr, Mime, Value };
use mime::TopLevel::Application;
use mime::SubLevel::Json;
use rustc_serialize::{ Decoder, Decodable, json };
use std::collections::HashMap;
use std::fs::{ self, File };
use std::io::prelude::*;
use std::io::{ Cursor, Error };
use std::path::Path;
use std::result;

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

pub struct Client {
  host: String,
  token: Option<String>
}

#[derive(RustcDecodable)]
struct Status {
  ok: bool
}

#[derive(RustcDecodable)]
struct Following {
  following: bool
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct User {
  pub id: u32,
  pub login: String,
  pub avatar: String,
  pub email: Option<String>,
  pub name: Option<String>,
}

#[derive(RustcDecodable)]
struct Users {
  users: Vec<User>
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Crate {
  pub name: String,
  pub description: Option<String>,
  pub max_version: String
}

// RustcDecodable be derived because the key used in json is `crate`,
// a reserved word
struct CrateReq {
  krate: Crate
}

impl Decodable for CrateReq {
  fn decode<D: Decoder>(d: &mut D) -> result::Result<CrateReq, D::Error> {
    d.read_struct("CrateReq", 1usize, |_d| {
      Ok(CrateReq {
        krate: try!(_d.read_struct_field("crate", 0usize, |_d| Decodable::decode(_d)))
      })
    })
  }
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Download {
  pub date: String,
  pub downloads: u32
}

#[derive(RustcDecodable)]
struct VersionDownloads {
  version_downloads: Vec<Download>
}

#[derive(RustcDecodable)]
struct ExtraDownloads {
  extra_downloads: Vec<Download>
}

#[derive(RustcDecodable)]
struct MetaDownloads {
  meta: ExtraDownloads
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Dependency {
  pub crate_id: String,
  pub default_features: bool,
  pub features: String,
  pub kind: String,
  pub optional: bool,
  pub req: String
}

#[derive(RustcDecodable)]
struct Dependencies {
  dependencies: Vec<Dependency>
}

#[derive(RustcDecodable)]
#[derive(Debug)]
pub struct Version {
  // crate: String,
  pub created_at: String,
  pub dl_path: String,
  pub downloads: u32,
  pub num: String,
  pub updated_at: String,
  pub yanked: bool
}

#[derive(RustcDecodable)]
struct VersionReq {
  version: Version
}

#[derive(RustcDecodable)]
struct Versions {
  versions: Vec<Version>
}

#[derive(RustcDecodable)]
struct Meta {
  names: Vec<String>
}

#[derive(RustcDecodable)]
struct Authors {
  meta: Meta
}

#[derive(RustcEncodable)]
pub struct NewCrate {
  pub name: String,
  pub vers: String,
  pub deps: Vec<NewCrateDependency>,
  pub features: HashMap<String, Vec<String>>,
  pub authors: Vec<String>,
  pub description: Option<String>,
  pub documentation: Option<String>,
  pub homepage: Option<String>,
  pub readme: Option<String>,
  pub keywords: Vec<String>,
  pub license: Option<String>,
  pub license_file: Option<String>,
  pub repository: Option<String>,
}

#[derive(RustcEncodable)]
pub struct NewCrateDependency {
  pub optional: bool,
  pub default_features: bool,
  pub name: String,
  pub features: Vec<String>,
  pub version_req: String,
  pub target: Option<String>,
  pub kind: String,
}

#[derive(RustcEncodable)]
pub struct OwnersReq<'a> {
  users: &'a [&'a str]
}

#[derive(RustcDecodable)]
struct Crates {
  crates: Vec<Crate>
}

struct Bod<'a> {
 read: &'a mut Box<&'a mut Read>,
 size: u64
}

impl Client {
  pub fn new() -> Client {
    Client::host("https://crates.io")
  }

  pub fn host(addr: &str) -> Client {
    Client {
      host: addr.to_string(),
      token: None
    }
  }

  pub fn token(self, auth: &str) -> Client {
    Client {
      host: self.host,
      token: Some(auth.to_string())
    }
  }

  // todo: sort (downloads|name), by letter/keyword/user_id/following
  pub fn find(&mut self, query: &str) -> Result<Vec<Crate>> {
    let body = try!(self.get(format!("/crates?q={}&sort={}", query, "name")));
    Ok(json::decode::<Crates>(&body).unwrap().crates)
  }

  pub fn named(&mut self, name: &str) -> Result<Crate> {
    let body = try!(self.get(format!("/crates/{}", name)));
    Ok(json::decode::<CrateReq>(&body).unwrap().krate)
  }

  // todo: publish -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L76
  pub fn publish(&mut self, krate: &NewCrate, tarball: &Path) -> Result<()> {
    let json = json::encode(krate).unwrap();
    let stat = try!(fs::metadata(tarball));
    let header = {
      let mut w = Vec::new();
      w.extend([
        (json.len() >>  0) as u8,
        (json.len() >>  8) as u8,
        (json.len() >> 16) as u8,
        (json.len() >> 24) as u8,
      ].iter().cloned());
      w.extend(json.as_bytes().iter().cloned());
      w.extend([
        (stat.len() >>  0) as u8,
        (stat.len() >>  8) as u8,
        (stat.len() >> 16) as u8,
        (stat.len() >> 24) as u8,
      ].iter().cloned());
      w
    };
    let size = stat.len() as usize + header.len();
    let tarball = try!(File::open(tarball));
    let mut body = Cursor::new(header).chain(tarball);
    let _ = try!(self.put("/crates/new".to_string(), Some(Bod { read: &mut Box::new(&mut body), size: size as u64 })));
    Ok(())
  }

  pub fn version(&mut self, name: &str, version: &str) -> Result<Version> {
    let body = try!(self.get(format!("/crates/{}/{}", name, version)));
    Ok(json::decode::<VersionReq>(&body).unwrap().version)
  }

  // todo: version download -- https://github.com/rust-lang/crates.io/blob/dabd8778c1a515ea7572c59096da76e562afe2e2/src/lib.rs#L78

  pub fn dependencies(&mut self, name: &str, version: &str) -> Result<Vec<Dependency>> {
    let body = try!(self.get(format!("/crates/{}/{}/dependencies", name, version)));
    Ok(json::decode::<Dependencies>(&body).unwrap().dependencies)
  }

  pub fn downloads(&mut self, name: &str, version: &str) -> Result<Vec<Download>> {
    let body = try!(self.get(format!("/crates/{}/{}/downloads", name, version)));
    Ok(json::decode::<VersionDownloads>(&body).unwrap().version_downloads)
  }

  pub fn authors(&mut self, name: &str, version: &str) -> Result<Vec<String>> {
    let body = try!(self.get(format!("/crates/{}/{}/authors", name, version)));
    Ok(json::decode::<Authors>(&body).unwrap().meta.names)
  }

  pub fn all_downloads(&mut self, name: &str) -> Result<Vec<Download>> {
    let body = try!(self.get(format!("/crates/{}/downloads", name)));
    Ok(json::decode::<MetaDownloads>(&body).unwrap().meta.extra_downloads)
  }

  pub fn versions(&mut self, name: &str) -> Result<Vec<Version>> {
    let body = try!(self.get(format!("/crates/{}/versions", name)));
    let versions: Vec<Version> = json::decode::<Versions>(&body).unwrap().versions;
    Ok(versions)
  }

  pub fn follow(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.put(format!("/crates/{}/follow", krate), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn unfollow(&mut self, krate: &str) -> Result<()> {
    let body = try!(self.delete(format!("/crates/{}/follow", krate), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn following(&mut self, krate: &str) -> Result<bool> {
    let body = try!(self.get(format!("/crates/{}/following", krate)));
    Ok(json::decode::<Following>(&body).unwrap().following)
  }

  pub fn owners(&mut self, krate: &str) -> Result<Vec<User>> {
    let body = try!(self.get(format!("/crates/{}/owners", krate)));
    Ok(json::decode::<Users>(&body).unwrap().users)
  }

  pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let data = json::encode(&OwnersReq { users: owners }).unwrap();
    let mut bytes = data.as_bytes();
    let body = try!(self.put(format!("/crates/{}/owners", krate),
                             Some(Bod { read: &mut Box::new(&mut bytes), size: bytes.len() as u64 })));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {
    let data = json::encode(&OwnersReq { users: owners }).unwrap();
    let mut bytes = data.as_bytes();
    let body = try!(self.delete(format!("/crates/{}/owners", krate),
                                Some(Bod { read: &mut Box::new(&mut bytes), size: bytes.len() as u64 })));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn yank(&mut self, krate: &str, version: &str) -> Result<()> {
    let body = try!(self.delete(format!("/crates/{}/{}/yank", krate, version), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn unyank(&mut self, krate: &str, version: &str) -> Result<()> {
    let body = try!(self.put(format!("/crates/{}/{}/unyank", krate, version), None));
    assert!(json::decode::<Status>(&body).unwrap().ok);
    Ok(())
  }

  pub fn reverse_dependencies(&mut self, krate: &str) -> Result<Vec<Dependency>> {
    let body = try!(self.get(format!("/crates/{}/reverse_dependencies", krate)));
    Ok(json::decode::<Dependencies>(&body).unwrap().dependencies)
  }

  fn get(&mut self, path: String) -> Result<String> {
    self.req(Method::Get, path, None)
  }

  fn delete(&mut self, path: String, body: Option<Bod>) -> Result<String> {
    self.req(Method::Delete, path, body)
  }

  fn put(&mut self, path: String, body: Option<Bod>) -> Result<String> {
    self.req(Method::Put, path, body)
  }

  fn req(&mut self, method: Method, path: String, body: Option<Bod>) -> Result<String> {
    let uri = Url::parse(&format!("{}/api/v1{}", self.host, path)).ok().expect("invalid url");
    let mut client = hyper::Client::new();
    let content_type: Mime = Mime(Application, Json, vec![(Attr::Charset, Value::Utf8)]);
    let bound = client.request(method, uri)
      .header(UserAgent("cargopants/0.1.0".to_string()))
      .header(Accept(vec![qitem(content_type.clone())]))
      .header(ContentType(content_type));
    let authenticated = match self.token.clone() {
      Some(auth) => bound.header(Authorization(auth)),
               _ => bound
    };
    let embodied = match body {
      Some(Bod { read: r, size: l }) => {
        let reader: &mut Read  = *r.deref_mut();
        authenticated.body(Body::SizedBody(reader, l))
      },
      _  => authenticated
    };
    let mut res = match embodied.send() {
      Ok(r)    => r,
      Err(err) => panic!("failed request: {:?}", err)
    };
    let mut body = String::new();
    res.read_to_string(&mut body).map(|_| body)
  }
}

#[cfg(test)]
mod tests {
  use test::Bencher;

  #[test]
  fn it_parses_crate_req() {

  }

  #[bench]
  fn it_benches(b: &mut Bencher) {

  }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#[cfg(test)]
mod tests {
   #[test]
   fn it_works() {}
}
<commit_msg>Variant and VTable implementation<commit_after>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

use std::any::{TypeId, Any};
use std::clone::Clone;
use std::fmt::{Display, Debug, Formatter, Error as FmtError};

pub struct Variant<'a> {
   data: *mut (),
   vtable: &'a VTable<'a>,
}

impl<'a> Variant<'a> {
   pub fn new<T: Any>(value: T, vtable: &'a VTable<'a>) -> Self {
      Variant {
         data: Box::into_raw(Box::new(value)) as *mut (),
         vtable: vtable,
      }
   }

   #[inline]
   pub fn is<T: Any>(&self) -> bool {
      self.vtable.id == TypeId::of::<T>()
   }

   #[inline]
   pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
      if self.is::<T>() {
         unsafe { Some(&*(self.data as *const T)) }
      } else {
         None
      }
   }

   #[inline]
   pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
      if self.is::<T>() {
         unsafe { Some(&mut *(self.data as *mut T)) }
      } else {
         None
      }
   }

   #[inline]
   pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
      debug_assert!(self.is::<T>());

      &*(self.data as *const T)
   }

   #[inline]
   pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
      debug_assert!(self.is::<T>());

      &mut *(self.data as *mut T)
   }
}

impl<'a> Clone for Variant<'a> {
   fn clone(&self) -> Self {
      (self.vtable.clone)(self)
   }
}

impl<'a> Drop for Variant<'a> {
   fn drop(&mut self) {
      (self.vtable.drop)(self)
   }
}

impl<'a> Display for Variant<'a> {
   fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
      (self.vtable.display)(self, f)
   }
}

impl<'a> Debug for Variant<'a> {
   fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
      (self.vtable.debug)(self, f)
   }
}

type CloneFn<'a> = fn(&Variant<'a>) -> Variant<'a>;

type DropFn<'a> = fn(&mut Variant<'a>);

type DisplayFn<'a> = fn(&Variant<'a>, f: &mut Formatter) -> Result<(), FmtError>;

type DebugFn<'a> = DisplayFn<'a>;

pub struct VTable<'a> {
   id: TypeId,
   clone: CloneFn<'a>,
   drop: DropFn<'a>,
   display: DisplayFn<'a>,
   debug: DebugFn<'a>,
}

impl<'a> VTable<'a> {
   #[cfg_attr(feature = "cargo-clippy", allow(new_without_default))]
   pub fn new<T: Any + Clone + Display + Debug>() -> Self {
      VTable {
         id: TypeId::of::<T>(),
         clone: clone_variant::<T>,
         drop: drop_variant::<T>,
         display: display_variant::<T>,
         debug: debug_variant::<T>,
      }
   }

   pub fn variant<T: Any>(&'a self, value: T) -> Variant<'a> {
      Variant::new(value, self)
   }
}

fn clone_variant<'a, T: Any + Clone>(variant: &Variant<'a>) -> Variant<'a> {
   Variant::new(unsafe { variant.downcast_ref_unchecked() as &T }.clone(), variant.vtable)
}

fn drop_variant<T>(variant: &mut Variant) {
   drop(unsafe { *Box::from_raw(variant.data as *mut T) });
}

fn display_variant<T: Any + Display>(variant: &Variant, f: &mut Formatter) -> Result<(), FmtError> {
   Display::fmt(unsafe { variant.downcast_ref_unchecked() as &T }, f)
}

fn debug_variant<T: Any + Debug>(variant: &Variant, f: &mut Formatter) -> Result<(), FmtError> {
   Debug::fmt(unsafe { variant.downcast_ref_unchecked() as &T }, f)
}

#[cfg(test)]
mod tests {
   use std::fmt::{Display, Debug};

   use super::*;

   #[test]
   fn clone() {
      let vtable = VTable::new::<i64>();
      let origin = vtable.variant(1234_i64);
      let cloned = origin.clone();
      assert_eq!(origin.downcast_ref::<i64>(), cloned.downcast_ref::<i64>());
      assert_eq!(Some(&1234_i64), cloned.downcast_ref::<i64>());
   }

   #[test]
   fn drop_count() {
      #[derive(Clone, Debug)]
      struct Dropper(*mut usize);

      impl Drop for Dropper {
         fn drop(&mut self) {
            unsafe { *self.0 += 1 };
         }
      }

      impl Display for Dropper {
         fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
            Debug::fmt(self, f)
         }
      }

      let vtable = VTable::new::<Dropper>();
      let mut dropped: usize = 0;
      let variant = vtable.variant(Dropper(&mut dropped));
      drop(variant);
      assert_eq!(dropped, 1);

      dropped = 0;
      let variant = vtable.variant(Dropper(&mut dropped));
      let clone = variant.clone();
      drop(variant);
      drop(clone);
      assert_eq!(dropped, 2);
   }

   #[test]
   fn debug() {
      let vtable = VTable::new::<&str>();
      let variant = vtable.variant("data");
      assert_eq!("\"data\"", format!("{:?}", variant));

      let vtable = VTable::new::<i64>();
      let variant = vtable.variant(1234_i64);
      assert_eq!("1234", format!("{:?}", variant));
   }

   #[test]
   fn display() {
      let vtable = VTable::new::<&str>();
      let variant = vtable.variant("data");
      assert_eq!("data", format!("{}", variant));

      let vtable = VTable::new::<i64>();
      let variant = vtable.variant(1234_i64);
      assert_eq!("1234", format!("{}", variant));
   }
}
<|endoftext|>