<commit_before>//
// base64n.rs - new base64 module
//
// The Base64 Alphabet
//
//  Value Encoding  Value Encoding  Value Encoding  Value Encoding
//      0 A            17 R            34 i            51 z
//      1 B            18 S            35 j            52 0
//      2 C            19 T            36 k            53 1
//      3 D            20 U            37 l            54 2
//      4 E            21 V            38 m            55 3
//      5 F            22 W            39 n            56 4
//      6 G            23 X            40 o            57 5
//      7 H            24 Y            41 p            58 6
//      8 I            25 Z            42 q            59 7
//      9 J            26 a            43 r            60 8
//     10 K            27 b            44 s            61 9
//     11 L            28 c            45 t            62 +
//     12 M            29 d            46 u            63 /
//     13 N            30 e            47 v
//     14 O            31 f            48 w         (pad) =
//     15 P            32 g            49 x
//     16 Q            33 h            50 y
//
// The "URL and Filename safe" Base 64 Alphabet
//
// Value Encoding  Value Encoding  Value Encoding  Value Encoding
//     0 A            17 R            34 i            51 z
//     1 B            18 S            35 j            52 0
//     2 C            19 T            36 k            53 1
//     3 D            20 U            37 l            54 2
//     4 E            21 V            38 m            55 3
//     5 F            22 W            39 n            56 4
//     6 G            23 X            40 o            57 5
//     7 H            24 Y            41 p            58 6
//     8 I            25 Z            42 q            59 7
//     9 J            26 a            43 r            60 8
//    10 K            27 b            44 s            61 9
//    11 L            28 c            45 t            62 - (minus)
//    12 M            29 d            46 u            63 _ (underline)
//    13 N            30 e            47 v
//    14 O            31 f            48 w
//    15 P            32 g            49 x
//    16 Q            33 h            50 y         (pad) =
//

use std;

import vec::len;

const PAD: u8 = 61u8;

iface enc {
    fn encode(dst: [mutable u8], src: [u8]);
    fn encode_u(dst: [mutable u8], src: [u8]);
    fn encode_bytes(src: [u8]) -> [u8];
    fn encode_bytes_u(src: [u8]) -> [u8];
    fn encode_str(src: str) -> str;
    fn encode_str_u(src: str) -> str;
    // FIXME `decode` and `decode_u` should return desired length of `dst`
    fn decode(dst: [mutable u8], src: [u8]);
    fn decode_u(dst: [mutable u8], src: [u8]);
    fn decode_bytes(src: [u8]) -> [u8];
    fn decode_bytes_u(src: [u8]) -> [u8];
}

fn mk() -> enc {
    type _enc = {table: [u8], table_u: [u8],
                 decode_map: [u8], decode_map_u: [u8]};

    impl of enc for _enc {
        fn encode(dst: [mutable u8], src: [u8]) {
            b64encode(self.table, dst, src);
        }
        fn encode_u(dst: [mutable u8], src: [u8]) {
            b64encode(self.table_u, dst, src);
        }
        fn encode_bytes(src: [u8]) -> [u8] {
            let dst_length = encoded_len(len(src));
            let dst = vec::to_mut(vec::from_elem(dst_length, 0u8));
            self.encode(dst, src);
            vec::from_mut(dst)
        }
        fn encode_bytes_u(src: [u8]) -> [u8] {
            let dst_length = encoded_len(len(src));
            let dst = vec::to_mut(vec::from_elem(dst_length, 0u8));
            self.encode_u(dst, src);
            vec::from_mut(dst)
        }
        fn encode_str(src: str) -> str {
            let src = str::bytes(src);
            str::from_bytes(self.encode_bytes(src))
        }
        fn encode_str_u(src: str) -> str {
            let src = str::bytes(src);
            str::from_bytes(self.encode_bytes_u(src))
        }
        fn decode(dst: [mutable u8], src: [u8]) {
            b64decode(self.decode_map, dst, src);
        }
        fn decode_u(dst: [mutable u8], src: [u8]) {
            b64decode(self.decode_map_u, dst, src);
        }
        fn decode_bytes(src: [u8]) -> [u8] { [] }
        fn decode_bytes_u(src: [u8]) -> [u8] { [] }
    }

    let table = vec::to_mut(vec::from_elem(64u, 0u8)), i = 0u8;
    u8::range(65u8, 91u8)  { |j| table[i] = j; i += 1u8; }
    u8::range(97u8, 123u8) { |j| table[i] = j; i += 1u8; }
    u8::range(48u8, 58u8)  { |j| table[i] = j; i += 1u8; }
    table[i] = 43u8; table[i + 1u8] = 47u8;

    let table_u = table;
    table_u[i] = 45u8; table_u[i + 1u8] = 95u8;

    let decode_map = vec::to_mut(vec::from_elem(256u, 0xff_u8));
    let decode_map_u = vec::to_mut(vec::from_elem(256u, 0xff_u8));

    i = 0u8;
    while i < 64u8 {
        decode_map[table[i]] = i as u8;
        i += 1u8;
    }

    i = 0u8;
    while i < 64u8 {
        decode_map_u[table_u[i]] = i as u8;
        i += 1u8;
    }

    {table: vec::from_mut(table),
     table_u: vec::from_mut(table_u),
     decode_map: vec::from_mut(decode_map),
     decode_map_u: vec::from_mut(decode_map_u)} as enc
}

fn encoded_len(src_length: uint) -> uint {
    (src_length + 2u) / 3u * 4u
}

fn decoded_len(src_length: uint) -> uint {
    src_length / 4u * 3u
}

fn b64encode(table: [u8], dst: [mutable u8], src: [u8]) {
    if len(src) == 0u {
        ret;
    }

    let src_length = len(src);
    let dst_length = len(dst);
    let dst_curr = 0u;
    let src_curr = 0u;

    if dst_length % 4u != 0u {
        fail "dst's length should be divisible by 4";
    }

    while src_length > 0u {
        dst[dst_curr + 0u] = 0u8;
        dst[dst_curr + 1u] = 0u8;
        dst[dst_curr + 2u] = 0u8;
        dst[dst_curr + 3u] = 0u8;

        if src_length == 1u {
            dst[dst_curr + 0u] |= (src[src_curr + 0u]) >> 2u8;
            dst[dst_curr + 1u] |= (src[src_curr + 0u] << 4u8) & 0x3f_u8;
        } else if src_length == 2u {
            dst[dst_curr + 0u] |= (src[src_curr + 0u]) >> 2u8;
            dst[dst_curr + 1u] |= (src[src_curr + 0u] << 4u8) & 0x3f_u8;
            dst[dst_curr + 1u] |= (src[src_curr + 1u] >> 4u8);
            dst[dst_curr + 2u] |= (src[src_curr + 1u] << 2u8) & 0x3f_u8;
        } else {
            dst[dst_curr + 0u] |= (src[src_curr + 0u]) >> 2u8;
            dst[dst_curr + 1u] |= (src[src_curr + 0u] << 4u8) & 0x3f_u8;
            dst[dst_curr + 1u] |= (src[src_curr + 1u] >> 4u8);
            dst[dst_curr + 2u] |= (src[src_curr + 1u] << 2u8) & 0x3f_u8;
            dst[dst_curr + 2u] |= (src[src_curr + 2u] >> 6u8);
            dst[dst_curr + 3u] |= (src[src_curr + 2u]) & 0x3f_u8;
        }

        dst[dst_curr + 0u] = table[dst[dst_curr + 0u]];
        dst[dst_curr + 1u] = table[dst[dst_curr + 1u]];
        dst[dst_curr + 2u] = table[dst[dst_curr + 2u]];
        dst[dst_curr + 3u] = table[dst[dst_curr + 3u]];

        if src_length < 3u {
            dst[dst_curr + 3u] = PAD;
            if src_length < 2u {
                dst[dst_curr + 2u] = PAD;
            }
            break;
        }

        src_length -= 3u;
        src_curr += 3u;
        dst_curr += 4u;
    }
}

fn b64decode(table: [u8], dst: [mutable u8], src: [u8]) {
    // FIXME write
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_encode_bytes() {
        let src = [102u8, 111u8, 111u8, 98u8, 97u8, 114u8];
        let enc = mk();
        let res = enc.encode_bytes(src);
        assert res == [90u8, 109u8, 57u8, 118u8, 89u8, 109u8, 70u8, 121u8];
    }
    #[test]
    fn test_encode_str() {
        let src = "foobar";
        let enc = mk();
        let res = enc.encode_str(src);
        assert res == "Zm9vYmFy";
    }
}
<commit_msg>base64n: Add test for encode_*_u methods<commit_after>//
// base64n.rs - new base64 module
//
// The Base64 Alphabet
//
//  Value Encoding  Value Encoding  Value Encoding  Value Encoding
//      0 A            17 R            34 i            51 z
//      1 B            18 S            35 j            52 0
//      2 C            19 T            36 k            53 1
//      3 D            20 U            37 l            54 2
//      4 E            21 V            38 m            55 3
//      5 F            22 W            39 n            56 4
//      6 G            23 X            40 o            57 5
//      7 H            24 Y            41 p            58 6
//      8 I            25 Z            42 q            59 7
//      9 J            26 a            43 r            60 8
//     10 K            27 b            44 s            61 9
//     11 L            28 c            45 t            62 +
//     12 M            29 d            46 u            63 /
//     13 N            30 e            47 v
//     14 O            31 f            48 w         (pad) =
//     15 P            32 g            49 x
//     16 Q            33 h            50 y
//
// The "URL and Filename safe" Base 64 Alphabet
//
// Value Encoding  Value Encoding  Value Encoding  Value Encoding
//     0 A            17 R            34 i            51 z
//     1 B            18 S            35 j            52 0
//     2 C            19 T            36 k            53 1
//     3 D            20 U            37 l            54 2
//     4 E            21 V            38 m            55 3
//     5 F            22 W            39 n            56 4
//     6 G            23 X            40 o            57 5
//     7 H            24 Y            41 p            58 6
//     8 I            25 Z            42 q            59 7
//     9 J            26 a            43 r            60 8
//    10 K            27 b            44 s            61 9
//    11 L            28 c            45 t            62 - (minus)
//    12 M            29 d            46 u            63 _ (underline)
//    13 N            30 e            47 v
//    14 O            31 f            48 w
//    15 P            32 g            49 x
//    16 Q            33 h            50 y         (pad) =
//

use std;

import vec::len;

const PAD: u8 = 61u8;

iface enc {
    fn encode(dst: [mutable u8], src: [u8]);
    fn encode_u(dst: [mutable u8], src: [u8]);
    fn encode_bytes(src: [u8]) -> [u8];
    fn encode_bytes_u(src: [u8]) -> [u8];
    fn encode_str(src: str) -> str;
    fn encode_str_u(src: str) -> str;
    // FIXME `decode` and `decode_u` should return desired length of `dst`
    fn decode(dst: [mutable u8], src: [u8]);
    fn decode_u(dst: [mutable u8], src: [u8]);
    fn decode_bytes(src: [u8]) -> [u8];
    fn decode_bytes_u(src: [u8]) -> [u8];
}

