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

#![crate_name = "js"]
#![crate_type = "rlib"]

#![feature(core_intrinsics)]
#![feature(link_args)]
#![feature(str_utf16)]
#![feature(unsafe_no_drop_flag)]
#![feature(const_fn)]

#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case, improper_ctypes, raw_pointer_derive)]

#[macro_use]
extern crate heapsize;
extern crate libc;
#[macro_use]
extern crate log;
extern crate mozjs_sys;
extern crate num;
extern crate rustc_serialize as serialize;

#[cfg(target_os = "linux")]
#[cfg(target_pointer_width = "64")]
mod jsapi_linux_64;

#[cfg(target_os = "macos")]
#[cfg(target_pointer_width = "64")]
mod jsapi_macos_64;

#[cfg(target_os = "windows")]
#[cfg(target_pointer_width = "64")]
mod jsapi_windows_gcc_64;

#[cfg(not(target_os = "windows"))]
#[cfg(target_pointer_width = "32")]
mod jsapi_linux_32;

pub mod jsapi {
    #[cfg(target_os = "linux")]
    #[cfg(target_pointer_width = "64")]
    pub use jsapi_linux_64::*;

    #[cfg(target_os = "macos")]
    #[cfg(target_pointer_width = "64")]
    pub use jsapi_macos_64::*;

    #[cfg(target_os = "windows")]
    #[cfg(target_pointer_width = "64")]
    pub use jsapi_windows_gcc_64::*;

    #[cfg(not(target_os = "windows"))]
    #[cfg(target_pointer_width = "32")]
    pub use jsapi_linux_32::*;
}

mod consts;
pub mod conversions;
pub mod error;
pub mod glue;
pub mod jsval;
pub mod rust;

pub use consts::*;

use heapsize::HeapSizeOf;
use jsapi::{JSContext, Heap};
use jsval::JSVal;
use rust::GCMethods;

#[link(name = "jsglue")]
extern { }

#[cfg(target_os = "android")]
#[link(name = "stdc++")]
extern { }

#[cfg(target_os = "android")]
#[link(name = "gcc")]
extern { }

#[inline(always)]
pub unsafe fn JS_ARGV(_cx: *mut JSContext, vp: *mut JSVal) -> *mut JSVal {
    vp.offset(2)
}

#[inline(always)]
pub unsafe fn JS_CALLEE(_cx: *mut JSContext, vp: *mut JSVal) -> JSVal {
    *vp
}

// This is measured properly by the heap measurement implemented in SpiderMonkey.
impl<T: Copy + GCMethods<T>> HeapSizeOf for Heap<T> {
    fn heap_size_of_children(&self) -> usize {
        0
    }
}
known_heap_size!(0, JSVal);

<commit_msg>Remove link directives from lib.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_name = "js"]
#![crate_type = "rlib"]

#![feature(core_intrinsics)]
#![feature(link_args)]
#![feature(str_utf16)]
#![feature(unsafe_no_drop_flag)]
#![feature(const_fn)]

#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case, improper_ctypes, raw_pointer_derive)]

#[macro_use]
extern crate heapsize;
extern crate libc;
#[macro_use]
extern crate log;
extern crate mozjs_sys;
extern crate num;
extern crate rustc_serialize as serialize;

#[cfg(target_os = "linux")]
#[cfg(target_pointer_width = "64")]
mod jsapi_linux_64;

#[cfg(target_os = "macos")]
#[cfg(target_pointer_width = "64")]
mod jsapi_macos_64;

#[cfg(target_os = "windows")]
#[cfg(target_pointer_width = "64")]
mod jsapi_windows_gcc_64;

#[cfg(not(target_os = "windows"))]
#[cfg(target_pointer_width = "32")]
mod jsapi_linux_32;

pub mod jsapi {
    #[cfg(target_os = "linux")]
    #[cfg(target_pointer_width = "64")]
    pub use jsapi_linux_64::*;

    #[cfg(target_os = "macos")]
    #[cfg(target_pointer_width = "64")]
    pub use jsapi_macos_64::*;

    #[cfg(target_os = "windows")]
    #[cfg(target_pointer_width = "64")]
    pub use jsapi_windows_gcc_64::*;

    #[cfg(not(target_os = "windows"))]
    #[cfg(target_pointer_width = "32")]
    pub use jsapi_linux_32::*;
}

mod consts;
pub mod conversions;
pub mod error;
pub mod glue;
pub mod jsval;
pub mod rust;

pub use consts::*;

use heapsize::HeapSizeOf;
use jsapi::{JSContext, Heap};
use jsval::JSVal;
use rust::GCMethods;

#[inline(always)]
pub unsafe fn JS_ARGV(_cx: *mut JSContext, vp: *mut JSVal) -> *mut JSVal {
    vp.offset(2)
}

#[inline(always)]
pub unsafe fn JS_CALLEE(_cx: *mut JSContext, vp: *mut JSVal) -> JSVal {
    *vp
}

// This is measured properly by the heap measurement implemented in SpiderMonkey.
impl<T: Copy + GCMethods<T>> HeapSizeOf for Heap<T> {
    fn heap_size_of_children(&self) -> usize {
        0
    }
}
known_heap_size!(0, JSVal);

<|endoftext|>


<commit_before>// Adapton for Rust

#![feature(associated_consts)]
#![feature(box_patterns)]
#![feature(box_syntax)]

#![crate_name = "adapton"]
#![crate_type = "lib"]

extern crate core;

#[macro_use]
pub mod macros ;
pub mod engine ;
pub mod catalog ;
pub mod parse_val;

mod reflect;

mod adapton {
    pub use super::*;
}
<commit_msg>doc for the adapton crate; general info about papers and other projects<commit_after>/*!

Adapton for Rust
================

This Rust implementation embodies the latest implementation
[Adapton](http://adapton.org), which offers a foundational,
language-based semantics for general-purpose incremental computation.

**Programming interface in Rust:**
For an overview of its Rust programming interface, see the
documentation for the `adapton::macros` module, which wraps the
`adapton::engine` module with some convenient macros.

**See also**:

- [Presentations and benchmark results](https://github.com/cuplv/adapton-talk#benchmark-results)
- [IODyn: Adapton collections, for algorithms with dynamic input and output](https://github.com/cuplv/iodyn.rust)
- [Adapton Lab: Evaluation and testing](https://github.com/cuplv/adapton-lab.rust)

Background:
-----------

Adapton proposes the _demanded computation graph_ (or **DCG**), and a
demand-driven _change propagation_ algorithm. Further, it proposes
first-class _names_ for identifying cached data structures and
computations.

The following academic papers detail these technical proposals:

- **DCG, and change propagation**: [_Adapton: Composable, demand-driven incremental computation_, **PLDI 2014**](http://www.cs.umd.edu/~hammer/adapton/).
- **Nominal memoization**: [_Incremental computation with names_, **OOPSLA 2015**](http://arxiv.org/abs/1503.07792).
- **Type and effect structures**: The draft [_Typed Adapton: Refinement types for incremental computation with precise names_](https://arxiv.org/abs/1610.00097).

Why Rust?
----------

Adapton's first implementations used Python and OCaml; The latest
implementation in Rust offers the best performance thus far, since (1)
Rust is fast, and (2) [traversal-based garbage collection presents
performance challenges for incremental
computation](http://dl.acm.org/citation.cfm?doid=1375634.1375642).  By
liberating Adapton from traversal-based collection, [our empirical
results](https://github.com/cuplv/adapton-talk#benchmark-results) are
both predictable and scalable.

*/

#![feature(associated_consts)]
#![feature(box_patterns)]
#![feature(box_syntax)]

#![crate_name = "adapton"]
#![crate_type = "lib"]

extern crate core;

#[macro_use]
pub mod macros ;
pub mod engine ;
pub mod catalog ;
pub mod parse_val;

mod reflect;