fn mk() -> enc {
    type _enc = {table: [u8], table_u: [u8],
                 decode_map: [u8], decode_map_u: [u8]};

    impl of enc for _enc {
        fn encode(dst: [mutable u8], src: [u8]) {
            b64encode(self.table, dst, src);
        }
        fn encode_u(dst: [mutable u8], src: [u8]) {
            b64encode(self.table_u, dst, src);
        }
        fn encode_bytes(src: [u8]) -> [u8] {
            let dst_length = encoded_len(len(src));
            let dst = vec::to_mut(vec::from_elem(dst_length, 0u8));
            self.encode(dst, src);
            vec::from_mut(dst)
        }
        fn encode_bytes_u(src: [u8]) -> [u8] {
            let dst_length = encoded_len(len(src));
            let dst = vec::to_mut(vec::from_elem(dst_length, 0u8));
            self.encode_u(dst, src);
            vec::from_mut(dst)
        }
        fn encode_str(src: str) -> str {
            let src = str::bytes(src);
            str::from_bytes(self.encode_bytes(src))
        }
        fn encode_str_u(src: str) -> str {
            let src = str::bytes(src);
            str::from_bytes(self.encode_bytes_u(src))
        }
        fn decode(dst: [mutable u8], src: [u8]) {
            b64decode(self.decode_map, dst, src);
        }
        fn decode_u(dst: [mutable u8], src: [u8]) {
            b64decode(self.decode_map_u, dst, src);
        }
        fn decode_bytes(src: [u8]) -> [u8] { [] }
        fn decode_bytes_u(src: [u8]) -> [u8] { [] }
    }

    let table = vec::to_mut(vec::from_elem(64u, 0u8)), i = 0u8;
    u8::range(65u8, 91u8)  { |j| table[i] = j; i += 1u8; }
    u8::range(97u8, 123u8) { |j| table[i] = j; i += 1u8; }
    u8::range(48u8, 58u8)  { |j| table[i] = j; i += 1u8; }
    table[i] = 43u8; table[i + 1u8] = 47u8;

    let table_u = table;
    table_u[i] = 45u8; table_u[i + 1u8] = 95u8;

    let decode_map = vec::to_mut(vec::from_elem(256u, 0xff_u8));
    let decode_map_u = vec::to_mut(vec::from_elem(256u, 0xff_u8));

    i = 0u8;
    while i < 64u8 {
        decode_map[table[i]] = i as u8;
        i += 1u8;
    }

    i = 0u8;
    while i < 64u8 {
        decode_map_u[table_u[i]] = i as u8;
        i += 1u8;
    }

    {table: vec::from_mut(table),
     table_u: vec::from_mut(table_u),
     decode_map: vec::from_mut(decode_map),
     decode_map_u: vec::from_mut(decode_map_u)} as enc
}

fn encoded_len(src_length: uint) -> uint {
    (src_length + 2u) / 3u * 4u
}

fn decoded_len(src_length: uint) -> uint {
    src_length / 4u * 3u
}

fn b64encode(table: [u8], dst: [mutable u8], src: [u8]) {
    if len(src) == 0u {
        ret;
    }

    let src_length = len(src);
    let dst_length = len(dst);
    let dst_curr = 0u;
    let src_curr = 0u;

    if dst_length % 4u != 0u {
        fail "dst's length should be divisible by 4";
    }

    while src_length > 0u {
        dst[dst_curr + 0u] = 0u8;
        dst[dst_curr + 1u] = 0u8;
        dst[dst_curr + 2u] = 0u8;
        dst[dst_curr + 3u] = 0u8;

        if src_length == 1u {
            dst[dst_curr + 0u] |= (src[src_curr + 0u]) >> 2u8;
            dst[dst_curr + 1u] |= (src[src_curr + 0u] << 4u8) & 0x3f_u8;
        } else if src_length == 2u {
            dst[dst_curr + 0u] |= (src[src_curr + 0u]) >> 2u8;
            dst[dst_curr + 1u] |= (src[src_curr + 0u] << 4u8) & 0x3f_u8;
            dst[dst_curr + 1u] |= (src[src_curr + 1u] >> 4u8);
            dst[dst_curr + 2u] |= (src[src_curr + 1u] << 2u8) & 0x3f_u8;
        } else {
            dst[dst_curr + 0u] |= (src[src_curr + 0u]) >> 2u8;
            dst[dst_curr + 1u] |= (src[src_curr + 0u] << 4u8) & 0x3f_u8;
            dst[dst_curr + 1u] |= (src[src_curr + 1u] >> 4u8);
            dst[dst_curr + 2u] |= (src[src_curr + 1u] << 2u8) & 0x3f_u8;
            dst[dst_curr + 2u] |= (src[src_curr + 2u] >> 6u8);
            dst[dst_curr + 3u] |= (src[src_curr + 2u]) & 0x3f_u8;
        }

        dst[dst_curr + 0u] = table[dst[dst_curr + 0u]];
        dst[dst_curr + 1u] = table[dst[dst_curr + 1u]];
        dst[dst_curr + 2u] = table[dst[dst_curr + 2u]];
        dst[dst_curr + 3u] = table[dst[dst_curr + 3u]];

        if src_length < 3u {
            dst[dst_curr + 3u] = PAD;
            if src_length < 2u {
                dst[dst_curr + 2u] = PAD;
            }
            break;
        }

        src_length -= 3u;
        src_curr += 3u;
        dst_curr += 4u;
    }
}

fn b64decode(table: [u8], dst: [mutable u8], src: [u8]) {
    // FIXME write
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_encode_bytes() {
        let src = [102u8, 111u8, 111u8, 98u8, 97u8, 114u8];
        let enc = mk();
        let res = enc.encode_bytes(src);
        assert res == [90u8, 109u8, 57u8, 118u8, 89u8, 109u8, 70u8, 121u8];
    }
    #[test]
    fn test_encode_str() {
        let src = "foobar";
        let enc = mk();
        let res = enc.encode_str(src);
        assert res == "Zm9vYmFy";
    }
    #[test]
    fn test_encode_bytes_u() {
        let src = [102u8, 111u8, 111u8, 98u8, 97u8, 63u8];
        let enc = mk();
        let res = enc.encode_bytes_u(src);
        assert res == [90u8, 109u8, 57u8, 118u8, 89u8, 109u8, 69u8, 95u8];
    }
    #[test]
    fn test_encode_str_u() {
        let src = "fooba?";
        let enc = mk();
        let res = enc.encode_str_u(src);
        assert res == "Zm9vYmE_";
    }
}
<|endoftext|>


<commit_before>//! Route match predicates
#![allow(non_snake_case)]
use std::marker::PhantomData;

use http;
use http::{header, HttpTryFrom};
use httpmessage::HttpMessage;
use httprequest::HttpRequest;
use server::message::Request;

/// Trait defines resource route predicate.
/// Predicate can modify request object. It is also possible to
/// to store extra attributes on request by using `Extensions` container,
/// Extensions container available via `HttpRequest::extensions()` method.
pub trait Predicate<S> {
    /// Check if request matches predicate
    fn check(&self, &Request, &S) -> bool;
}

/// Return predicate that matches if any of supplied predicate matches.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{pred, App, HttpResponse};
///
/// fn main() {
///     App::new().resource("/index.html", |r| {
///         r.route()
///             .filter(pred::Any(pred::Get()).or(pred::Post()))
///             .f(|r| HttpResponse::MethodNotAllowed())
///     });
/// }
/// ```
pub fn Any<S: 'static, P: Predicate<S> + 'static>(pred: P) -> AnyPredicate<S> {
    AnyPredicate(vec![Box::new(pred)])
}

/// Matches if any of supplied predicate matches.
pub struct AnyPredicate<S>(Vec<Box<Predicate<S>>>);

impl<S> AnyPredicate<S> {
    /// Add new predicate to list of predicates to check
    pub fn or<P: Predicate<S> + 'static>(mut self, pred: P) -> Self {
        self.0.push(Box::new(pred));
        self
    }
}

impl<S: 'static> Predicate<S> for AnyPredicate<S> {
    fn check(&self, req: &Request, state: &S) -> bool {
        for p in &self.0 {
            if p.check(req, state) {
                return true;
            }
        }
        false
    }
}

/// Return predicate that matches if all of supplied predicate matches.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{pred, App, HttpResponse};
///
/// fn main() {
///     App::new().resource("/index.html", |r| {
///         r.route()
///             .filter(
///                 pred::All(pred::Get())
///                     .and(pred::Header("content-type", "plain/text")),
///             )
///             .f(|_| HttpResponse::MethodNotAllowed())
///     });
/// }
/// ```
pub fn All<S: 'static, P: Predicate<S> + 'static>(pred: P) -> AllPredicate<S> {
    AllPredicate(vec![Box::new(pred)])
}

/// Matches if all of supplied predicate matches.
pub struct AllPredicate<S>(Vec<Box<Predicate<S>>>);

impl<S> AllPredicate<S> {
    /// Add new predicate to list of predicates to check
    pub fn and<P: Predicate<S> + 'static>(mut self, pred: P) -> Self {
        self.0.push(Box::new(pred));
        self
    }
}

impl<S: 'static> Predicate<S> for AllPredicate<S> {
    fn check(&self, req: &Request, state: &S) -> bool {
        for p in &self.0 {
            if !p.check(req, state) {
                return false;
            }
        }
        true
    }
}

/// Return predicate that matches if supplied predicate does not match.
pub fn Not<S: 'static, P: Predicate<S> + 'static>(pred: P) -> NotPredicate<S> {
    NotPredicate(Box::new(pred))
}

#[doc(hidden)]
pub struct NotPredicate<S>(Box<Predicate<S>>);

impl<S: 'static> Predicate<S> for NotPredicate<S> {
    fn check(&self, req: &Request, state: &S) -> bool {
        !self.0.check(req, state)
    }
}

/// Http method predicate
#[doc(hidden)]
pub struct MethodPredicate<S>(http::Method, PhantomData<S>);

impl<S: 'static> Predicate<S> for MethodPredicate<S> {
    fn check(&self, req: &Request, _: &S) -> bool {
        *req.method() == self.0
    }
}

/// Predicate to match *GET* http method
pub fn Get<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::GET, PhantomData)
}

/// Predicate to match *POST* http method
pub fn Post<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::POST, PhantomData)
}

/// Predicate to match *PUT* http method
pub fn Put<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::PUT, PhantomData)
}

/// Predicate to match *DELETE* http method
pub fn Delete<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::DELETE, PhantomData)
}

/// Predicate to match *HEAD* http method
pub fn Head<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::HEAD, PhantomData)
}

/// Predicate to match *OPTIONS* http method
pub fn Options<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::OPTIONS, PhantomData)
}

/// Predicate to match *CONNECT* http method
pub fn Connect<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::CONNECT, PhantomData)
}

/// Predicate to match *PATCH* http method
pub fn Patch<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::PATCH, PhantomData)
}

/// Predicate to match *TRACE* http method
pub fn Trace<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::TRACE, PhantomData)
}

/// Predicate to match specified http method
pub fn Method<S: 'static>(method: http::Method) -> MethodPredicate<S> {
    MethodPredicate(method, PhantomData)
}

/// Return predicate that matches if request contains specified header and
/// value.
pub fn Header<S: 'static>(
    name: &'static str, value: &'static str,
) -> HeaderPredicate<S> {
    HeaderPredicate(
        header::HeaderName::try_from(name).unwrap(),
        header::HeaderValue::from_static(value),
        PhantomData,
    )
}

#[doc(hidden)]
pub struct HeaderPredicate<S>(header::HeaderName, header::HeaderValue, PhantomData<S>);

impl<S: 'static> Predicate<S> for HeaderPredicate<S> {
    fn check(&self, req: &Request, _: &S) -> bool {
        if let Some(val) = req.headers().get(&self.0) {
            return val == self.1;
        }
        false
    }
}

/// Return predicate that matches if request contains specified Host name.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{pred, App, HttpResponse};
///
/// fn main() {
///     App::new().resource("/index.html", |r| {
///         r.route()
///             .filter(pred::Host("www.rust-lang.org"))
///             .f(|_| HttpResponse::MethodNotAllowed())
///     });
/// }
/// ```
pub fn Host<S: 'static, H: AsRef<str>>(host: H) -> HostPredicate<S> {
    HostPredicate(host.as_ref().to_string(), None, PhantomData)
}

#[doc(hidden)]
pub struct HostPredicate<S>(String, Option<String>, PhantomData<S>);

impl<S> HostPredicate<S> {
    /// Set reuest scheme to match
    pub fn scheme<H: AsRef<str>>(&mut self, scheme: H) {
        self.1 = Some(scheme.as_ref().to_string())
    }
}

impl<S: 'static> Predicate<S> for HostPredicate<S> {
    fn check(&self, req: &Request, _: &S) -> bool {
        let info = req.connection_info();
        if let Some(ref scheme) = self.1 {
            self.0 == info.host() && scheme == info.scheme()
        } else {
            self.0 == info.host()
        }
    }
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;

    use super::*;
    use http::header::{self, HeaderMap};
    use http::{Method, Uri, Version};
    use test::TestRequest;

    #[test]
    fn test_header() {
        let req = TestRequest::with_header(
            header::TRANSFER_ENCODING,
            header::HeaderValue::from_static("chunked"),
        ).finish();

        let pred = Header("transfer-encoding", "chunked");
        assert!(pred.check(&req, req.state()));

        let pred = Header("transfer-encoding", "other");
        assert!(!pred.check(&req, req.state()));

        let pred = Header("content-type", "other");
        assert!(!pred.check(&req, req.state()));
    }

    #[test]
    fn test_host() {
        let req = TestRequest::default()
            .header(
                header::HOST,
                header::HeaderValue::from_static("www.rust-lang.org"),
            )
            .finish();

        let pred = Host("www.rust-lang.org");
        assert!(pred.check(&req, req.state()));

        let pred = Host("localhost");
        assert!(!pred.check(&req, req.state()));
    }

    #[test]
    fn test_methods() {
        let req = TestRequest::default().finish();
        let req2 = TestRequest::default().method(Method::POST).finish();

        assert!(Get().check(&req, req.state()));
        assert!(!Get().check(&req2, req2.state()));
        assert!(Post().check(&req2, req2.state()));
        assert!(!Post().check(&req, req.state()));

        let r = TestRequest::default().method(Method::PUT).finish();
        assert!(Put().check(&r, r.state()));
        assert!(!Put().check(&req, req.state()));

        let r = TestRequest::default().method(Method::DELETE).finish();
        assert!(Delete().check(&r, r.state()));
        assert!(!Delete().check(&req, req.state()));

        let r = TestRequest::default().method(Method::HEAD).finish();
        assert!(Head().check(&r, r.state()));
        assert!(!Head().check(&req, req.state()));

        let r = TestRequest::default().method(Method::OPTIONS).finish();
        assert!(Options().check(&r, r.state()));
        assert!(!Options().check(&req, req.state()));

        let r = TestRequest::default().method(Method::CONNECT).finish();
        assert!(Connect().check(&r, r.state()));
        assert!(!Connect().check(&req, req.state()));

        let r = TestRequest::default().method(Method::PATCH).finish();
        assert!(Patch().check(&r, r.state()));
        assert!(!Patch().check(&req, req.state()));

        let r = TestRequest::default().method(Method::TRACE).finish();
        assert!(Trace().check(&r, r.state()));
        assert!(!Trace().check(&req, req.state()));
    }

    #[test]
    fn test_preds() {
        let r = TestRequest::default().method(Method::TRACE).finish();

        assert!(Not(Get()).check(&r, r.state()));
        assert!(!Not(Trace()).check(&r, r.state()));

        assert!(All(Trace()).and(Trace()).check(&r, r.state()));
        assert!(!All(Get()).and(Trace()).check(&r, r.state()));

        assert!(Any(Get()).or(Trace()).check(&r, r.state()));
        assert!(!Any(Get()).or(Get()).check(&r, r.state()));
    }
}
<commit_msg>plain/text -> text/plain in comment (#362)<commit_after>//! Route match predicates
#![allow(non_snake_case)]
use std::marker::PhantomData;

use http;
use http::{header, HttpTryFrom};
use httpmessage::HttpMessage;
use httprequest::HttpRequest;
use server::message::Request;

/// Trait defines resource route predicate.
/// Predicate can modify request object. It is also possible to
/// to store extra attributes on request by using `Extensions` container,
/// Extensions container available via `HttpRequest::extensions()` method.
pub trait Predicate<S> {
    /// Check if request matches predicate
    fn check(&self, &Request, &S) -> bool;
}

/// Return predicate that matches if any of supplied predicate matches.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{pred, App, HttpResponse};
///
/// fn main() {
///     App::new().resource("/index.html", |r| {
///         r.route()
///             .filter(pred::Any(pred::Get()).or(pred::Post()))
///             .f(|r| HttpResponse::MethodNotAllowed())
///     });
/// }
/// ```
pub fn Any<S: 'static, P: Predicate<S> + 'static>(pred: P) -> AnyPredicate<S> {
    AnyPredicate(vec![Box::new(pred)])
}

/// Matches if any of supplied predicate matches.
pub struct AnyPredicate<S>(Vec<Box<Predicate<S>>>);

impl<S> AnyPredicate<S> {
    /// Add new predicate to list of predicates to check
    pub fn or<P: Predicate<S> + 'static>(mut self, pred: P) -> Self {
        self.0.push(Box::new(pred));
        self
    }
}

impl<S: 'static> Predicate<S> for AnyPredicate<S> {
    fn check(&self, req: &Request, state: &S) -> bool {
        for p in &self.0 {
            if p.check(req, state) {
                return true;
            }
        }
        false
    }
}

/// Return predicate that matches if all of supplied predicate matches.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{pred, App, HttpResponse};
///
/// fn main() {
///     App::new().resource("/index.html", |r| {
///         r.route()
///             .filter(
///                 pred::All(pred::Get())
///                     .and(pred::Header("content-type", "text/plain")),
///             )
///             .f(|_| HttpResponse::MethodNotAllowed())
///     });
/// }
/// ```
pub fn All<S: 'static, P: Predicate<S> + 'static>(pred: P) -> AllPredicate<S> {
    AllPredicate(vec![Box::new(pred)])
}

/// Matches if all of supplied predicate matches.
pub struct AllPredicate<S>(Vec<Box<Predicate<S>>>);

impl<S> AllPredicate<S> {
    /// Add new predicate to list of predicates to check
    pub fn and<P: Predicate<S> + 'static>(mut self, pred: P) -> Self {
        self.0.push(Box::new(pred));
        self
    }
}

impl<S: 'static> Predicate<S> for AllPredicate<S> {
    fn check(&self, req: &Request, state: &S) -> bool {
        for p in &self.0 {
            if !p.check(req, state) {
                return false;
            }
        }
        true
    }
}

/// Return predicate that matches if supplied predicate does not match.
pub fn Not<S: 'static, P: Predicate<S> + 'static>(pred: P) -> NotPredicate<S> {
    NotPredicate(Box::new(pred))
}

#[doc(hidden)]
pub struct NotPredicate<S>(Box<Predicate<S>>);

impl<S: 'static> Predicate<S> for NotPredicate<S> {
    fn check(&self, req: &Request, state: &S) -> bool {
        !self.0.check(req, state)
    }
}

/// Http method predicate
#[doc(hidden)]
pub struct MethodPredicate<S>(http::Method, PhantomData<S>);

impl<S: 'static> Predicate<S> for MethodPredicate<S> {
    fn check(&self, req: &Request, _: &S) -> bool {
        *req.method() == self.0
    }
}

/// Predicate to match *GET* http method
pub fn Get<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::GET, PhantomData)
}

/// Predicate to match *POST* http method
pub fn Post<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::POST, PhantomData)
}

/// Predicate to match *PUT* http method
pub fn Put<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::PUT, PhantomData)
}

/// Predicate to match *DELETE* http method
pub fn Delete<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::DELETE, PhantomData)
}

/// Predicate to match *HEAD* http method
pub fn Head<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::HEAD, PhantomData)
}

/// Predicate to match *OPTIONS* http method
pub fn Options<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::OPTIONS, PhantomData)
}

/// Predicate to match *CONNECT* http method
pub fn Connect<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::CONNECT, PhantomData)
}

/// Predicate to match *PATCH* http method
pub fn Patch<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::PATCH, PhantomData)
}

/// Predicate to match *TRACE* http method
pub fn Trace<S: 'static>() -> MethodPredicate<S> {
    MethodPredicate(http::Method::TRACE, PhantomData)
}

/// Predicate to match specified http method
pub fn Method<S: 'static>(method: http::Method) -> MethodPredicate<S> {
    MethodPredicate(method, PhantomData)
}

/// Return predicate that matches if request contains specified header and
/// value.
pub fn Header<S: 'static>(
    name: &'static str,
    value: &'static str,
) -> HeaderPredicate<S> {
    HeaderPredicate(
        header::HeaderName::try_from(name).unwrap(),
        header::HeaderValue::from_static(value),
        PhantomData,
    )
}

#[doc(hidden)]
pub struct HeaderPredicate<S>(header::HeaderName, header::HeaderValue, PhantomData<S>);

impl<S: 'static> Predicate<S> for HeaderPredicate<S> {
    fn check(&self, req: &Request, _: &S) -> bool {
        if let Some(val) = req.headers().get(&self.0) {
            return val == self.1;
        }
        false
    }
}

/// Return predicate that matches if request contains specified Host name.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{pred, App, HttpResponse};
///
/// fn main() {
///     App::new().resource("/index.html", |r| {
///         r.route()
///             .filter(pred::Host("www.rust-lang.org"))
///             .f(|_| HttpResponse::MethodNotAllowed())
///     });
/// }
/// ```
pub fn Host<S: 'static, H: AsRef<str>>(host: H) -> HostPredicate<S> {
    HostPredicate(host.as_ref().to_string(), None, PhantomData)
}

#[doc(hidden)]
pub struct HostPredicate<S>(String, Option<String>, PhantomData<S>);

impl<S> HostPredicate<S> {
    /// Set reuest scheme to match
    pub fn scheme<H: AsRef<str>>(&mut self, scheme: H) {
        self.1 = Some(scheme.as_ref().to_string())
    }
}

impl<S: 'static> Predicate<S> for HostPredicate<S> {
    fn check(&self, req: &Request, _: &S) -> bool {
        let info = req.connection_info();
        if let Some(ref scheme) = self.1 {
            self.0 == info.host() && scheme == info.scheme()
        } else {
            self.0 == info.host()
        }
    }
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;

    use super::*;
    use http::header::{self, HeaderMap};
    use http::{Method, Uri, Version};
    use test::TestRequest;

    #[test]
    fn test_header() {
        let req = TestRequest::with_header(
            header::TRANSFER_ENCODING,
            header::HeaderValue::from_static("chunked"),
        ).finish();

        let pred = Header("transfer-encoding", "chunked");
        assert!(pred.check(&req, req.state()));

        let pred = Header("transfer-encoding", "other");
        assert!(!pred.check(&req, req.state()));

        let pred = Header("content-type", "other");
        assert!(!pred.check(&req, req.state()));
    }

    #[test]
    fn test_host() {
        let req = TestRequest::default()
            .header(
                header::HOST,
                header::HeaderValue::from_static("www.rust-lang.org"),
            )
            .finish();

        let pred = Host("www.rust-lang.org");
        assert!(pred.check(&req, req.state()));

        let pred = Host("localhost");
        assert!(!pred.check(&req, req.state()));
    }

    #[test]
    fn test_methods() {
        let req = TestRequest::default().finish();
        let req2 = TestRequest::default().method(Method::POST).finish();

        assert!(Get().check(&req, req.state()));
        assert!(!Get().check(&req2, req2.state()));
        assert!(Post().check(&req2, req2.state()));
        assert!(!Post().check(&req, req.state()));

        let r = TestRequest::default().method(Method::PUT).finish();
        assert!(Put().check(&r, r.state()));
        assert!(!Put().check(&req, req.state()));

        let r = TestRequest::default().method(Method::DELETE).finish();
        assert!(Delete().check(&r, r.state()));
        assert!(!Delete().check(&req, req.state()));

        let r = TestRequest::default().method(Method::HEAD).finish();
        assert!(Head().check(&r, r.state()));
        assert!(!Head().check(&req, req.state()));

        let r = TestRequest::default().method(Method::OPTIONS).finish();
        assert!(Options().check(&r, r.state()));
        assert!(!Options().check(&req, req.state()));

        let r = TestRequest::default().method(Method::CONNECT).finish();
        assert!(Connect().check(&r, r.state()));
        assert!(!Connect().check(&req, req.state()));

        let r = TestRequest::default().method(Method::PATCH).finish();
        assert!(Patch().check(&r, r.state()));
        assert!(!Patch().check(&req, req.state()));

        let r = TestRequest::default().method(Method::TRACE).finish();
        assert!(Trace().check(&r, r.state()));
        assert!(!Trace().check(&req, req.state()));
    }

    #[test]
    fn test_preds() {
        let r = TestRequest::default().method(Method::TRACE).finish();

        assert!(Not(Get()).check(&r, r.state()));
        assert!(!Not(Trace()).check(&r, r.state()));

        assert!(All(Trace()).and(Trace()).check(&r, r.state()));
        assert!(!All(Get()).and(Trace()).check(&r, r.state()));

        assert!(Any(Get()).or(Trace()).check(&r, r.state()));
        assert!(!Any(Get()).or(Get()).check(&r, r.state()));
    }
}
<|endoftext|>