mod adapton {
    pub use super::*;
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::{c_char, c_short, c_int};

pub enum SpcHandle {}

#[link(name = "snes_spc")]
extern {
    // Instantiate a new SPC emulator and return a handle to it.
    pub fn spc_new() -> *mut SpcHandle;

    // Free an SPC emulator given its handle.
    pub fn spc_delete(spc: *mut SpcHandle);

    // Load SPC data into emulator.
    pub fn spc_load_spc(spc: *mut SpcHandle, data: *const u8, len: c_int)
        -> *const c_char;

    // Clear SPC echo buffer.
    pub fn spc_clear_echo(spc: *mut SpcHandle);

    // Emulate SPC output, recording `count` 16-bit samples to `out`
    pub fn spc_play(spc: *mut SpcHandle, count: c_int, out: *mut c_short)
        -> *const c_char;
}

#[test]
fn it_works() {
    unsafe {
        let mut spc = spc_new();
        spc_delete(spc);
    }
}
<commit_msg>Add a simple safe wrapper and privatize the unsafe API<commit_after>extern crate libc;

use libc::{c_char, c_short, c_int};

pub enum SpcHandle {}

#[link(name = "snes_spc")]
extern {
    // Instantiate a new SPC emulator and return a handle to it.
    fn spc_new() -> *mut SpcHandle;

    // Free an SPC emulator given its handle.
    fn spc_delete(spc: *mut SpcHandle);

    // Load SPC data into emulator.
    fn spc_load_spc(spc: *mut SpcHandle, data: *const u8, len: c_int)
        -> *const c_char;

    // Clear SPC echo buffer.
    fn spc_clear_echo(spc: *mut SpcHandle);

    // Emulate SPC output, recording `count` 16-bit samples to `out`
    fn spc_play(spc: *mut SpcHandle, count: c_int, out: *mut c_short)
        -> *const c_char;
}

/// A simple, safe wrapper around an opaque SNES_SPC handle.
pub struct SnesSpc {
    handle: *mut SpcHandle
}

impl SnesSpc {
    pub fn new() -> SnesSpc {
        unsafe {
            SnesSpc {
                handle: spc_new()
            }
        }
    }

    pub fn load_spc(&mut self, data: &[u8]) {
        unsafe {
            spc_load_spc(self.handle, data.as_ptr(), data.len() as c_int);
        }
    }

    pub fn clear_echo(&mut self) {
        unsafe {
            spc_clear_echo(self.handle);
        }
    }

    pub fn play(&mut self, count: u32, out: &mut [i16]) {
        unsafe {
            // TODO: check that out is big enough :)
            spc_play(self.handle, count as c_int, out.as_mut_ptr());
        }
    }
}

#[test]
fn can_call_unsafe_api_without_exploding() {
    unsafe {
        let mut spc = spc_new();
        spc_delete(spc);
    }
}

#[test]
fn can_use_safe_wrapper_without_being_stabbed() {
    let mut spc = SnesSpc::new();
    spc.clear_echo();
    // Drop it!
}
<|endoftext|>


<commit_before>//! Quasi-quoting without a Syntex dependency, intended for use with [Macros
//! 1.1](https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md).
//!
//! ```toml
//! [dependencies]
//! quote = "0.3"
//! ```
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate quote;
//! ```
//!
//! Interpolation is done with `#var`:
//!
//! ```text
//! let tokens = quote! {
//!     struct SerializeWith #generics #where_clause {
//!         value: &'a #field_ty,
//!         phantom: ::std::marker::PhantomData<#item_ty>,
//!     }
//!
//!     impl #generics serde::Serialize for SerializeWith #generics #where_clause {
//!         fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
//!             where S: serde::Serializer
//!         {
//!             #path(self.value, s)
//!         }
//!     }
//!
//!     SerializeWith {
//!         value: #value,
//!         phantom: ::std::marker::PhantomData::<#item_ty>,
//!     }
//! };
//! ```
//!
//! Repetition is done using `#(...)*` or `#(...),*` very similar to `macro_rules!`:
//!
//! - `#(#var)*` - no separators
//! - `#(#var),*` - the character before the asterisk is used as a separator
//! - `#( struct #var; )*` - the repetition can contain other things
//! - `#( #k => println!("{}", #v), )*` - even multiple interpolations
//!
//! The return type of `quote!` is `quote::Tokens`. Tokens can be interpolated into
//! other quotes:
//!
//! ```text
//! let t = quote! { /* ... */ };
//! return quote! { /* ... */ #t /* ... */ };
//! ```
//!
//! Call `to_string()` on a Tokens to get a String of Rust code.
//!
//! The `quote!` macro relies on deep recursion so some large invocations may fail
//! with "recursion limit reached" when you compile. If it fails, bump up the
//! recursion limit by adding `#![recursion_limit = "128"]` to your crate. An even
//! higher limit may be necessary for especially large invocations.

mod tokens;
pub use tokens::Tokens;

mod to_tokens;
pub use to_tokens::{ToTokens, ByteStr};

#[macro_export]
macro_rules! quote {
    () => {
        $crate::Tokens::new()
    };

    ($($tt:tt)+) => {
        {
            let mut _s = $crate::Tokens::new();
            quote_each_token!(_s $($tt)*);
            _s
        }
    };
}

// Extract the names of all #metavariables and pass them to the $finish macro.
//
// in:   pounded_var_names!(then () a #b c #( #d )* #e)
// out:  then!(() b d e)
#[macro_export]
#[doc(hidden)]
macro_rules! pounded_var_names {
    ($finish:ident ($($found:ident)*) # ( $($inner:tt)* ) $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # [ $($inner:tt)* ] $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # { $($inner:tt)* } $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # $first:ident $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)* $first) $($rest)*)
    };

    ($finish:ident ($($found:ident)*) ( $($inner:tt)* ) $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) [ $($inner:tt)* ] $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) { $($inner:tt)* } $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) $ignore:tt $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($rest)*)
    };

    ($finish:ident ($($found:ident)*)) => {
        $finish!(() $($found)*)
    };
}

// in:   nested_tuples_pat!(() a b c d e)
// out:  ((((a b) c) d) e)
//
// in:   nested_tuples_pat!(() a)
// out:  a
#[macro_export]
#[doc(hidden)]
macro_rules! nested_tuples_pat {
    (()) => {
        &()
    };

    (() $first:ident $($rest:ident)*) => {
        nested_tuples_pat!(($first) $($rest)*)
    };

    (($pat:pat) $first:ident $($rest:ident)*) => {
        nested_tuples_pat!((($pat, $first)) $($rest)*)
    };

    (($done:pat)) => {
        $done
    };
}

// in:   multi_zip_expr!(() a b c d e)
// out:  a.into_iter().zip(b).zip(c).zip(d).zip(e)
//
// in:   multi_zip_iter!(() a)
// out:  a
#[macro_export]
#[doc(hidden)]
macro_rules! multi_zip_expr {
    (()) => {
        &[]
    };

    (() $single:ident) => {
        $single
    };

    (() $first:ident $($rest:ident)*) => {
        multi_zip_expr!(($first.into_iter()) $($rest)*)
    };

    (($zips:expr) $first:ident $($rest:ident)*) => {
        multi_zip_expr!(($zips.zip($first)) $($rest)*)
    };

    (($done:expr)) => {
        $done
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! quote_each_token {
    ($tokens:ident) => {};

    ($tokens:ident # ! $($rest:tt)*) => {
        $tokens.append("#");
        $tokens.append("!");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # ( $($inner:tt)* ) * $($rest:tt)*) => {
        for pounded_var_names!(nested_tuples_pat () $($inner)*)
        in pounded_var_names!(multi_zip_expr () $($inner)*) {
            quote_each_token!($tokens $($inner)*);
        }
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # ( $($inner:tt)* ) $sep:tt * $($rest:tt)*) => {
        for (_i, pounded_var_names!(nested_tuples_pat () $($inner)*))
        in pounded_var_names!(multi_zip_expr () $($inner)*).into_iter().enumerate() {
            if _i > 0 {
                $tokens.append(stringify!($sep));
            }
            quote_each_token!($tokens $($inner)*);
        }
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # [ $($inner:tt)* ] $($rest:tt)*) => {
        $tokens.append("#");
        $tokens.append("[");
        quote_each_token!($tokens $($inner)*);
        $tokens.append("]");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # $first:ident $($rest:tt)*) => {
        $crate::ToTokens::to_tokens(&$first, &mut $tokens);
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident ( $($first:tt)* ) $($rest:tt)*) => {
        $tokens.append("(");
        quote_each_token!($tokens $($first)*);
        $tokens.append(")");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident [ $($first:tt)* ] $($rest:tt)*) => {
        $tokens.append("[");
        quote_each_token!($tokens $($first)*);
        $tokens.append("]");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident { $($first:tt)* } $($rest:tt)*) => {
        $tokens.append("{");
        quote_each_token!($tokens $($first)*);
        $tokens.append("}");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident $first:tt $($rest:tt)*) => {
        $tokens.append(stringify!($first));
        quote_each_token!($tokens $($rest)*);
    };
}
<commit_msg>Document quote!(...) sort of<commit_after>//! Quasi-quoting without a Syntex dependency, intended for use with [Macros
//! 1.1](https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md).
//!
//! ```toml
//! [dependencies]
//! quote = "0.3"
//! ```
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate quote;
//! ```
//!
//! Interpolation is done with `#var`:
//!
//! ```text
//! let tokens = quote! {
//!     struct SerializeWith #generics #where_clause {
//!         value: &'a #field_ty,
//!         phantom: ::std::marker::PhantomData<#item_ty>,
//!     }
//!
//!     impl #generics serde::Serialize for SerializeWith #generics #where_clause {
//!         fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
//!             where S: serde::Serializer
//!         {
//!             #path(self.value, s)
//!         }
//!     }
//!
//!     SerializeWith {
//!         value: #value,
//!         phantom: ::std::marker::PhantomData::<#item_ty>,
//!     }
//! };
//! ```
//!
//! Repetition is done using `#(...)*` or `#(...),*` very similar to `macro_rules!`:
//!
//! - `#(#var)*` - no separators
//! - `#(#var),*` - the character before the asterisk is used as a separator
//! - `#( struct #var; )*` - the repetition can contain other things
//! - `#( #k => println!("{}", #v), )*` - even multiple interpolations
//!
//! The return type of `quote!` is `quote::Tokens`. Tokens can be interpolated into
//! other quotes:
//!
//! ```text
//! let t = quote! { /* ... */ };
//! return quote! { /* ... */ #t /* ... */ };
//! ```
//!
//! Call `to_string()` on a Tokens to get a String of Rust code.
//!
//! The `quote!` macro relies on deep recursion so some large invocations may fail
//! with "recursion limit reached" when you compile. If it fails, bump up the
//! recursion limit by adding `#![recursion_limit = "128"]` to your crate. An even
//! higher limit may be necessary for especially large invocations.

mod tokens;
pub use tokens::Tokens;

mod to_tokens;
pub use to_tokens::{ToTokens, ByteStr};

/// The whole point.
#[macro_export]
macro_rules! quote {
    () => {
        $crate::Tokens::new()
    };

    ($($tt:tt)+) => {
        {
            let mut _s = $crate::Tokens::new();
            quote_each_token!(_s $($tt)*);
            _s
        }
    };
}

// Extract the names of all #metavariables and pass them to the $finish macro.
//
// in:   pounded_var_names!(then () a #b c #( #d )* #e)
// out:  then!(() b d e)
#[macro_export]
#[doc(hidden)]
macro_rules! pounded_var_names {
    ($finish:ident ($($found:ident)*) # ( $($inner:tt)* ) $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # [ $($inner:tt)* ] $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # { $($inner:tt)* } $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) # $first:ident $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)* $first) $($rest)*)
    };

    ($finish:ident ($($found:ident)*) ( $($inner:tt)* ) $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) [ $($inner:tt)* ] $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) { $($inner:tt)* } $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
    };

    ($finish:ident ($($found:ident)*) $ignore:tt $($rest:tt)*) => {
        pounded_var_names!($finish ($($found)*) $($rest)*)
    };

    ($finish:ident ($($found:ident)*)) => {
        $finish!(() $($found)*)
    };
}