<commit_before>//! Reading an OSM XML file.

use std::{fmt, io, str};
use xml::attribute::OwnedAttribute;
use xml::reader::{Error, EventReader, Result, XmlEvent};
use ::elements::{Member, Node, Osm, Relation, Way};

pub fn read_xml<R: io::Read>(source: R) -> Result<Osm> {
    let mut reader = EventReader::new(source);
    while let XmlEvent::ProcessingInstruction{..} = reader.next()? {
    }
    if expect_element(&mut reader, "osm")?.is_none() {
        panic!("Got unexpected end element event");
    }
    read_document(&mut reader)
}

fn read_document<R: io::Read>(reader: &mut EventReader<R>) -> Result<Osm> {
    let mut res = Osm::new();
    loop {
        let (name, attrs) = match reader.next()? {
            XmlEvent::EndDocument => return Ok(res),
            XmlEvent::StartElement{name, attributes, ..} => {
                (name.local_name, attributes)
            }
            _ => return Err(Error::from((&*reader, "expected element"))),
        };
        match name.as_ref() {
            "node" => { res.add_node(read_node(attrs, reader)?); },
            "way" => { res.add_way(read_way(attrs, reader)?); },
            "relation" => { res.add_relation(read_relation(attrs, reader)?); },
            _ => { }
        }
    }
}

fn read_node<R: io::Read>(attrs: Vec<OwnedAttribute>,
                          reader: &mut EventReader<R>) -> Result<Node> {
    let (mut id, mut lat, mut lon) = (None, None, None);
    for item in attrs {
        match item.name.local_name.as_ref() {
            "id" => id = Some(item.value),
            "lat" => lat = Some(item.value),
            "lon" => lon = Some(item.value),
            _ => { }
        }
    }
    let id = from_attr(id, reader, "id")?;
    let lat = from_attr(lat, reader, "lat")?;
    let lon = from_attr(lon, reader, "lon")?;
    let mut node = Node::new(id, lat, lon);
    while let Some((name, attrs)) = expect_any_element(reader)? {
        if name == "tag" {
            let (k, v) = read_tag(attrs, reader)?;
            node.insert_tag(k, v);
        }
    }
    Ok(node)
}

fn read_way<R: io::Read>(attrs: Vec<OwnedAttribute>,
                         reader: &mut EventReader<R>) -> Result<Way> {
    let mut id = None;
    for item in attrs {
        match item.name.local_name.as_ref() {
            "id" => id = Some(item.value),
            _ => { }
        }
    }
    let id = from_attr(id, reader, "id")?;
    let mut way = Way::new(id);
    while let Some((name, attrs)) = expect_any_element(reader)? {
        match name.as_ref() {
            "nd" => {
                way.push_node(read_nd(attrs, reader)?);
            }
            "tag" => {
                let (k, v) = read_tag(attrs, reader)?;
                way.insert_tag(k, v)
            }
            _ => { }
        }
    }
    Ok(way)
}

fn read_relation<R: io::Read>(attrs: Vec<OwnedAttribute>,
                              reader: &mut EventReader<R>)
                              -> Result<Relation> {
    let mut id = None;
    for item in attrs {
        match item.name.local_name.as_ref() {
            "id" => id = Some(item.value),
            _ => { }
        }
    }
    let id = from_attr(id, reader, "id")?;
    let mut relation = Relation::new(id);
    while let Some((name, attrs)) = expect_any_element(reader)? {
        match name.as_ref() {
            "member" => {
                relation.push_member(read_member(attrs, reader)?);
            }
            "tag" => {
                let (k, v) = read_tag(attrs, reader)?;
                relation.insert_tag(k, v);
            }
            _ => { }
        }
    }
    Ok(relation)
}

fn read_tag<R: io::Read>(attrs: Vec<OwnedAttribute>,
                         reader: &mut EventReader<R>)
                         -> Result<(String, String)> {
    let (mut k, mut v) = (None, None);
    for item in attrs {
        match item.name.local_name.as_ref() {
            "k" => k = Some(item.value),
            "v" => v = Some(item.value),
            _ => { }
        }
    }
    let k = from_attr(k, reader, "k")?;
    let v = from_attr(v, reader, "v")?;
    Ok((k, v))
}

fn read_nd<R: io::Read>(attrs: Vec<OwnedAttribute>,
                        reader: &mut EventReader<R>) -> Result<i64> {
    let mut id = None;
    for item in attrs {
        match item.name.local_name.as_ref() {
            "ref" => id = Some(item.value),
            _ => { }
        }
    }
    let id = from_attr(id, reader, "ref")?;
    Ok(id)
}

fn read_member<R: io::Read>(attrs: Vec<OwnedAttribute>,
                            reader: &mut EventReader<R>) -> Result<Member> {
    let (mut mtype, mut id, mut role) = (None, None, None);
    for item in attrs {
        match item.name.local_name.as_ref() {
            "type" => mtype = Some(item.value),
            "ref" => id = Some(item.value),
            "role" => role = Some(item.value),
            _ => { }
        }
    }
    let mtype = from_attr(mtype, reader, "type")?;
    let id = from_attr(id, reader, "ref")?;
    let role = from_attr(role, reader, "role")?;
    Ok(Member::new(mtype, id, role))
}

//------------ Helpers -------------------------------------------------------

fn expect_element<R: io::Read>(reader: &mut EventReader<R>, elem: &str)
                               -> Result<Option<Vec<OwnedAttribute>>> {
    match reader.next()? {
        XmlEvent::StartElement{name, attributes, ..} => {
            if name.local_name == elem {
                Ok(Some(attributes))
            }
            else {
                Err(Error::from((&*reader,
                                 format!("expected element '{}'", elem))))
            }
        }
        XmlEvent::EndElement{..} => Ok(None),
        _ => return Err(Error::from((&*reader, "expected element"))),
    }
}

fn expect_any_element<R: io::Read>(reader: &mut EventReader<R>)
                            -> Result<Option<(String, Vec<OwnedAttribute>)>> {
    match reader.next()? {
        XmlEvent::StartElement{name, attributes, ..} => {
            Ok(Some((name.local_name, attributes)))
        }
        XmlEvent::EndElement{..} => Ok(None),
        _ => return Err(Error::from((&*reader, "expected element"))),
    }
}

fn from_attr<R, T>(val: Option<String>, reader: &EventReader<R>,
                   attr: &str) -> Result<T>
            where R: io::Read, T: str::FromStr, T::Err: fmt::Display {
    match val {
        Some(val) => {
            str::FromStr::from_str(&val)
                         .map_err(|err| Error::from((&*reader,
                                                     format!("{}", err))))
        }
        None => {
            Err(Error::from((&*reader,
                             format!("missing '{}' attribute", attr))))
        }
    }
}
<commit_msg>Print event type for debugging.<commit_after>//! Reading an OSM XML file.

use std::{fmt, io, str};
use xml::attribute::OwnedAttribute;
use xml::reader::{Error, EventReader, Result, XmlEvent};
use ::elements::{Member, Node, Osm, Relation, Way};

pub fn read_xml<R: io::Read>(source: R) -> Result<Osm> {
    let mut reader = EventReader::new(source);
    while let XmlEvent::ProcessingInstruction{..} = reader.next()? {
    }
    if expect_element(&mut reader, "osm")?.is_none() {
        panic!("Got unexpected end element event");
    }
    read_document(&mut reader)
}

fn read_document<R: io::Read>(reader: &mut EventReader<R>) -> Result<Osm> {
    let mut res = Osm::new();
    loop {
        let (name, attrs) = match reader.next()? {
            XmlEvent::EndDocument => return Ok(res),
            XmlEvent::StartElement{name, attributes, ..} => {
                (name.local_name, attributes)
            }
            ev => return Err(Error::from((&*reader,
                                          format!("expected element, got {:?}",
                                                  ev)))),
        };
        match name.as_ref() {
            "node" => { res.add_node(read_node(attrs, reader)?); },
            "way" => { res.add_way(read_way(attrs, reader)?); },
            "relation" => { res.add_relation(read_relation(attrs, reader)?); },
            _ => { }
        }
    }
}

fn read_node<R: io::Read>(attrs: Vec<OwnedAttribute>,
                          reader: &mut EventReader<R>) -> Result<Node> {
    let (mut id, mut lat, mut lon) = (None, None, None);
    for item in attrs {
        match item.name.local_name.as_ref() {
            "id" => id = Some(item.value),
            "lat" => lat = Some(item.value),
            "lon" => lon = Some(item.value),
            _ => { }
        }
    }
    let id = from_attr(id, reader, "id")?;
    let lat = from_attr(lat, reader, "lat")?;
    let lon = from_attr(lon, reader, "lon")?;
    let mut node = Node::new(id, lat, lon);
    while let Some((name, attrs)) = expect_any_element(reader)? {
        if name == "tag" {
            let (k, v) = read_tag(attrs, reader)?;
            node.insert_tag(k, v);
        }
    }
    Ok(node)
}

fn read_way<R: io::Read>(attrs: Vec<OwnedAttribute>,
                         reader: &mut EventReader<R>) -> Result<Way> {
    let mut id = None;
    for item in attrs {
        match item.name.local_name.as_ref() {
            "id" => id = Some(item.value),
            _ => { }
        }
    }
    let id = from_attr(id, reader, "id")?;
    let mut way = Way::new(id);
    while let Some((name, attrs)) = expect_any_element(reader)? {
        match name.as_ref() {
            "nd" => {
                way.push_node(read_nd(attrs, reader)?);
            }
            "tag" => {
                let (k, v) = read_tag(attrs, reader)?;
                way.insert_tag(k, v)
            }
            _ => { }
        }
    }
    Ok(way)
}

fn read_relation<R: io::Read>(attrs: Vec<OwnedAttribute>,
                              reader: &mut EventReader<R>)
                              -> Result<Relation> {
    let mut id = None;
    for item in attrs {
        match item.name.local_name.as_ref() {
            "id" => id = Some(item.value),
            _ => { }
        }
    }
    let id = from_attr(id, reader, "id")?;
    let mut relation = Relation::new(id);
    while let Some((name, attrs)) = expect_any_element(reader)? {
        match name.as_ref() {
            "member" => {
                relation.push_member(read_member(attrs, reader)?);
            }
            "tag" => {
                let (k, v) = read_tag(attrs, reader)?;
                relation.insert_tag(k, v);
            }
            _ => { }
        }
    }
    Ok(relation)
}

fn read_tag<R: io::Read>(attrs: Vec<OwnedAttribute>,
                         reader: &mut EventReader<R>)
                         -> Result<(String, String)> {
    let (mut k, mut v) = (None, None);
    for item in attrs {
        match item.name.local_name.as_ref() {
            "k" => k = Some(item.value),
            "v" => v = Some(item.value),
            _ => { }
        }
    }
    let k = from_attr(k, reader, "k")?;
    let v = from_attr(v, reader, "v")?;
    Ok((k, v))
}