// in:   nested_tuples_pat!(() a b c d e)
// out:  ((((a b) c) d) e)
//
// in:   nested_tuples_pat!(() a)
// out:  a
#[macro_export]
#[doc(hidden)]
macro_rules! nested_tuples_pat {
    (()) => {
        &()
    };

    (() $first:ident $($rest:ident)*) => {
        nested_tuples_pat!(($first) $($rest)*)
    };

    (($pat:pat) $first:ident $($rest:ident)*) => {
        nested_tuples_pat!((($pat, $first)) $($rest)*)
    };

    (($done:pat)) => {
        $done
    };
}

// in:   multi_zip_expr!(() a b c d e)
// out:  a.into_iter().zip(b).zip(c).zip(d).zip(e)
//
// in:   multi_zip_iter!(() a)
// out:  a
#[macro_export]
#[doc(hidden)]
macro_rules! multi_zip_expr {
    (()) => {
        &[]
    };

    (() $single:ident) => {
        $single
    };

    (() $first:ident $($rest:ident)*) => {
        multi_zip_expr!(($first.into_iter()) $($rest)*)
    };

    (($zips:expr) $first:ident $($rest:ident)*) => {
        multi_zip_expr!(($zips.zip($first)) $($rest)*)
    };

    (($done:expr)) => {
        $done
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! quote_each_token {
    ($tokens:ident) => {};

    ($tokens:ident # ! $($rest:tt)*) => {
        $tokens.append("#");
        $tokens.append("!");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # ( $($inner:tt)* ) * $($rest:tt)*) => {
        for pounded_var_names!(nested_tuples_pat () $($inner)*)
        in pounded_var_names!(multi_zip_expr () $($inner)*) {
            quote_each_token!($tokens $($inner)*);
        }
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # ( $($inner:tt)* ) $sep:tt * $($rest:tt)*) => {
        for (_i, pounded_var_names!(nested_tuples_pat () $($inner)*))
        in pounded_var_names!(multi_zip_expr () $($inner)*).into_iter().enumerate() {
            if _i > 0 {
                $tokens.append(stringify!($sep));
            }
            quote_each_token!($tokens $($inner)*);
        }
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # [ $($inner:tt)* ] $($rest:tt)*) => {
        $tokens.append("#");
        $tokens.append("[");
        quote_each_token!($tokens $($inner)*);
        $tokens.append("]");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident # $first:ident $($rest:tt)*) => {
        $crate::ToTokens::to_tokens(&$first, &mut $tokens);
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident ( $($first:tt)* ) $($rest:tt)*) => {
        $tokens.append("(");
        quote_each_token!($tokens $($first)*);
        $tokens.append(")");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident [ $($first:tt)* ] $($rest:tt)*) => {
        $tokens.append("[");
        quote_each_token!($tokens $($first)*);
        $tokens.append("]");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident { $($first:tt)* } $($rest:tt)*) => {
        $tokens.append("{");
        quote_each_token!($tokens $($first)*);
        $tokens.append("}");
        quote_each_token!($tokens $($rest)*);
    };

    ($tokens:ident $first:tt $($rest:tt)*) => {
        $tokens.append(stringify!($first));
        quote_each_token!($tokens $($rest)*);
    };
}
<|endoftext|>


<commit_before>#![crate_name="postgres_macros"]
#![crate_type="dylib"]
#![feature(plugin_registrar, core, rustc_private, std_misc, libc)]

extern crate libc;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::ffi::CString;
use std::mem;
use std::str;
use syntax::ast::{TokenTree, ExprLit, LitStr, Expr, Ident};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::token;
use syntax::parse::token::{InternedString, Comma, Eof};
use syntax::parse;
use syntax::parse::parser::Parser;
use syntax::ptr::P;

mod ffi {
    use libc::{c_char, c_int};

    #[repr(C)]
    pub struct ParseResult {
        pub success: c_int,
        pub error_message: *const c_char,
        pub index: c_int,
        pub num_params: c_int,
    }

    extern {
        pub fn init_parser();
        pub fn parse_query(query: *const c_char, result: *mut ParseResult);
    }
}

struct ParseInfo {
    num_params: usize,
}

struct ParseError {
    message: String,
    index: usize,
}

#[plugin_registrar]
#[doc(hidden)]
pub fn registrar(reg: &mut Registry) {
    reg.register_macro("sql", expand_sql);
    reg.register_macro("execute", expand_execute);
    unsafe { ffi::init_parser() }
}

fn expand_sql(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
              -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp)
    };

    match parse(&query) {
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    MacExpr::new(query_expr)
}

fn expand_execute(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                  -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let conn = parser.parse_expr();

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp),
    };

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let args = match parse_args(cx, &mut parser) {
        Some(args) => args,
        None => return DummyResult::expr(sp),
    };

    match parse(&query) {
        Ok(ref info) if info.num_params != args.len() =>
            cx.span_err(sp, format!("Expected {} query parameters but got {}",
                                    info.num_params, args.len()).as_slice()),
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    let ident = Ident::new(token::intern("execute"));
    let args = cx.expr_vec(sp, args);
    MacExpr::new(cx.expr_method_call(sp, conn, ident, vec![query_expr, args]))
}

fn parse_error(cx: &mut ExtCtxt, sp: Span, err: ParseError) {
    cx.span_err(sp, format!("Invalid syntax at position {}: {}",
                            err.index,
                            err.message).as_slice());
}

fn parse_str_lit(cx: &mut ExtCtxt, e: &Expr) -> Option<InternedString> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                LitStr(ref s, _) => Some(s.clone()),
                _ => {
                    cx.span_err(e.span, "expected string literal");
                    None
                }
            }
        }
        _ => {
            cx.span_err(e.span, "expected string literal");
            None
        }
    }
}