fn read_nd<R: io::Read>(attrs: Vec<OwnedAttribute>,
                        reader: &mut EventReader<R>) -> Result<i64> {
    let mut id = None;
    for item in attrs {
        match item.name.local_name.as_ref() {
            "ref" => id = Some(item.value),
            _ => { }
        }
    }
    let id = from_attr(id, reader, "ref")?;
    Ok(id)
}

fn read_member<R: io::Read>(attrs: Vec<OwnedAttribute>,
                            reader: &mut EventReader<R>) -> Result<Member> {
    let (mut mtype, mut id, mut role) = (None, None, None);
    for item in attrs {
        match item.name.local_name.as_ref() {
            "type" => mtype = Some(item.value),
            "ref" => id = Some(item.value),
            "role" => role = Some(item.value),
            _ => { }
        }
    }
    let mtype = from_attr(mtype, reader, "type")?;
    let id = from_attr(id, reader, "ref")?;
    let role = from_attr(role, reader, "role")?;
    Ok(Member::new(mtype, id, role))
}

//------------ Helpers -------------------------------------------------------

fn expect_element<R: io::Read>(reader: &mut EventReader<R>, elem: &str)
                               -> Result<Option<Vec<OwnedAttribute>>> {
    match reader.next()? {
        XmlEvent::StartElement{name, attributes, ..} => {
            if name.local_name == elem {
                Ok(Some(attributes))
            }
            else {
                Err(Error::from((&*reader,
                                 format!("expected element '{}'", elem))))
            }
        }
        XmlEvent::EndElement{..} => Ok(None),
        _ => return Err(Error::from((&*reader, "expected element"))),
    }
}

fn expect_any_element<R: io::Read>(reader: &mut EventReader<R>)
                            -> Result<Option<(String, Vec<OwnedAttribute>)>> {
    match reader.next()? {
        XmlEvent::StartElement{name, attributes, ..} => {
            Ok(Some((name.local_name, attributes)))
        }
        XmlEvent::EndElement{..} => Ok(None),
        _ => return Err(Error::from((&*reader, "expected element"))),
    }
}

fn from_attr<R, T>(val: Option<String>, reader: &EventReader<R>,
                   attr: &str) -> Result<T>
            where R: io::Read, T: str::FromStr, T::Err: fmt::Display {
    match val {
        Some(val) => {
            str::FromStr::from_str(&val)
                         .map_err(|err| Error::from((&*reader,
                                                     format!("{}", err))))
        }
        None => {
            Err(Error::from((&*reader,
                             format!("missing '{}' attribute", attr))))
        }
    }
}
<|endoftext|>


<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/. */

//! Rust wrappers around the raw JS apis

use libc::types::os::arch::c95::{size_t, c_uint};
use libc::uintptr_t;
use libc::c_char;
use std::cmp;
use std::rc;
use std::rt::Runtime;
use std::string;
use jsapi::*;
use jsapi::JSVersion::JSVERSION_LATEST;
use jsval::{JSVal, NullValue};
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use ERR;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = rc::Rc<rt_rsrc>;

pub struct rt_rsrc {
    pub ptr : *mut JSRuntime,
}

impl Drop for rt_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *mut JSRuntime) -> rt {
    return rc::Rc::new(rt_rsrc {
        ptr: p
    })
}

pub trait RtUtils {
    fn cx(&self) -> rc::Rc<Cx>;
}

impl RtUtils for rc::Rc<rt_rsrc> {
    fn cx(&self) -> rc::Rc<Cx> {
        unsafe {
            new_context(JS_NewContext(self.deref().ptr,
                                      default_stacksize as size_t), self.clone())
        }
    }
}

pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    pub ptr: *mut JSContext,
    pub rt: rt,
}

#[unsafe_destructor]
impl Drop for Cx {
    fn drop(&mut self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *mut JSContext, rt: rt) -> rc::Rc<Cx> {
    return rc::Rc::new(Cx {
        ptr: ptr,
        rt: rt,
    })
}

impl Cx {
    pub fn set_default_options_and_version(&self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE);
        self.set_version(JSVERSION_LATEST);
    }

    pub fn set_options(&self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    pub fn set_version(&self, v: JSVersion) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    pub fn set_logging_error_reporter(&self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportError));
        }
    }

    pub fn set_error_reporter(&self, reportfn: unsafe extern "C" fn(*mut JSContext, *const c_char, *mut JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportfn));
        }
    }

    pub fn evaluate_script(&self, glob: *mut JSObject, script: String, filename: String, line_num: uint)
                    -> Result<(),()> {
        let script_utf16: Vec<u16> = script.as_slice().utf16_units().collect();
        let filename_cstr = filename.to_c_str();
        let mut rval: JSVal = NullValue();
        debug!("Evaluating script from {:s} with content {}", filename, script);
        // SpiderMonkey does not approve of null pointers.
        let (ptr, len) = if script_utf16.len() == 0 {
            static empty: &'static [u16] = &[];
            (empty.as_ptr(), 0)
        } else {
            (script_utf16.as_ptr(), script_utf16.len() as c_uint)
        };
        assert!(ptr.is_not_null());
        unsafe {
            if ERR == JS_EvaluateUCScript(self.ptr, glob, ptr, len,
                                          filename_cstr.as_ptr(), line_num as c_uint,
                                          &mut rval) {
                debug!("...err!");
                Err(())
            } else {
                // we could return the script result but then we'd have
                // to root it and so forth and, really, who cares?
                debug!("...ok!");
                Ok(())
            }
        }
    }
}

pub unsafe extern fn reportError(_cx: *mut JSContext, msg: *const c_char, report: *mut JSErrorReport) {
    let fnptr = (*report).filename;
    let fname = if fnptr.is_not_null() {string::raw::from_buf(fnptr as *const i8 as *const u8)} else {"none".to_string()};
    let lineno = (*report).lineno;
    let msg = string::raw::from_buf(msg as *const i8 as *const u8);
    error!("Error at {:s}:{}: {:s}\n", fname, lineno, msg);
}

pub fn with_compartment<R>(cx: *mut JSContext, object: *mut JSObject, cb: || -> R) -> R {
    unsafe {
        let call = JS_EnterCrossCompartmentCall(cx, object);
        let result = cb();
        JS_LeaveCrossCompartmentCall(call);
        result
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::RtUtils;

    #[test]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.deref().set_default_options_and_version();
        cx.deref().set_logging_error_reporter();
    }

}
<commit_msg>Pass the responsibility for error reporting to the embedder.<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/. */

//! Rust wrappers around the raw JS apis

use libc::types::os::arch::c95::{size_t, c_uint};
use libc::uintptr_t;
use libc::c_char;
use std::cmp;
use std::rc;
use std::rt::Runtime;
use std::string;
use jsapi::*;
use jsapi::JSVersion::JSVERSION_LATEST;
use jsval::{JSVal, NullValue};
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use ERR;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = rc::Rc<rt_rsrc>;

pub struct rt_rsrc {
    pub ptr : *mut JSRuntime,
}

impl Drop for rt_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *mut JSRuntime) -> rt {
    return rc::Rc::new(rt_rsrc {
        ptr: p
    })
}

pub trait RtUtils {
    fn cx(&self) -> rc::Rc<Cx>;
}

impl RtUtils for rc::Rc<rt_rsrc> {
    fn cx(&self) -> rc::Rc<Cx> {
        unsafe {
            new_context(JS_NewContext(self.deref().ptr,
                                      default_stacksize as size_t), self.clone())
        }
    }
}

pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    pub ptr: *mut JSContext,
    pub rt: rt,
}

#[unsafe_destructor]
impl Drop for Cx {
    fn drop(&mut self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *mut JSContext, rt: rt) -> rc::Rc<Cx> {
    return rc::Rc::new(Cx {
        ptr: ptr,
        rt: rt,
    })
}

impl Cx {
    pub fn set_default_options_and_version(&self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE |
                         JSOPTION_DONT_REPORT_UNCAUGHT |
                         JSOPTION_AUTOJSAPI_OWNS_ERROR_REPORTING);
        self.set_version(JSVERSION_LATEST);
    }

    pub fn set_options(&self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    pub fn set_version(&self, v: JSVersion) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    pub fn set_logging_error_reporter(&self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportError));
        }
    }

    pub fn set_error_reporter(&self, reportfn: unsafe extern "C" fn(*mut JSContext, *const c_char, *mut JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportfn));
        }
    }

    pub fn evaluate_script(&self, glob: *mut JSObject, script: String, filename: String, line_num: uint)
                    -> Result<(),()> {
        let script_utf16: Vec<u16> = script.as_slice().utf16_units().collect();
        let filename_cstr = filename.to_c_str();
        let mut rval: JSVal = NullValue();
        debug!("Evaluating script from {:s} with content {}", filename, script);
        // SpiderMonkey does not approve of null pointers.
        let (ptr, len) = if script_utf16.len() == 0 {
            static empty: &'static [u16] = &[];
            (empty.as_ptr(), 0)
        } else {
            (script_utf16.as_ptr(), script_utf16.len() as c_uint)
        };
        assert!(ptr.is_not_null());
        unsafe {
            if ERR == JS_EvaluateUCScript(self.ptr, glob, ptr, len,
                                          filename_cstr.as_ptr(), line_num as c_uint,
                                          &mut rval) {
                debug!("...err!");
                Err(())
            } else {
                // we could return the script result but then we'd have
                // to root it and so forth and, really, who cares?
                debug!("...ok!");
                Ok(())
            }
        }
    }
}

pub unsafe extern fn reportError(_cx: *mut JSContext, msg: *const c_char, report: *mut JSErrorReport) {
    let fnptr = (*report).filename;
    let fname = if fnptr.is_not_null() {string::raw::from_buf(fnptr as *const i8 as *const u8)} else {"none".to_string()};
    let lineno = (*report).lineno;
    let msg = string::raw::from_buf(msg as *const i8 as *const u8);
    error!("Error at {:s}:{}: {:s}\n", fname, lineno, msg);
}

pub fn with_compartment<R>(cx: *mut JSContext, object: *mut JSObject, cb: || -> R) -> R {
    unsafe {
        let call = JS_EnterCrossCompartmentCall(cx, object);
        let result = cb();
        JS_LeaveCrossCompartmentCall(call);
        result
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::RtUtils;

    #[test]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.deref().set_default_options_and_version();
        cx.deref().set_logging_error_reporter();
    }

}
<|endoftext|>


<commit_before>use syntax::ast;
use syntax::ast::Item;
use syntax::codemap::Span;
use syntax::ptr::P;
use syntax::parse::token;
use syntax::ext::expand;
use syntax::ext::base::{ExtCtxt, SyntaxExtension};
use syntax::fold::Folder;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("simd"), SyntaxExtension::Modifier(Box::new(simd)));
}

fn simd<'a>(cx: &mut ExtCtxt<'a>, sp: Span, mi: &ast::MetaItem, orig_item: P<ast::Item>)
            -> P<ast::Item> {
    let supported = match orig_item.node {
        ast::ItemFn(_, _, _, _, ref generics, _) => !generics.is_parameterized(),
        _ => false,
    };
    if !supported {
        cx.span_err(orig_item.span, "#[simd] not supported on this item");
        return orig_item;
    }

    println!("item: {:#?}", orig_item);
    orig_item.map(|item| {
        let new_node = match item.node {
            ast::ItemFn(decl, safety, constness, abi, generics, block) => {
                println!("Function declaration:");
                for a in &decl.inputs {
                    println!("{:#?}", a);
                    println!("{:#?}", a.ty.node);
                    match a.ty.node {
                        ast::TyPath(_, ref p) => {
                            println!("path = {:#?}", p);
                            println!("segments = {:#?}", p.segments);
                        },
                        _ => {},
                    }
                }
                println!("Return type = {:#?}", decl.output);
                println!("\nFunction statements:");
                for i in &block.stmts {
                    println!("{:#?}", i);
                }
                if let Some(ref expr) = block.expr {
                    println!("Function has an expression");
                    println!("{:#?}", expr);
                    println!("node = {:#?}", expr.node);
                    match expr.node {
                        ast::ExprBinary(ref op, ref l, ref r) => {
                            println!("left = {:#?}", l.node);
                            println!("right = {:#?}", r.node);
                        },
                        _ => {},
                    }
                }
                ast::ItemFn(decl, safety, constness, abi, generics, block)
            },
            _ => unreachable!(),
        };
        ast::Item {
            node: new_node,
            .. item
        }
    })
}