fn parse_args(cx: &mut ExtCtxt, parser: &mut Parser) -> Option<Vec<P<Expr>>> {
    let mut args = Vec::new();

    while parser.token != Eof {
        args.push(parser.parse_expr());

        if !parser.eat(&Comma) && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    Some(args)
}

fn parse(query: &str) -> Result<ParseInfo, ParseError> {
    unsafe {
        let mut result = mem::uninitialized();
        let query = CString::from_slice(query.as_bytes());
        ffi::parse_query(query.as_ptr(), &mut result);
        if result.success != 0 {
            Ok(ParseInfo {
                num_params: result.num_params as usize,
            })
        } else {
            let bytes = std::ffi::c_str_to_bytes(&result.error_message);
            Err(ParseError {
                message: str::from_utf8(bytes).unwrap().to_string(),
                index: result.index as usize,
            })
        }
    }
}
<commit_msg>rustup: MaxExpr::new -> MacEager::expr<commit_after>#![crate_name="postgres_macros"]
#![crate_type="dylib"]
#![feature(plugin_registrar, core, rustc_private, std_misc, libc)]

extern crate libc;
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::ffi::CString;
use std::mem;
use std::str;
use syntax::ast::{TokenTree, ExprLit, LitStr, Expr, Ident};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::parse::token;
use syntax::parse::token::{InternedString, Comma, Eof};
use syntax::parse;
use syntax::parse::parser::Parser;
use syntax::ptr::P;

mod ffi {
    use libc::{c_char, c_int};

    #[repr(C)]
    pub struct ParseResult {
        pub success: c_int,
        pub error_message: *const c_char,
        pub index: c_int,
        pub num_params: c_int,
    }

    extern {
        pub fn init_parser();
        pub fn parse_query(query: *const c_char, result: *mut ParseResult);
    }
}

struct ParseInfo {
    num_params: usize,
}

struct ParseError {
    message: String,
    index: usize,
}

#[plugin_registrar]
#[doc(hidden)]
pub fn registrar(reg: &mut Registry) {
    reg.register_macro("sql", expand_sql);
    reg.register_macro("execute", expand_execute);
    unsafe { ffi::init_parser() }
}

fn expand_sql(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
              -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp)
    };

    match parse(&query) {
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    MacEager::expr(query_expr)
}

fn expand_execute(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
                  -> Box<MacResult+'static> {
    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
                                                tts.to_vec());

    let conn = parser.parse_expr();

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let query_expr = cx.expander().fold_expr(parser.parse_expr());
    let query = match parse_str_lit(cx, &*query_expr) {
        Some(query) => query,
        None => return DummyResult::expr(sp),
    };

    if !parser.eat(&Comma) {
        cx.span_err(parser.span, "expected `,`");
        return DummyResult::expr(sp);
    }

    let args = match parse_args(cx, &mut parser) {
        Some(args) => args,
        None => return DummyResult::expr(sp),
    };

    match parse(&query) {
        Ok(ref info) if info.num_params != args.len() =>
            cx.span_err(sp, format!("Expected {} query parameters but got {}",
                                    info.num_params, args.len()).as_slice()),
        Ok(_) => {}
        Err(err) => parse_error(cx, query_expr.span, err),
    }

    let ident = Ident::new(token::intern("execute"));
    let args = cx.expr_vec(sp, args);
    MacEager::expr(cx.expr_method_call(sp, conn, ident, vec![query_expr, args]))
}

fn parse_error(cx: &mut ExtCtxt, sp: Span, err: ParseError) {
    cx.span_err(sp, format!("Invalid syntax at position {}: {}",
                            err.index,
                            err.message).as_slice());
}

fn parse_str_lit(cx: &mut ExtCtxt, e: &Expr) -> Option<InternedString> {
    match e.node {
        ExprLit(ref lit) => {
            match lit.node {
                LitStr(ref s, _) => Some(s.clone()),
                _ => {
                    cx.span_err(e.span, "expected string literal");
                    None
                }
            }
        }
        _ => {
            cx.span_err(e.span, "expected string literal");
            None
        }
    }
}

fn parse_args(cx: &mut ExtCtxt, parser: &mut Parser) -> Option<Vec<P<Expr>>> {
    let mut args = Vec::new();

    while parser.token != Eof {
        args.push(parser.parse_expr());

        if !parser.eat(&Comma) && parser.token != Eof {
            cx.span_err(parser.span, "expected `,`");
            return None;
        }
    }

    Some(args)
}

fn parse(query: &str) -> Result<ParseInfo, ParseError> {
    unsafe {
        let mut result = mem::uninitialized();
        let query = CString::from_slice(query.as_bytes());
        ffi::parse_query(query.as_ptr(), &mut result);
        if result.success != 0 {
            Ok(ParseInfo {
                num_params: result.num_params as usize,
            })
        } else {
            let bytes = std::ffi::c_str_to_bytes(&result.error_message);
            Err(ParseError {
                message: str::from_utf8(bytes).unwrap().to_string(),
                index: result.index as usize,
            })
        }
    }
}
<|endoftext|>


<commit_before>extern crate core;

extern crate easy_process;

#[macro_use]
extern crate failure;
#[macro_use]
extern crate failure_derive;

#[macro_use]
extern crate log;

extern crate chrono;
extern crate crypto_hash;
extern crate hex;

extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_ini;

#[cfg(test)]
#[macro_use]
extern crate serde_json;

#[cfg(not(test))]
extern crate serde_json;

extern crate parse_duration;

extern crate rand;

#[macro_use]
extern crate hyper;
extern crate reqwest;

extern crate walkdir;

#[cfg(test)]
extern crate mktemp;

#[cfg(test)]
extern crate mockito;

pub mod build_info;

mod serde_helpers;
mod update_package;

pub mod runtime_settings;
pub mod settings;

pub mod client;

pub mod firmware;

pub mod states;

pub use failure::Error;

use std::result;
pub type Result<T> = result::Result<T, Error>;
<commit_msg>lib.rs: Rework the importing of crates and sub-modules<commit_after>extern crate chrono;
extern crate core;
extern crate crypto_hash;
extern crate easy_process;
extern crate hex;
extern crate parse_duration;
extern crate rand;
extern crate reqwest;
extern crate serde;
extern crate serde_ini;
extern crate walkdir;

#[macro_use]
extern crate failure;
#[macro_use]
extern crate failure_derive;

#[macro_use]
extern crate log;

#[macro_use]
extern crate hyper;
#[macro_use]
extern crate serde_derive;
#[cfg(not(test))]
extern crate serde_json;

#[cfg(test)]
extern crate mktemp;
#[cfg(test)]
extern crate mockito;
#[cfg(test)]
#[macro_use]
extern crate serde_json;

pub mod build_info;
pub mod client;
pub mod firmware;
pub mod runtime_settings;
mod serde_helpers;
pub mod settings;
pub mod states;
mod update_package;
pub use failure::Error;

use std::result;
pub type Result<T> = result::Result<T, Error>;
<|endoftext|>


<commit_before>// Copyright (c) 2015 T. Okubo
// This file is part of vlc-rs.
// Licensed under the MIT license, see the LICENSE file.

extern crate libc;

pub mod sys;

mod tools;
mod core;
mod media;
mod media_player;
mod media_list;
mod media_library;
mod enums;
mod video;
mod audio;

pub use enums::*;
pub use core::*;
pub use media::*;
pub use media_player::*;
pub use media_list::*;
pub use media_library::*;
pub use video::*;
pub use audio::*;
<commit_msg>lib: fix crate path<commit_after>// Copyright (c) 2015 T. Okubo
// This file is part of vlc-rs.
// Licensed under the MIT license, see the LICENSE file.

extern crate libc;

pub mod sys;

mod tools;
mod core;
mod media;
mod media_player;
mod media_list;
mod media_library;
mod enums;
mod video;
mod audio;

pub use crate::enums::*;
pub use crate::core::*;
pub use crate::media::*;
pub use crate::media_player::*;
pub use crate::media_list::*;
pub use crate::media_library::*;
pub use crate::video::*;
pub use crate::audio::*;
<|endoftext|>


<commit_before>//! A library for interpreting & manipulating Finagle/linkerd [dtab]s.
//!
//! The goal of this library is to provide a DSL for constructing and
//! manipulating dtabs that uses Rust's type system to ensure that invalid
//! dtabs cannot be represented, rather than just representing them as strings.
//!
//! [dtab]: https://linkerd.io/in-depth/dtabs/
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

extern crate serde;
#[macro_use] extern crate serde_derive;
//
// #[macro_use] extern crate nom;

// extern crate regex;

use std::fmt;

pub mod nametree;
pub use self::nametree::*;

/// Macro for constructing a [`Dentry`].
///
/// This allows us to make [`Dentry`]s somewhat more ergonomically
/// than using the `>>` operator (since it doesn't require
/// the use of grouping symbols for the destination side of the
/// Dentry when using the [`NameTree`] DSL).
///
/// The macro also allows the use of `=>` rather than `>>`, as to
/// more closely match the dtab synbtax.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate dtab;
/// # fn main() {
/// use dtab::NameTree;
///
/// let dentry = dentry!( "/iceCreamStore" =>
///     NameTree::from("/smitten") | "/humphrys" | "/birite" | "/three-twins" );
///
/// assert_eq!(
///   "/iceCreamStore => /smitten | /humphrys | /birite | /three-twins;"
/// , &dentry.to_string()
/// );
/// # }
/// ```
///
#[macro_export]
macro_rules! dentry {
  ($src: expr => $dst: expr ) => ($crate::Dentry {
      prefix: $crate::NameTree::from($src), dst: $dst
  })
}

/// Convenience macro for making [`Dtab`]s.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate dtab;
/// # fn main() {
/// use dtab::NameTree;
///
/// let dtab = dtab![
///   "/smitten"       => NameTree::from("/USA/CA/SF/Harrison/2790");
///   "/iceCreamStore" => NameTree::from("/humphrys") | "/smitten";
/// ];
///
///
/// assert_eq!( &format!("{}", dtab)
///           , "/smitten => /USA/CA/SF/Harrison/2790;\n\
///              /iceCreamStore => /humphrys | /smitten;\n"
///           );
/// # }
/// ```
///
/// [`Dtab`]: type.Dtab.html
#[macro_export]
macro_rules! dtab {
  ($($src: expr => $dst: expr ;)+) => (
    Dtab(vec![ $(dentry!($src => $dst)),+ ])
  )
}
/// A `dtab` (delegation table) comprises a sequence of delegation rules.
#[derive(Debug, Clone, Serialize)]
pub struct Dtab(pub Vec<Dentry>);

impl fmt::Display for Dtab {
    #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.iter()
            .fold( Ok(())
                 , |r, ref entry| r.and_then(|_| {
                        write!(f, "{}\n", entry)
                    }))

    }
}

#[derive(Debug, Clone, Serialize)]
pub struct Dentry {
    #[serde(serialize_with ="nametree::serialize")]
    pub prefix: NameTree<String>
  , #[serde(serialize_with ="nametree::serialize")]
    pub dst: NameTree<String>
}

impl fmt::Display for Dentry {
    #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} => {};", self.prefix, self.dst)
    }
}
<commit_msg>fix(dtab! macro): fix dtab! macro not using $crate:: for names<commit_after>//! A library for interpreting & manipulating Finagle/linkerd [dtab]s.
//!
//! The goal of this library is to provide a DSL for constructing and
//! manipulating dtabs that uses Rust's type system to ensure that invalid
//! dtabs cannot be represented, rather than just representing them as strings.
//!
//! [dtab]: https://linkerd.io/in-depth/dtabs/
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

extern crate serde;
#[macro_use] extern crate serde_derive;
//
// #[macro_use] extern crate nom;

// extern crate regex;

use std::fmt;

pub mod nametree;
pub use self::nametree::*;

/// Macro for constructing a [`Dentry`].
///
/// This allows us to make [`Dentry`]s somewhat more ergonomically
/// than using the `>>` operator (since it doesn't require
/// the use of grouping symbols for the destination side of the
/// Dentry when using the [`NameTree`] DSL).
///
/// The macro also allows the use of `=>` rather than `>>`, as to
/// more closely match the dtab synbtax.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate dtab;
/// # fn main() {
/// use dtab::NameTree;
///
/// let dentry = dentry!( "/iceCreamStore" =>
///     NameTree::from("/smitten") | "/humphrys" | "/birite" | "/three-twins" );
///
/// assert_eq!(
///   "/iceCreamStore => /smitten | /humphrys | /birite | /three-twins;"
/// , &dentry.to_string()
/// );
/// # }
/// ```
///
#[macro_export]
macro_rules! dentry {
  ($src: expr => $dst: expr ) => ($crate::Dentry {
      prefix: $crate::NameTree::from($src), dst: $dst
  })
}

/// Convenience macro for making [`Dtab`]s.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate dtab;
/// # fn main() {
/// use dtab::NameTree;
///
/// let dtab = dtab![
///   "/smitten"       => NameTree::from("/USA/CA/SF/Harrison/2790");
///   "/iceCreamStore" => NameTree::from("/humphrys") | "/smitten";
/// ];
///
///
/// assert_eq!( &format!("{}", dtab)
///           , "/smitten => /USA/CA/SF/Harrison/2790;\n\
///              /iceCreamStore => /humphrys | /smitten;\n"
///           );
/// # }
/// ```
///
/// [`Dtab`]: type.Dtab.html
#[macro_export]
macro_rules! dtab {
  ($($src: expr => $dst: expr ;)+) => (
    $crate::Dtab(vec![ $(dentry!($src => $dst)),+ ])
  )
}
/// A `dtab` (delegation table) comprises a sequence of delegation rules.
#[derive(Debug, Clone, Serialize)]
pub struct Dtab(pub Vec<Dentry>);

impl fmt::Display for Dtab {
    #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.iter()
            .fold( Ok(())
                 , |r, ref entry| r.and_then(|_| {
                        write!(f, "{}\n", entry)
                    }))

    }
}

#[derive(Debug, Clone, Serialize)]
pub struct Dentry {
    #[serde(serialize_with ="nametree::serialize")]
    pub prefix: NameTree<String>
  , #[serde(serialize_with ="nametree::serialize")]
    pub dst: NameTree<String>
}

impl fmt::Display for Dentry {
    #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} => {};", self.prefix, self.dst)
    }
}
<|endoftext|>


<commit_before>//! This library provides an API client for [Diffbot](https://www.diffbot.com)
//!
//! See also [the diffbot documentation](https://www.diffbot.com/dev/docs/).
//!
//! # Example
//!
//! ```
//! extern crate diffbot;
//! use diffbot::*;
//!
//! fn main() {
//!     let client = Diffbot::v3("insert_your_token_here");
//!     match client.call(API::Analyze, "http://www.diffbot.com") {
//!         Ok(result) =>
//!             println!("{:?}", result),
//!         Err(Error::Api(code, msg)) =>
//!             println!("API returned error {}: {}", code, msg),
//!         Err(err) =>
//!             println!("Other error: {:?}", err),
//!     };
//! }
//! ```

extern crate url;
extern crate hyper;
extern crate rustc_serialize;

use hyper::header::ContentType;
use hyper::mime::{Mime, TopLevel, SubLevel};

use std::error::{self, Error as StdError};
use std::io;
use std::fmt;

use rustc_serialize::json;

/// Diffbot API client.
///
/// # Example
///
/// ```
/// # extern crate diffbot;
/// # use diffbot::*;
/// # fn main() {
/// let diffbot = Diffbot::v3("token");
/// let result = diffbot.call(API::Analyze, "http://diffbot.com");
/// # println!("{:?}", result);
/// # }
/// ```
pub struct Diffbot {
    token: String,
    version: u32,

    client: hyper::Client,
}

/// One of the possible diffbot API.
///
/// See [the diffbot documentation](https://www.diffbot.com/dev/docs/).
pub enum API {
    /// The analyze API automatically detects the page type.
    Analyze,
    /// The article API for news article.
    Article,
    /// The product API for products in online shops.
    Product,
    /// The discussion API for forums.
    Discussion,
    /// The image API for image-central pages.
    Image,
    /// The video API for video pages (youtube, ...).
    Video,
}

impl API {
    fn get_str(&self) -> &'static str {
        match self {
            &API::Analyze => "analyze",
            &API::Article => "article",
            &API::Product => "product",
            &API::Discussion => "discussion",
            &API::Image => "image",
            &API::Video => "video",
        }
    }

    fn get_url(&self) -> String {
        format!("https://diffbot.com/api/{}", self.get_str())
    }
}

/// Error occuring during a call.
#[derive(Debug)]
pub enum Error {
    /// The API returned an error.
    Api(u32, String),
    /// An error occured when decoding JSON from the API.
    Json,
    /// An error occured with the network.
    Io(io::Error),
    // TODO: don't expose hyper
    /// An HTTP error occured with the webserver.
    Http(hyper::Error),
}

impl From<json::ParserError> for Error {
    fn from(err: json::ParserError) -> Self {
        match err {
            json::ParserError::SyntaxError(_, _, _) => Error::Json,
            json::ParserError::IoError(err) => Error::Io(err),
        }
    }
}