<commit_msg>Print information about declarations as well<commit_after>use syntax::ast;
use syntax::ast::Item;
use syntax::codemap::Span;
use syntax::ptr::P;
use syntax::parse::token;
use syntax::ext::expand;
use syntax::ext::base::{ExtCtxt, SyntaxExtension};
use syntax::fold::Folder;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("simd"), SyntaxExtension::Modifier(Box::new(simd)));
}

fn simd<'a>(cx: &mut ExtCtxt<'a>, sp: Span, mi: &ast::MetaItem, orig_item: P<ast::Item>)
            -> P<ast::Item> {
    let supported = match orig_item.node {
        ast::ItemFn(_, _, _, _, ref generics, _) => !generics.is_parameterized(),
        _ => false,
    };
    if !supported {
        cx.span_err(orig_item.span, "#[simd] not supported on this item");
        return orig_item;
    }

    println!("item: {:#?}", orig_item);
    orig_item.map(|item| {
        let new_node = match item.node {
            ast::ItemFn(decl, safety, constness, abi, generics, block) => {
                println!("Function declaration:");
                for a in &decl.inputs {
                    println!("{:#?}", a);
                    println!("{:#?}", a.ty.node);
                    match a.ty.node {
                        ast::TyPath(_, ref p) => {
                            println!("path = {:#?}", p);
                            println!("segments = {:#?}", p.segments);
                        },
                        _ => {},
                    }
                }
                println!("Return type = {:#?}", decl.output);
                println!("\nFunction statements:");
                for i in &block.stmts {
                    println!("{:#?}", i);
                    match i.node {
                        ast::StmtDecl(ref decl, _) => {
                            match decl.node {
                                ast::DeclLocal(ref local) => {
                                    match local.ty {
                                        Some(ref ty) => println!("type {:#?}", ty),
                                        None => println!("no type"),
                                    }
                                },
                                ast::DeclItem(_) => {
                                    println!("item decl");
                                },
                            }
                        },
                        _ => println!("other decl"),
                    }
                }
                if let Some(ref expr) = block.expr {
                    println!("Function has an expression");
                    println!("{:#?}", expr);
                    println!("node = {:#?}", expr.node);
                    match expr.node {
                        ast::ExprBinary(ref op, ref l, ref r) => {
                            println!("left = {:#?}", l.node);
                            println!("right = {:#?}", r.node);
                        },
                        _ => {},
                    }
                }
                ast::ItemFn(decl, safety, constness, abi, generics, block)
            },
            _ => unreachable!(),
        };
        ast::Item {
            node: new_node,
            .. item
        }
    })
}

<|endoftext|>


<commit_before>use std::str::FromStr;
use std::time::Instant;
use std::fmt;

/// Absolute time.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Time(f64);

impl Time {
  pub fn as_f64(self) -> f64 {
    self.0
  }
}

impl fmt::Display for Time {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    self.0.fmt(f)
  }
}

/// Monotonic time.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Monotonic(Instant);

impl Monotonic {
  pub fn now() -> Self {
    Monotonic(Instant::now())
  }

  pub fn elapsed_secs(&self) -> Time {
    let dur = self.0.elapsed();
    let secs = dur.as_secs() as f64;
    let nanos = dur.subsec_nanos() as f64;

    Time(secs + nanos * 1e-9)
  }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DurationSpecError {
  MissingSecondsSuffix,
  CannotParseMinutes,
  CannotParseSeconds
}

impl fmt::Display for DurationSpecError {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      DurationSpecError::MissingSecondsSuffix => f.write_str("missing the seconds suffix"),
      DurationSpecError::CannotParseMinutes => f.write_str("cannot parse minutes"),
      DurationSpecError::CannotParseSeconds => f.write_str("cannot parse seconds"),
    }
  }
}

/// A way to specify a duration with minutes and seconds.
///
/// The string format is the following:
///
///   - `MmSs`, if you want minutes (e.g. `3m43s`).
///   - `Ss`, if you only have seconds (e.g. `23s`).
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DurationSpec {
  mins: u8,
  secs: u8
}

impl FromStr for DurationSpec {
  type Err = DurationSpecError;

  fn from_str(s: &str) -> Result<Self, Self::Err> {
    if !s.ends_with('s') {
      if s.ends_with('m') {
        // only minutes
        let mins = s.trim_end_matches('m').parse().map_err(|_| DurationSpecError::CannotParseMinutes)?;

        Ok(DurationSpec { mins, secs: 0 })
      } else {
        Err(DurationSpecError::MissingSecondsSuffix)
      }
    } else if s.contains('m') {
      // the first argument represents minutes, so let’s take them out first
      let mut iter = s.split('m');
      let mins = iter.next().and_then(|x| x.parse().ok()).ok_or(DurationSpecError::CannotParseMinutes)?;
      let secs = iter.next().and_then(|x| x.trim_end_matches('s').parse().ok()).ok_or(DurationSpecError::CannotParseSeconds)?;

      Ok(DurationSpec { mins, secs })
    } else {
      // only seconds
      let secs = s.trim_end_matches('s').parse().map_err(|_| DurationSpecError::CannotParseSeconds)?;

      Ok(DurationSpec { mins: 0, secs })
    }
  }
}

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

  #[test]
  fn parse_duraction_spec() {
    assert_eq!("1s".parse::<DurationSpec>().unwrap(), DurationSpec { mins: 0, secs: 1 });
    assert_eq!("2m".parse::<DurationSpec>().unwrap(), DurationSpec { mins: 2, secs: 0 });
    assert_eq!("3m12s".parse::<DurationSpec>().unwrap(), DurationSpec { mins: 3, secs: 12 });
    assert_eq!("3m12".parse::<DurationSpec>(), Err(DurationSpecError::MissingSecondsSuffix));
  }
}
<commit_msg>Fix typo.<commit_after>use std::str::FromStr;
use std::time::Instant;
use std::fmt;

/// Absolute time.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Time(f64);

impl Time {
  pub fn as_f64(self) -> f64 {
    self.0
  }
}

impl fmt::Display for Time {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    self.0.fmt(f)
  }
}

/// Monotonic time.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Monotonic(Instant);

impl Monotonic {
  pub fn now() -> Self {
    Monotonic(Instant::now())
  }

  pub fn elapsed_secs(&self) -> Time {
    let dur = self.0.elapsed();
    let secs = dur.as_secs() as f64;
    let nanos = dur.subsec_nanos() as f64;

    Time(secs + nanos * 1e-9)
  }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DurationSpecError {
  MissingSecondsSuffix,
  CannotParseMinutes,
  CannotParseSeconds
}

impl fmt::Display for DurationSpecError {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
    match *self {
      DurationSpecError::MissingSecondsSuffix => f.write_str("missing the seconds suffix"),
      DurationSpecError::CannotParseMinutes => f.write_str("cannot parse minutes"),
      DurationSpecError::CannotParseSeconds => f.write_str("cannot parse seconds"),
    }
  }
}

/// A way to specify a duration with minutes and seconds.
///
/// The string format is the following:
///
///   - `MmSs`, if you want minutes (e.g. `3m43s`).
///   - `Ss`, if you only have seconds (e.g. `23s`).
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DurationSpec {
  mins: u8,
  secs: u8
}

impl FromStr for DurationSpec {
  type Err = DurationSpecError;

  fn from_str(s: &str) -> Result<Self, Self::Err> {
    if !s.ends_with('s') {
      if s.ends_with('m') {
        // only minutes
        let mins = s.trim_end_matches('m').parse().map_err(|_| DurationSpecError::CannotParseMinutes)?;

        Ok(DurationSpec { mins, secs: 0 })
      } else {
        Err(DurationSpecError::MissingSecondsSuffix)
      }
    } else if s.contains('m') {
      // the first argument represents minutes, so let’s take them out first
      let mut iter = s.split('m');
      let mins = iter.next().and_then(|x| x.parse().ok()).ok_or(DurationSpecError::CannotParseMinutes)?;
      let secs = iter.next().and_then(|x| x.trim_end_matches('s').parse().ok()).ok_or(DurationSpecError::CannotParseSeconds)?;

      Ok(DurationSpec { mins, secs })
    } else {
      // only seconds
      let secs = s.trim_end_matches('s').parse().map_err(|_| DurationSpecError::CannotParseSeconds)?;

      Ok(DurationSpec { mins: 0, secs })
    }
  }
}

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

  #[test]
  fn parse_duration_spec() {
    assert_eq!("1s".parse::<DurationSpec>().unwrap(), DurationSpec { mins: 0, secs: 1 });
    assert_eq!("2m".parse::<DurationSpec>().unwrap(), DurationSpec { mins: 2, secs: 0 });
    assert_eq!("3m12s".parse::<DurationSpec>().unwrap(), DurationSpec { mins: 3, secs: 12 });
    assert_eq!("3m12".parse::<DurationSpec>(), Err(DurationSpecError::MissingSecondsSuffix));
  }
}
<|endoftext|>