impl From<hyper::Error> for Error {
    fn from(err: hyper::Error) -> Self {
        Error::Http(err)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::Api(_, ref msg) => msg,
            &Error::Json => "invalid JSON",
            &Error::Io(ref err) => err.description(),
            &Error::Http(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::Api(_, _) => None,
            &Error::Json => None,
            &Error::Io(ref err) => Some(err),
            &Error::Http(ref err) => Some(err),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

/// Result from a call.
pub type DiffbotResult = Result<json::Object, Error>;

impl Diffbot {
    /// Returns a Diffbot client that uses the given token and version.
    ///
    /// Valid versions: `1`, `2`, `3`.
    pub fn new<S: ToString>(token: S, version: u32) -> Self {
        Diffbot {
            token: token.to_string(),
            version: version,
            client: hyper::Client::new(),
        }
    }

    /// Convenient method to use a v1 client.
    pub fn v1<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 1)
    }

    /// Convenient method to use a v2 client.
    pub fn v2<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 2)
    }

    /// Convenient method to use a v3 client (recommended).
    pub fn v3<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 3)
    }

    /// Makes an API call without extra options.
    ///
    /// Just calls `call_with_options` with an empty option list.
    pub fn call(&self, api: API, target_url: &str) -> DiffbotResult {
        self.call_with_options::<String>(api, target_url, &[])
    }

    /// Makes an API call
    ///
    /// Runs `target_url` through the diffbot endpoint specified by `api`.
    /// Add each (key,value) pair in `options` to the query string.
    /// Read the [diffbot documentation](https://www.diffbot.com/dev/docs/)
    /// for information on supported values.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}",
    /// diffbot.call_with_options(API::Article,
    ///                           "http://diffbot.com",
    ///                           &[("paging", "false")])
    /// # );
    /// # }
    /// ```
    pub fn call_with_options<S: ToString>(&self,
                                          api: API,
                                          target_url: &str,
                                          options: &[(S, S)])
                                          -> DiffbotResult {
        let url = self.prepare_url(api, target_url, options);

        let builder = self.client.get(url);
        Diffbot::process_request(builder)
    }

    /// Posti an entire html body to the API, without extra options.
    ///
    /// See `call_with_options` for information on the arguments.
    ///
    /// `target_url` here is the URL the page would have.
    /// It doesn't have to be accessible, but will be used when resolving links.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}", {
    /// let body = b"<html>...</html>";
    /// diffbot.post_body(API::Article,
    ///                   "http://my.website.com",
    ///                   body)
    /// # } );
    /// # }
    /// ```
    pub fn post_body(&self, api: API, target_url: &str, body: &[u8]) -> DiffbotResult {
        self.post_body_with_options::<String>(api, target_url, body, &[])
    }

    /// Posti an entire html body to the API.
    ///
    /// See `call_with_options` for information on the arguments.
    ///
    /// `target_url` here is the URL the page would have.
    /// It doesn't have to be accessible, but will be used when resolving links.
    pub fn post_body_with_options<S: ToString>(&self,
                                               api: API,
                                               target_url: &str,
                                               body: &[u8],
                                               options: &[(S, S)])
                                               -> DiffbotResult {
        let url = self.prepare_url(api, target_url, options);

        let header = ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]));
        let builder = self.client.post(url).body(body).header(header);
        Diffbot::process_request(builder)
    }

    /// Run a search in a diffbot collection without extra options.
    ///
    /// Use `col` = `GLOBAL-INDEX` for the global search collection.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}",
    /// diffbot.search("GLOBAL-INDEX", "diffbot")
    /// # );
    /// # }
    /// ```
    pub fn search(&self, col: &str, query: &str) -> DiffbotResult {
        self.search_with_options::<String>(col, query, &[])
    }

    /// Run a search in a diffbot collection.
    ///
    /// Use `col` = `GLOBAL-INDEX` for the global search collection.
    pub fn search_with_options<S: ToString>(&self,
                                            col: &str,
                                            query: &str,
                                            options: &[(S, S)])
                                            -> DiffbotResult {
        let url = self.prepare_search_url(col, query, options);

        let builder = self.client.get(url);
        Diffbot::process_request(builder)
    }

    // TODO: add crawlbot API

    // Process a request and analyze the result
    fn process_request(builder: hyper::client::RequestBuilder) -> DiffbotResult {
        let mut result = try!(builder.send());

        let json_result = match try!(json::Json::from_reader(&mut result)) {
            json::Json::Object(obj) => obj,
            _ => return Err(Error::Json),
        };

        if json_result.contains_key("error") {
            let error_code = json_result.get("errorCode")
                                        .and_then(|c| c.as_u64())
                                        .unwrap_or(0u64);
            let error = json_result["error"].as_string().unwrap_or("");
            return Err(Error::Api(error_code as u32, error.to_string()));
        }

        Ok(json_result)
    }

    fn prepare_search_url<S: ToString>(&self,
                                       col: &str,
                                       query: &str,
                                       options: &[(S, S)])
                                       -> hyper::Url {
        let mut params = Vec::<(String, String)>::new();
        params.push(("token".to_string(), self.token.clone()));
        params.push(("version".to_string(), self.version.to_string()));
        params.push(("col".to_string(), col.to_string()));
        params.push(("query".to_string(), query.to_string()));
        for &(ref key, ref value) in options.iter() {
            params.push((key.to_string(), value.to_string()));
        }

        // We control the URL, it should always be valid.
        let mut url = hyper::Url::parse("https://diffbot.com/api/search").unwrap();
        url.set_query_from_pairs(&params);

        url
    }

    // Returns the diffbot URL for the given call
    fn prepare_url<S: ToString>(&self,
                                api: API,
                                target_url: &str,
                                options: &[(S, S)])
                                -> hyper::Url {

        let mut params = Vec::<(String, String)>::new();
        params.push(("token".to_string(), self.token.clone()));
        params.push(("version".to_string(), self.version.to_string()));
        params.push(("url".to_string(), target_url.to_string()));
        for &(ref key, ref value) in options.iter() {
            params.push((key.to_string(), value.to_string()));
        }

        // We control the URL, it should always be valid.
        let mut url = hyper::Url::parse(&api.get_url()).unwrap();
        url.set_query_from_pairs(&params);

        url
    }
}

#[test]
fn test_search() {
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.search("GLOBAL-INDEX", "diffbot"));
}

#[test]
fn test_search_with_options() {
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.search_with_options("GLOBAL-INDEX",
                                                 "site:techcrunch.com sortby:date",
                                                 &[("num", "2")]));
}

#[test]
fn test_call() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.call(API::Analyze, "http://diffbot.com"));
}

#[test]
fn test_call_with_options() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.call_with_options(API::Analyze,
                                               "http://diffbot.com",
                                               &[("fields", "links,meta")]));
}

#[test]
fn test_post() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    let res = diffbot.post_body(API::Article,
                                "http://my.website.com",
                                br#"

        <title>My Website</title>

My Website

This is a fake website, yet we will analyze its content.
           Isn't it interesting?

"#);

    println!("{:?}", res);
}
<commit_msg>Add user agent on calls<commit_after>//! This library provides an API client for [Diffbot](https://www.diffbot.com)
//!
//! See also [the diffbot documentation](https://www.diffbot.com/dev/docs/).
//!
//! # Example
//!
//! ```
//! extern crate diffbot;
//! use diffbot::*;
//!
//! fn main() {
//!     let client = Diffbot::v3("insert_your_token_here");
//!     match client.call(API::Analyze, "http://www.diffbot.com") {
//!         Ok(result) =>
//!             println!("{:?}", result),
//!         Err(Error::Api(code, msg)) =>
//!             println!("API returned error {}: {}", code, msg),
//!         Err(err) =>
//!             println!("Other error: {:?}", err),
//!     };
//! }
//! ```

extern crate url;
extern crate hyper;
extern crate rustc_serialize;

use hyper::header::{ContentType, UserAgent};
use hyper::mime::{Mime, SubLevel, TopLevel};

use std::error::{self, Error as StdError};
use std::io;
use std::fmt;

use rustc_serialize::json;

pub fn user_agent() -> UserAgent {
    UserAgent("diffbot/rust".to_owned())
}

/// Diffbot API client.
///
/// # Example
///
/// ```
/// # extern crate diffbot;
/// # use diffbot::*;
/// # fn main() {
/// let diffbot = Diffbot::v3("token");
/// let result = diffbot.call(API::Analyze, "http://diffbot.com");
/// # println!("{:?}", result);
/// # }
/// ```
pub struct Diffbot {
    token: String,
    version: u32,

    client: hyper::Client,
}

/// One of the possible diffbot API.
///
/// See [the diffbot documentation](https://www.diffbot.com/dev/docs/).
pub enum API {
    /// The analyze API automatically detects the page type.
    Analyze,
    /// The article API for news article.
    Article,
    /// The product API for products in online shops.
    Product,
    /// The discussion API for forums.
    Discussion,
    /// The image API for image-central pages.
    Image,
    /// The video API for video pages (youtube, ...).
    Video,
}

impl API {
    fn get_str(&self) -> &'static str {
        match self {
            &API::Analyze => "analyze",
            &API::Article => "article",
            &API::Product => "product",
            &API::Discussion => "discussion",
            &API::Image => "image",
            &API::Video => "video",
        }
    }

    fn get_url(&self) -> String {
        format!("https://diffbot.com/api/{}", self.get_str())
    }
}

/// Error occuring during a call.
#[derive(Debug)]
pub enum Error {
    /// The API returned an error.
    Api(u32, String),
    /// An error occured when decoding JSON from the API.
    Json,
    /// An error occured with the network.
    Io(io::Error),
    // TODO: don't expose hyper
    /// An HTTP error occured with the webserver.
    Http(hyper::Error),
}

impl From<json::ParserError> for Error {
    fn from(err: json::ParserError) -> Self {
        match err {
            json::ParserError::SyntaxError(_, _, _) => Error::Json,
            json::ParserError::IoError(err) => Error::Io(err),
        }
    }
}

impl From<hyper::Error> for Error {
    fn from(err: hyper::Error) -> Self {
        Error::Http(err)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::Api(_, ref msg) => msg,
            &Error::Json => "invalid JSON",
            &Error::Io(ref err) => err.description(),
            &Error::Http(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::Api(_, _) => None,
            &Error::Json => None,
            &Error::Io(ref err) => Some(err),
            &Error::Http(ref err) => Some(err),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

/// Result from a call.
pub type DiffbotResult = Result<json::Object, Error>;

impl Diffbot {
    /// Returns a Diffbot client that uses the given token and version.
    ///
    /// Valid versions: `1`, `2`, `3`.
    pub fn new<S: ToString>(token: S, version: u32) -> Self {
        Diffbot {
            token: token.to_string(),
            version: version,
            client: hyper::Client::new(),
        }
    }

    /// Convenient method to use a v1 client.
    pub fn v1<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 1)
    }

    /// Convenient method to use a v2 client.
    pub fn v2<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 2)
    }

    /// Convenient method to use a v3 client (recommended).
    pub fn v3<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 3)
    }

    /// Makes an API call without extra options.
    ///
    /// Just calls `call_with_options` with an empty option list.
    pub fn call(&self, api: API, target_url: &str) -> DiffbotResult {
        self.call_with_options::<String>(api, target_url, &[])
    }

    /// Makes an API call
    ///
    /// Runs `target_url` through the diffbot endpoint specified by `api`.
    /// Add each (key,value) pair in `options` to the query string.
    /// Read the [diffbot documentation](https://www.diffbot.com/dev/docs/)
    /// for information on supported values.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}",
    /// diffbot.call_with_options(API::Article,
    ///                           "http://diffbot.com",
    ///                           &[("paging", "false")])
    /// # );
    /// # }
    /// ```
    pub fn call_with_options<S: ToString>(&self, api: API, target_url: &str,
                                          options: &[(S, S)])
                                          -> DiffbotResult {
        let url = self.prepare_url(api, target_url, options);

        let builder = self.client.get(url).header(user_agent());
        Diffbot::process_request(builder)
    }

    /// Posti an entire html body to the API, without extra options.
    ///
    /// See `call_with_options` for information on the arguments.
    ///
    /// `target_url` here is the URL the page would have.
    /// It doesn't have to be accessible, but will be used when resolving links.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}", {
    /// let body = b"<html>...</html>";
    /// diffbot.post_body(API::Article,
    ///                   "http://my.website.com",
    ///                   body)
    /// # } );
    /// # }
    /// ```
    pub fn post_body(&self, api: API, target_url: &str, body: &[u8])
                     -> DiffbotResult {
        self.post_body_with_options::<String>(api, target_url, body, &[])
    }

    /// Posti an entire html body to the API.
    ///
    /// See `call_with_options` for information on the arguments.
    ///
    /// `target_url` here is the URL the page would have.
    /// It doesn't have to be accessible, but will be used when resolving links.
    pub fn post_body_with_options<S: ToString>(&self, api: API,
                                               target_url: &str, body: &[u8],
                                               options: &[(S, S)])
                                               -> DiffbotResult {
        let url = self.prepare_url(api, target_url, options);

        let content_type = ContentType(Mime(TopLevel::Text,
                                            SubLevel::Html,
                                            vec![]));
        let builder = self.client
                          .post(url)
                          .body(body)
                          .header(content_type)
                          .header(user_agent());
        Diffbot::process_request(builder)
    }

    /// Run a search in a diffbot collection without extra options.
    ///
    /// Use `col` = `GLOBAL-INDEX` for the global search collection.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}",
    /// diffbot.search("GLOBAL-INDEX", "diffbot")
    /// # );
    /// # }
    /// ```
    pub fn search(&self, col: &str, query: &str) -> DiffbotResult {
        self.search_with_options::<String>(col, query, &[])
    }

    /// Run a search in a diffbot collection.
    ///
    /// Use `col` = `GLOBAL-INDEX` for the global search collection.
    pub fn search_with_options<S: ToString>(&self, col: &str, query: &str,
                                            options: &[(S, S)])
                                            -> DiffbotResult {
        let url = self.prepare_search_url(col, query, options);

        let builder = self.client.get(url).header(user_agent());
        Diffbot::process_request(builder)
    }

    // TODO: add crawlbot API

    // Process a request and analyze the result
    fn process_request(builder: hyper::client::RequestBuilder) -> DiffbotResult {
        let mut result = try!(builder.send());

        let json_result = match try!(json::Json::from_reader(&mut result)) {
            json::Json::Object(obj) => obj,
            _ => return Err(Error::Json),
        };

        if json_result.contains_key("error") {
            let error_code = json_result.get("errorCode")
                                        .and_then(|c| c.as_u64())
                                        .unwrap_or(0u64);
            let error = json_result["error"].as_string().unwrap_or("");
            return Err(Error::Api(error_code as u32, error.to_string()));
        }

        Ok(json_result)
    }

    fn prepare_search_url<S: ToString>(&self, col: &str, query: &str,
                                       options: &[(S, S)])
                                       -> hyper::Url {
        let mut params = Vec::<(String, String)>::new();
        params.push(("token".to_string(), self.token.clone()));
        params.push(("version".to_string(), self.version.to_string()));
        params.push(("col".to_string(), col.to_string()));
        params.push(("query".to_string(), query.to_string()));
        for &(ref key, ref value) in options.iter() {
            params.push((key.to_string(), value.to_string()));
        }

        // We control the URL, it should always be valid.
        let mut url = hyper::Url::parse("https://diffbot.com/api/search")
                          .unwrap();
        url.set_query_from_pairs(&params);

        url
    }

    // Returns the diffbot URL for the given call
    fn prepare_url<S: ToString>(&self, api: API, target_url: &str,
                                options: &[(S, S)])
                                -> hyper::Url {

        let mut params = Vec::<(String, String)>::new();
        params.push(("token".to_string(), self.token.clone()));
        params.push(("version".to_string(), self.version.to_string()));
        params.push(("url".to_string(), target_url.to_string()));
        for &(ref key, ref value) in options.iter() {
            params.push((key.to_string(), value.to_string()));
        }

        // We control the URL, it should always be valid.
        let mut url = hyper::Url::parse(&api.get_url()).unwrap();
        url.set_query_from_pairs(&params);

        url
    }
}

#[test]
fn test_search() {
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.search("GLOBAL-INDEX", "diffbot"));
}

#[test]
fn test_search_with_options() {
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}",
             diffbot.search_with_options("GLOBAL-INDEX",
                                         "site:techcrunch.com sortby:date",
                                         &[("num", "2")]));
}

#[test]
fn test_call() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.call(API::Analyze, "http://diffbot.com"));
}

#[test]
fn test_call_with_options() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}",
             diffbot.call_with_options(API::Analyze,
                                       "http://diffbot.com",
                                       &[("fields", "links,meta")]));
}

#[test]
fn test_post() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    let res = diffbot.post_body(API::Article,
                                "http://my.website.com",
                                br#"

        <title>My Website</title>

My Website

This is a fake website, yet we will analyze its content.
           Isn't it interesting?

"#);

    println!("{:?}", res);
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Mul,Div,Neg,Rem};

pub struct LimitVal {
    val : Result<u8,u8>,
    min : u8,
    max : u8
}

impl LimitVal {
    fn new(val:u8) -> LimitVal {
        if val > 0 && val < 10 { //0 and 10 replaced by macro for realz
            LimitVal{val: Ok(val), min: 0, max: 10} //0 and 10 used for illustration
        } else {
            LimitVal{val: Err(val), min: 0, max: 10} //0 and 10 used for illustration
        }
    }

    fn unwrap(&self) -> u8 {
        self.val.unwrap()
    }

    fn unwrap_err(&self) -> u8 {
        self.val.unwrap_err()
    }

    fn expect(&self, msg: &str) -> u8 {
       self.val.expect(msg)
    }

    fn map<F>(&self, op:F) -> LimitVal
        where F: Fn(u8) -> u8 {
        match self.val {
            Ok(x) => LimitVal::new(op(x)),
            Err(x) => LimitVal::new(op(x))
        }

    }

}

impl Add for LimitVal {
    type Output = LimitVal;

    fn add(self, other: LimitVal) -> LimitVal {
        match self.val {
            Ok(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x+y), //both are Ok
                    Err(y) => LimitVal::new(x+y)
                }
            }
            Err(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x+y),
                    Err(y) => LimitVal::new(x+y)
                }
            }

        }
    }
}

impl Sub for LimitVal {
    type Output = LimitVal;

    fn sub(self, other: LimitVal) -> LimitVal {
        match self.val {
            Ok(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x-y), //both are Ok
                    Err(y) => LimitVal::new(x-y)
                }
            }
            Err(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x-y),
                    Err(y) => LimitVal::new(x-y)
                }
            }

        }
    }
}