<commit_before>/// unit creates a type representing a single unit.
///
/// # Examples
///
/// ```
/// #[macro_use(unit)]
/// extern crate fiz_math;
/// use std::fmt::Debug;
///
/// // GoldCoins are golden!
/// unit!(GoldCoins);
///
/// // SilverCoins are like gold coins, only worse!
/// unit!(SilverCoins);
///
/// fn collect<T: Debug>(coins: GoldCoins<T>) {
///     println!("We've collected {:?} golden coins!", coins.0);
/// }
///
/// fn main() {
///     let x = GoldCoins(5);
///     collect(x);
///
///     let y = SilverCoins(6);
///
///     // Try uncommenting the line below and see:
///     //
///     // error: mismatched types: expected `GoldCoins<_>`, found `SilverCoins<_>`"
///     //
///     //collect(y);
///
///     // add, subtract, multiply, divide:
///     assert_eq!(y + SilverCoins(4), SilverCoins(10));
///     assert_eq!(y - SilverCoins(3), SilverCoins(3));
///     assert_eq!(y * SilverCoins(3), SilverCoins(18));
///     assert_eq!(y / SilverCoins(2), SilverCoins(3));
///
///     // ordering and equality:
///     assert!(y < SilverCoins(7));
///     assert!(y > SilverCoins(5));
///     assert!(y <= SilverCoins(6));
///     assert!(y >= SilverCoins(6));
///     assert!(y == SilverCoins(6));
/// }
/// ```
///
#[macro_export]
macro_rules! unit {
    ( $ident:ident ) => {
        #[derive(Copy, Clone, Debug)]
        pub struct $ident<T>(pub T);

        unit!(impl_std_ops, $ident);
        unit!(impl_std_cmp, $ident);
        unit!(impl_num_traits, $ident);
    };

    (impl_std_ops, $ident:ident ) => {
        // addition
        impl<T: ::std::ops::Add<Output = T>> ::std::ops::Add for $ident<T> {
            type Output = Self;

            fn add(self, _rhs: Self) -> Self {
                $ident(self.0 + _rhs.0)
            }
        }

        // subtraction
        impl<T: ::std::ops::Sub<Output = T>> ::std::ops::Sub for $ident<T> {
            type Output = Self;

            fn sub(self, _rhs: Self) -> Self {
                $ident(self.0 - _rhs.0)
            }
        }

        // multiplication
        impl<T: ::std::ops::Mul<Output = T>> ::std::ops::Mul for $ident<T> {
            type Output = Self;

            fn mul(self, _rhs: Self) -> Self {
                $ident(self.0 * _rhs.0)
            }
        }

        // division
        impl<T: ::std::ops::Div<Output = T>> ::std::ops::Div for $ident<T> {
            type Output = Self;

            fn div(self, _rhs: Self) -> Self {
                $ident(self.0 / _rhs.0)
            }
        }

        // remainder
        impl<T: ::std::ops::Rem<Output = T>> ::std::ops::Rem for $ident<T> {
            type Output = Self;

            fn rem(self, rhs: Self) -> Self { $ident(self.0 % rhs.0) }
        }

        // negation
        impl<T: ::std::ops::Neg<Output = T>> ::std::ops::Neg for $ident<T> {
            type Output = Self;

            fn neg(self) -> Self::Output { $ident(-self.0) }
        }

        // not
        impl<T: ::std::ops::Not<Output = T>> ::std::ops::Not for $ident<T> {
            type Output = Self;

            fn not(self) -> Self::Output { $ident(!self.0) }
        }

        // bitwise and
        impl<T: ::std::ops::BitAnd<Output = T>> ::std::ops::BitAnd for $ident<T> {
            type Output = Self;

            fn bitand(self, rhs: Self) -> Self::Output { $ident(self.0 & rhs.0) }
        }

        // bitwise or
        impl<T: ::std::ops::BitOr<Output = T>> ::std::ops::BitOr for $ident<T> {
            type Output = Self;

            fn bitor(self, rhs: Self) -> Self::Output { $ident(self.0 | rhs.0) }
        }

        // bitwise xor
        impl<T: ::std::ops::BitXor<Output = T>> ::std::ops::BitXor for $ident<T> {
            type Output = Self;

            fn bitxor(self, rhs: Self) -> Self::Output { $ident(self.0 ^ rhs.0) }
        }

        // shift left
        impl<T: ::std::ops::Shl<usize>> ::std::ops::Shl<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shl(self, rhs: usize) -> Self::Output { $ident(self.0 << rhs) }
        }

        // shift right
        impl<T: ::std::ops::Shr<usize>> ::std::ops::Shr<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shr(self, rhs: usize) -> Self::Output { $ident(self.0 >> rhs) }
        }
    };

    (impl_std_cmp, $ident:ident ) => {
        // partial equality
        impl<T: ::std::cmp::PartialEq> ::std::cmp::PartialEq for $ident<T> {
            fn eq(&self, _rhs: &Self) -> bool {
                self.0 == _rhs.0
            }
        }

        // equality
        impl<T: ::std::cmp::Eq> ::std::cmp::Eq for $ident<T> {}

        // partial ordering
        impl<T: ::std::cmp::PartialOrd> ::std::cmp::PartialOrd for $ident<T> {
            fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
                if self.0 < other.0 {
                    Some(::std::cmp::Ordering::Less)
                } else if self.0 > other.0 {
                    Some(::std::cmp::Ordering::Greater)
                } else if self == other {
                    Some(::std::cmp::Ordering::Equal)
                } else {
                    None
                }
            }
        }

        // total ordering
        impl<T: ::std::cmp::Ord> ::std::cmp::Ord for $ident<T> {
            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                if self.0 < other.0 {
                    ::std::cmp::Ordering::Less
                } else if self.0 > other.0 {
                    ::std::cmp::Ordering::Greater
                } else {
                    ::std::cmp::Ordering::Equal
                }
            }
        }
    };

    (impl_num_traits, $ident:ident ) => {
        impl<T: $crate::num_export::traits::Zero> $crate::num_export::traits::Zero for $ident<T> {
            fn zero() -> Self { $ident(T::zero()) }
            fn is_zero(&self) -> bool { self.0.is_zero() }
        }

        impl<T: $crate::num_export::traits::One> $crate::num_export::traits::One for $ident<T> {
            fn one() -> Self { $ident(T::one()) }
        }

        impl<T: $crate::num_export::traits::Num> $crate::num_export::traits::Num for $ident<T> {
            type FromStrRadixErr = T::FromStrRadixErr;
            fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
                match T::from_str_radix(str, radix) {
                    Ok(x) => { Ok($ident(x)) }
                    Err(e) => { Err(e) }
                }
            }
        }

        impl<T: $crate::num_export::traits::ToPrimitive> $crate::num_export::traits::ToPrimitive for $ident<T> {
            fn to_i64(&self) -> Option<i64> { self.0.to_i64() }
            fn to_u64(&self) -> Option<u64> { self.0.to_u64() }
            fn to_isize(&self) -> Option<isize> { self.0.to_isize() }
            fn to_i8(&self) -> Option<i8> { self.0.to_i8() }
            fn to_i16(&self) -> Option<i16> { self.0.to_i16() }
            fn to_i32(&self) -> Option<i32> { self.0.to_i32() }
            fn to_usize(&self) -> Option<usize> { self.0.to_usize() }
            fn to_u8(&self) -> Option<u8> { self.0.to_u8() }
            fn to_u16(&self) -> Option<u16> { self.0.to_u16() }
            fn to_u32(&self) -> Option<u32> { self.0.to_u32() }
            fn to_f32(&self) -> Option<f32> { self.0.to_f32() }
            fn to_f64(&self) -> Option<f64> { self.0.to_f64() }
        }
    };
}
<commit_msg>unit! impl num::traits::NumCast<commit_after>/// unit creates a type representing a single unit.
///
/// # Examples
///
/// ```
/// #[macro_use(unit)]
/// extern crate fiz_math;
/// use std::fmt::Debug;
///
/// // GoldCoins are golden!
/// unit!(GoldCoins);
///
/// // SilverCoins are like gold coins, only worse!
/// unit!(SilverCoins);
///
/// fn collect<T: Debug>(coins: GoldCoins<T>) {
///     println!("We've collected {:?} golden coins!", coins.0);
/// }
///
/// fn main() {
///     let x = GoldCoins(5);
///     collect(x);
///
///     let y = SilverCoins(6);
///
///     // Try uncommenting the line below and see:
///     //
///     // error: mismatched types: expected `GoldCoins<_>`, found `SilverCoins<_>`"
///     //
///     //collect(y);
///
///     // add, subtract, multiply, divide:
///     assert_eq!(y + SilverCoins(4), SilverCoins(10));
///     assert_eq!(y - SilverCoins(3), SilverCoins(3));
///     assert_eq!(y * SilverCoins(3), SilverCoins(18));
///     assert_eq!(y / SilverCoins(2), SilverCoins(3));
///
///     // ordering and equality:
///     assert!(y < SilverCoins(7));
///     assert!(y > SilverCoins(5));
///     assert!(y <= SilverCoins(6));
///     assert!(y >= SilverCoins(6));
///     assert!(y == SilverCoins(6));
/// }
/// ```
///
#[macro_export]
macro_rules! unit {
    ( $ident:ident ) => {
        #[derive(Copy, Clone, Debug)]
        pub struct $ident<T>(pub T);

        unit!(impl_std_ops, $ident);
        unit!(impl_std_cmp, $ident);
        unit!(impl_num_traits, $ident);
    };

    (impl_std_ops, $ident:ident ) => {
        // addition
        impl<T: ::std::ops::Add<Output = T>> ::std::ops::Add for $ident<T> {
            type Output = Self;

            fn add(self, _rhs: Self) -> Self {
                $ident(self.0 + _rhs.0)
            }
        }

        // subtraction
        impl<T: ::std::ops::Sub<Output = T>> ::std::ops::Sub for $ident<T> {
            type Output = Self;

            fn sub(self, _rhs: Self) -> Self {
                $ident(self.0 - _rhs.0)
            }
        }

        // multiplication
        impl<T: ::std::ops::Mul<Output = T>> ::std::ops::Mul for $ident<T> {
            type Output = Self;

            fn mul(self, _rhs: Self) -> Self {
                $ident(self.0 * _rhs.0)
            }
        }

        // division
        impl<T: ::std::ops::Div<Output = T>> ::std::ops::Div for $ident<T> {
            type Output = Self;

            fn div(self, _rhs: Self) -> Self {
                $ident(self.0 / _rhs.0)
            }
        }

        // remainder
        impl<T: ::std::ops::Rem<Output = T>> ::std::ops::Rem for $ident<T> {
            type Output = Self;

            fn rem(self, rhs: Self) -> Self { $ident(self.0 % rhs.0) }
        }

        // negation
        impl<T: ::std::ops::Neg<Output = T>> ::std::ops::Neg for $ident<T> {
            type Output = Self;

            fn neg(self) -> Self::Output { $ident(-self.0) }
        }

        // not
        impl<T: ::std::ops::Not<Output = T>> ::std::ops::Not for $ident<T> {
            type Output = Self;

            fn not(self) -> Self::Output { $ident(!self.0) }
        }

        // bitwise and
        impl<T: ::std::ops::BitAnd<Output = T>> ::std::ops::BitAnd for $ident<T> {
            type Output = Self;

            fn bitand(self, rhs: Self) -> Self::Output { $ident(self.0 & rhs.0) }
        }

        // bitwise or
        impl<T: ::std::ops::BitOr<Output = T>> ::std::ops::BitOr for $ident<T> {
            type Output = Self;

            fn bitor(self, rhs: Self) -> Self::Output { $ident(self.0 | rhs.0) }
        }

        // bitwise xor
        impl<T: ::std::ops::BitXor<Output = T>> ::std::ops::BitXor for $ident<T> {
            type Output = Self;

            fn bitxor(self, rhs: Self) -> Self::Output { $ident(self.0 ^ rhs.0) }
        }

        // shift left
        impl<T: ::std::ops::Shl<usize>> ::std::ops::Shl<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shl(self, rhs: usize) -> Self::Output { $ident(self.0 << rhs) }
        }

        // shift right
        impl<T: ::std::ops::Shr<usize>> ::std::ops::Shr<usize> for $ident<T> {
            type Output = $ident<T::Output>;

            fn shr(self, rhs: usize) -> Self::Output { $ident(self.0 >> rhs) }
        }
    };

    (impl_std_cmp, $ident:ident ) => {
        // partial equality
        impl<T: ::std::cmp::PartialEq> ::std::cmp::PartialEq for $ident<T> {
            fn eq(&self, _rhs: &Self) -> bool {
                self.0 == _rhs.0
            }
        }

        // equality
        impl<T: ::std::cmp::Eq> ::std::cmp::Eq for $ident<T> {}

        // partial ordering
        impl<T: ::std::cmp::PartialOrd> ::std::cmp::PartialOrd for $ident<T> {
            fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
                if self.0 < other.0 {
                    Some(::std::cmp::Ordering::Less)
                } else if self.0 > other.0 {
                    Some(::std::cmp::Ordering::Greater)
                } else if self == other {
                    Some(::std::cmp::Ordering::Equal)
                } else {
                    None
                }
            }
        }

        // total ordering
        impl<T: ::std::cmp::Ord> ::std::cmp::Ord for $ident<T> {
            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                if self.0 < other.0 {
                    ::std::cmp::Ordering::Less
                } else if self.0 > other.0 {
                    ::std::cmp::Ordering::Greater
                } else {
                    ::std::cmp::Ordering::Equal
                }
            }
        }
    };

    (impl_num_traits, $ident:ident ) => {
        impl<T: $crate::num_export::traits::Zero> $crate::num_export::traits::Zero for $ident<T> {
            fn zero() -> Self { $ident(T::zero()) }
            fn is_zero(&self) -> bool { self.0.is_zero() }
        }

        impl<T: $crate::num_export::traits::One> $crate::num_export::traits::One for $ident<T> {
            fn one() -> Self { $ident(T::one()) }
        }

        impl<T: $crate::num_export::traits::Num> $crate::num_export::traits::Num for $ident<T> {
            type FromStrRadixErr = T::FromStrRadixErr;
            fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
                match T::from_str_radix(str, radix) {
                    Ok(x) => { Ok($ident(x)) }
                    Err(e) => { Err(e) }
                }
            }
        }

        impl<T: $crate::num_export::traits::ToPrimitive> $crate::num_export::traits::ToPrimitive for $ident<T> {
            fn to_i64(&self) -> Option<i64> { self.0.to_i64() }
            fn to_u64(&self) -> Option<u64> { self.0.to_u64() }
            fn to_isize(&self) -> Option<isize> { self.0.to_isize() }
            fn to_i8(&self) -> Option<i8> { self.0.to_i8() }
            fn to_i16(&self) -> Option<i16> { self.0.to_i16() }
            fn to_i32(&self) -> Option<i32> { self.0.to_i32() }
            fn to_usize(&self) -> Option<usize> { self.0.to_usize() }
            fn to_u8(&self) -> Option<u8> { self.0.to_u8() }
            fn to_u16(&self) -> Option<u16> { self.0.to_u16() }
            fn to_u32(&self) -> Option<u32> { self.0.to_u32() }
            fn to_f32(&self) -> Option<f32> { self.0.to_f32() }
            fn to_f64(&self) -> Option<f64> { self.0.to_f64() }
        }

        impl<T: $crate::num_export::traits::NumCast> $crate::num_export::traits::NumCast for $ident<T> {
            fn from<X: $crate::num_export::traits::ToPrimitive>(n: X) -> Option<Self> {
                match T::from(n) {
                    Some(x) => { Some($ident(x)) }
                    None => { None }
                }
            }
        }
    };
}
<|endoftext|>