impl Div for LimitVal {
    type Output = LimitVal;

    fn div(self, other: LimitVal) -> LimitVal {
        match self.val {
            Ok(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x/y), //both are Ok
                    Err(y) => LimitVal::new(x/y)
                }
            }
            Err(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x/y),
                    Err(y) => LimitVal::new(x/y)
                }
            }

        }
    }
}

impl Mul for LimitVal {
    type Output = LimitVal;

    fn mul(self, other: LimitVal) -> LimitVal {
        match self.val {
            Ok(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x*y), //both are Ok
                    Err(y) => LimitVal::new(x*y)
                }
            }
            Err(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x*y),
                    Err(y) => LimitVal::new(x*y)
                }
            }

        }
    }
}

impl Rem for LimitVal {
    type Output = LimitVal;

    fn rem(self, other: LimitVal) -> LimitVal {
        match self.val {
            Ok(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x%y), //both are Ok
                    Err(y) => LimitVal::new(x%y)
                }
            }
            Err(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x%y),
                    Err(y) => LimitVal::new(x%y)
                }
            }

        }
    }
}

impl Neg for LimitVal {
    type Output = LimitVal;

    fn neg(self) -> LimitVal {
        match self.val {
            Ok(x) => LimitVal::new(-x),
            Err(y) => LimitVal::new(-y)
        }
    }
}

#[cfg(test)]
mod tests {
    /*
    Can always put in own file, then would need:
    extern crate adder; (or whatever)
    and then namespace:: the functions.
    */
    use super::*;

    #[test]
    fn test_add() {
        let x: LimitVal = LimitVal::new(2);
        let y: LimitVal = LimitVal::new(3);

        let z = x + y;
        assert_eq!(z.unwrap(),5);
    }

    #[test]
    fn test_sub() {
        let x: LimitVal = LimitVal::new(2);
        let y: LimitVal = LimitVal::new(3);

        let z = y - x;
        assert_eq!(z.unwrap(),1);
    }
    #[test]
    fn test_div() {
        let x: LimitVal = LimitVal::new(4);
        let y: LimitVal = LimitVal::new(2);

        let z = x/y;
        assert_eq!(z.unwrap(),2);
    }
    #[test]
    fn test_mul() {
        let x: LimitVal = LimitVal::new(2);
        let y: LimitVal = LimitVal::new(3);

        let z = y * x;
        assert_eq!(z.unwrap(),6);
    }
    #[test]
    fn test_rem() {
        let x: LimitVal = LimitVal::new(5);
        let y: LimitVal = LimitVal::new(2);

        let z = x % y;
        assert_eq!(z.unwrap(),1);
    }
    #[test]
    #[should_panic]
    fn test_neg() {
        let x: LimitVal = LimitVal::new(2);
        let z = -x;
        assert_eq!(z.unwrap(), -2);
    }
    #[test]
    fn test_map() {
        let x: LimitVal = LimitVal::new(2);
        let f = |t| { t + 1};

        let z = x.map(f);
        assert_eq!(z.unwrap(),3);
    }
}
<commit_msg>Comments. Next step macro?<commit_after>use std::ops::{Add, Sub, Mul,Div,Neg,Rem};

pub struct LimitVal {
    val : Result<u8,u8>,
    min : u8,
    max : u8
}

impl LimitVal {

    /// Makes a new value inside the range specified by the macro.
    fn new(val:u8) -> LimitVal {
        if val > 0 && val < 10 { //0 and 10 replaced by macro for realz
            LimitVal{val: Ok(val), min: 0, max: 10} //0 and 10 used for illustration
        } else {
            LimitVal{val: Err(val), min: 0, max: 10} //0 and 10 used for illustration
        }
    }

    /// Pulls out the inner value if Ok, else panics.
    fn unwrap(&self) -> u8 {
        self.val.unwrap()
    }

    /// Pulls out the inner value if Err, else panics.
    fn unwrap_err(&self) -> u8 {
        self.val.unwrap_err()
    }

    /// Pulls out the inner value if ok, else prints msg.
    fn expect(&self, msg: &str) -> u8 {
       self.val.expect(msg)
    }

    /// Runs f on the current value.
    fn map<F>(&self, op:F) -> LimitVal
        where F: Fn(u8) -> u8 {
        match self.val {
            Ok(x) => LimitVal::new(op(x)),
            Err(x) => LimitVal::new(op(x))
        }

    }

    /// Runs f on val if val is err, else returns val.
    fn fix<F>(&self, op:F) -> LimitVal
        where F: Fn(u8) -> u8 {
        match self.val {
            Ok(x) => LimitVal::new(x),
            Err(x) => LimitVal::new(op(x))
        }

    }

}

impl Add for LimitVal {
    type Output = LimitVal;

    fn add(self, other: LimitVal) -> LimitVal {
        match self.val {
            Ok(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x+y), //both are Ok
                    Err(y) => LimitVal::new(x+y)
                }
            }
            Err(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x+y),
                    Err(y) => LimitVal::new(x+y)
                }
            }

        }
    }
}

impl Sub for LimitVal {
    type Output = LimitVal;

    fn sub(self, other: LimitVal) -> LimitVal {
        match self.val {
            Ok(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x-y), //both are Ok
                    Err(y) => LimitVal::new(x-y)
                }
            }
            Err(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x-y),
                    Err(y) => LimitVal::new(x-y)
                }
            }

        }
    }
}

impl Div for LimitVal {
    type Output = LimitVal;

    fn div(self, other: LimitVal) -> LimitVal {
        match self.val {
            Ok(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x/y), //both are Ok
                    Err(y) => LimitVal::new(x/y)
                }
            }
            Err(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x/y),
                    Err(y) => LimitVal::new(x/y)
                }
            }

        }
    }
}

impl Mul for LimitVal {
    type Output = LimitVal;

    fn mul(self, other: LimitVal) -> LimitVal {
        match self.val {
            Ok(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x*y), //both are Ok
                    Err(y) => LimitVal::new(x*y)
                }
            }
            Err(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x*y),
                    Err(y) => LimitVal::new(x*y)
                }
            }

        }
    }
}

impl Rem for LimitVal {
    type Output = LimitVal;

    fn rem(self, other: LimitVal) -> LimitVal {
        match self.val {
            Ok(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x%y), //both are Ok
                    Err(y) => LimitVal::new(x%y)
                }
            }
            Err(x) => {
                match other.val {
                    Ok(y) => LimitVal::new(x%y),
                    Err(y) => LimitVal::new(x%y)
                }
            }

        }
    }
}

impl Neg for LimitVal {
    type Output = LimitVal;

    fn neg(self) -> LimitVal {
        match self.val {
            Ok(x) => LimitVal::new(-x),
            Err(y) => LimitVal::new(-y)
        }
    }
}

#[cfg(test)]
mod tests {
    /*
    Can always put in own file, then would need:
    extern crate adder; (or whatever)
    and then namespace:: the functions.
    */
    use super::*;

    #[test]
    fn test_add() {
        let x: LimitVal = LimitVal::new(2);
        let y: LimitVal = LimitVal::new(3);

        let z = x + y;
        assert_eq!(z.unwrap(),5);
    }

    #[test]
    fn test_sub() {
        let x: LimitVal = LimitVal::new(2);
        let y: LimitVal = LimitVal::new(3);

        let z = y - x;
        assert_eq!(z.unwrap(),1);
    }
    #[test]
    fn test_div() {
        let x: LimitVal = LimitVal::new(4);
        let y: LimitVal = LimitVal::new(2);

        let z = x/y;
        assert_eq!(z.unwrap(),2);
    }
    #[test]
    fn test_mul() {
        let x: LimitVal = LimitVal::new(2);
        let y: LimitVal = LimitVal::new(3);

        let z = y * x;
        assert_eq!(z.unwrap(),6);
    }
    #[test]
    fn test_rem() {
        let x: LimitVal = LimitVal::new(5);
        let y: LimitVal = LimitVal::new(2);

        let z = x % y;
        assert_eq!(z.unwrap(),1);
    }
    #[test]
    #[should_panic]
    fn test_neg() {
        let x: LimitVal = LimitVal::new(2);
        let z = -x;
        assert_eq!(z.unwrap(), -2);
    }
    #[test]
    fn test_map() {
        let x: LimitVal = LimitVal::new(2);
        let f = |t| { t + 1};

        let z = x.map(f);
        assert_eq!(z.unwrap(),3);
    }
    #[test]
    fn test_fix() {
        let x = LimitVal::new(20);
        let f = | t : u8 | {
            let mut z : u8 = t;
            while z > x.max {
                z = t / 10;
            }
            z
        };
        let y = x.fix(f);
        assert_eq!(y.unwrap(),2);
    }
}
<|endoftext|>