<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use ffi;
use types::{gchar,gpointer};

use alloc::libc_heap::malloc_raw;
use libc;
use libc::c_char;
use std::c_str::{CString,ToCStr};
use std::mem::transmute;
use std::ptr::copy_nonoverlapping_memory;
use std::slice;
use std::str;
use std::string;

pub struct Utf8Buf {
    data: *mut gchar,
}

impl Utf8Buf {

    pub unsafe fn new(data: *mut gchar) -> Utf8Buf {
        Utf8Buf { data: data }
    }

    pub fn into_collection(self) -> Utf8Str {
        unsafe {
            let len = libc::strlen(self.data as *const c_char);
            Utf8Str { buf: transmute(self), len: len as uint }
        }
    }

    pub fn to_string(&self) -> String {
        unsafe {
            string::raw::from_buf(self.data as *const gchar as *const u8)
        }
    }

    #[inline]
    pub fn to_owned(&self) -> String { self.to_string() }

    #[inline]
    pub fn into_string(self) -> String { self.to_string() }

    #[inline]
    pub fn into_owned(self) -> String { self.to_string() }

    #[inline]
    pub fn is_empty(&self) -> bool { unsafe { *self.data == 0 } }
}

impl Drop for Utf8Buf {
    fn drop(&mut self) {
        unsafe { ffi::g_free(self.data as gpointer) }
    }
}

impl Clone for Utf8Buf {
    fn clone(&self) -> Utf8Buf {
        unsafe {
            Utf8Buf::new(ffi::g_strdup(self.data as *const gchar))
        }
    }
}

unsafe fn dup_to_c_str(source: *const c_char, len: uint) -> CString {
    let copy = malloc_raw(len + 1) as *mut c_char;
    copy_nonoverlapping_memory(copy, source, len + 1);
    CString::new(copy as *const c_char, true)
}

impl ToCStr for Utf8Buf {

    fn to_c_str(&self) -> CString {
        unsafe { self.to_c_str_unchecked() }
    }

    unsafe fn to_c_str_unchecked(&self) -> CString {
        let src = self.data as *const c_char;
        let len = libc::strlen(src) as uint;
        dup_to_c_str(src, len)
    }

    fn with_c_str<T>(&self, f: |*const i8| -> T) -> T {
        f(self.data as *const i8)
    }

    unsafe fn with_c_str_unchecked<T>(&self, f: |*const i8| -> T) -> T {
        f(self.data as *const i8)
    }
}

#[deriving(Clone)]
pub struct Utf8Str {
    buf: Utf8Buf,
    len: uint
}

impl Str for Utf8Str {
    fn as_slice<'a>(&'a self) -> &'a str {
        unsafe {
            slice::raw::buf_as_slice(
                self.buf.data as *const u8,
                self.len,
                |bytes| {
                    let s = str::raw::from_utf8(bytes);
                    transmute(s)
                })
        }
    }
}

impl StrAllocating for Utf8Str {
    fn into_string(self) -> String { self.buf.to_string() }
}

impl Collection for Utf8Str {
    fn len(&self) -> uint { return self.len }
    fn is_empty(&self) -> bool { return self.len == 0 }
}

impl ToCStr for Utf8Str {

    fn to_c_str(&self) -> CString { self.buf.to_c_str() }

    unsafe fn to_c_str_unchecked(&self) -> CString {
        dup_to_c_str(self.buf.data as *const c_char, self.len)
    }

    fn with_c_str<T>(&self, f: |*const i8| -> T) -> T {
        self.buf.with_c_str(f)
    }

    unsafe fn with_c_str_unchecked<T>(&self, f: |*const i8| -> T) -> T {
        self.buf.with_c_str_unchecked(f)
    }
}

impl PartialEq for Utf8Str {
    fn eq(&self, other: &Utf8Str) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for Utf8Str { }

impl<S: Str> Equiv<S> for Utf8Str {
    fn equiv(&self, other: &S) -> bool {
        self.as_slice() == other.as_slice()
    }
}
<commit_msg>Comment on the weird result of len() on Utf8Str<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use ffi;
use types::{gchar,gpointer};

use alloc::libc_heap::malloc_raw;
use libc;
use libc::c_char;
use std::c_str::{CString,ToCStr};
use std::mem::transmute;
use std::ptr::copy_nonoverlapping_memory;
use std::slice;
use std::str;
use std::string;

pub struct Utf8Buf {
    data: *mut gchar,
}

impl Utf8Buf {

    pub unsafe fn new(data: *mut gchar) -> Utf8Buf {
        Utf8Buf { data: data }
    }

    pub fn into_collection(self) -> Utf8Str {
        unsafe {
            let len = libc::strlen(self.data as *const c_char);
            Utf8Str { buf: transmute(self), len: len as uint }
        }
    }

    pub fn to_string(&self) -> String {
        unsafe {
            string::raw::from_buf(self.data as *const gchar as *const u8)
        }
    }

    #[inline]
    pub fn to_owned(&self) -> String { self.to_string() }

    #[inline]
    pub fn into_string(self) -> String { self.to_string() }

    #[inline]
    pub fn into_owned(self) -> String { self.to_string() }

    #[inline]
    pub fn is_empty(&self) -> bool { unsafe { *self.data == 0 } }
}

impl Drop for Utf8Buf {
    fn drop(&mut self) {
        unsafe { ffi::g_free(self.data as gpointer) }
    }
}

impl Clone for Utf8Buf {
    fn clone(&self) -> Utf8Buf {
        unsafe {
            Utf8Buf::new(ffi::g_strdup(self.data as *const gchar))
        }
    }
}

unsafe fn dup_to_c_str(source: *const c_char, len: uint) -> CString {
    let copy = malloc_raw(len + 1) as *mut c_char;
    copy_nonoverlapping_memory(copy, source, len + 1);
    CString::new(copy as *const c_char, true)
}

impl ToCStr for Utf8Buf {

    fn to_c_str(&self) -> CString {
        unsafe { self.to_c_str_unchecked() }
    }

    unsafe fn to_c_str_unchecked(&self) -> CString {
        let src = self.data as *const c_char;
        let len = libc::strlen(src) as uint;
        dup_to_c_str(src, len)
    }

    fn with_c_str<T>(&self, f: |*const i8| -> T) -> T {
        f(self.data as *const i8)
    }

    unsafe fn with_c_str_unchecked<T>(&self, f: |*const i8| -> T) -> T {
        f(self.data as *const i8)
    }
}

#[deriving(Clone)]
pub struct Utf8Str {
    buf: Utf8Buf,
    len: uint
}

impl Str for Utf8Str {
    fn as_slice<'a>(&'a self) -> &'a str {
        unsafe {
            slice::raw::buf_as_slice(
                self.buf.data as *const u8,
                self.len,
                |bytes| {
                    let s = str::raw::from_utf8(bytes);
                    transmute(s)
                })
        }
    }
}

impl StrAllocating for Utf8Str {
    fn into_string(self) -> String { self.buf.to_string() }
}

impl Collection for Utf8Str {

    // Common sense says we should return the UTF-8 length,
    // but &str returns length in bytes, so...
    fn len(&self) -> uint { return self.len }

    fn is_empty(&self) -> bool { return self.len == 0 }
}

impl ToCStr for Utf8Str {

    fn to_c_str(&self) -> CString { self.buf.to_c_str() }

    unsafe fn to_c_str_unchecked(&self) -> CString {
        dup_to_c_str(self.buf.data as *const c_char, self.len)
    }

    fn with_c_str<T>(&self, f: |*const i8| -> T) -> T {
        self.buf.with_c_str(f)
    }

    unsafe fn with_c_str_unchecked<T>(&self, f: |*const i8| -> T) -> T {
        self.buf.with_c_str_unchecked(f)
    }
}

impl PartialEq for Utf8Str {
    fn eq(&self, other: &Utf8Str) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for Utf8Str { }

impl<S: Str> Equiv<S> for Utf8Str {
    fn equiv(&self, other: &S) -> bool {
        self.as_slice() == other.as_slice()
    }
}
<|endoftext|>


<commit_before>use time::Duration;
use std::fmt::Write;
use std::fmt::{Display, Formatter, Result};

macro_rules! println_err {
    ($($arg:tt)*) => {
        {
            let res = writeln!(std::io::stderr(), $($arg)*);
            res.expect("Failed writing to stderr!");
        }
    };
}

macro_rules! expect {
    ($r:expr, $msg:tt) => {
        {
            $r.map_err(|e|{
                println_err!($msg, e.description());
                std::process::exit(1);
            }).unwrap()
        }
    };
}

pub trait PrettyPrint {
    fn pretty_print<W: Write>(&self, &mut W) -> Result;
}

impl PrettyPrint for Duration {
    fn pretty_print<W: Write>(&self, f: &mut W) -> Result {
        const NANOS_PER_MS: i64 = 1_000_000; // / any way to refer directly to time::NANOS_PER_MS?

        let nanos = self.num_nanoseconds().unwrap(); // TODO: Better error handling
        write!(f, "{} ms", (nanos as f64) / (NANOS_PER_MS as f64))
    }
}

pub struct PrettyPrinter<T: PrettyPrint>(pub T);

impl<T: PrettyPrint> Display for PrettyPrinter<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut str = String::new();
        self.0.pretty_print(&mut str).and(f.write_str(&str))
    }
}

impl<T: PrettyPrint> From<T> for PrettyPrinter<T> {
    fn from(t: T) -> Self {
        PrettyPrinter(t)
    }
}<commit_msg>fix(utils): use absolute paths in macros instead of relative<commit_after>use time::Duration;
use std::fmt::Write;
use std::fmt::{Display, Formatter, Result};

macro_rules! println_err {
    ($($arg:tt)*) => {
        {
            let res = writeln!(::std::io::stderr(), $($arg)*);
            res.expect("Failed writing to stderr!");
        }
    };
}

macro_rules! expect {
    ($r:expr, $msg:tt) => {
        {
            $r.map_err(|e|{
                println_err!($msg, e.description());
                ::std::process::exit(1);
            }).unwrap()
        }
    };
}

pub trait PrettyPrint {
    fn pretty_print<W: Write>(&self, &mut W) -> Result;
}

impl PrettyPrint for Duration {
    fn pretty_print<W: Write>(&self, f: &mut W) -> Result {
        const NANOS_PER_MS: i64 = 1_000_000;

        let nanos = self.num_nanoseconds().unwrap(); // TODO: Better error handling
        write!(f, "{} ms", (nanos as f64) / (NANOS_PER_MS as f64))
    }
}

pub struct PrettyPrinter<T: PrettyPrint>(pub T);

impl<T: PrettyPrint> Display for PrettyPrinter<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut str = String::new();
        self.0.pretty_print(&mut str).and(f.write_str(&str))
    }
}

impl<T: PrettyPrint> From<T> for PrettyPrinter<T> {
    fn from(t: T) -> Self {
        PrettyPrinter(t)
    }
}<|endoftext|>