<commit_before>use std::io::Cursor;
use std::result;

use serde::Deserialize;

use rmp_serde::Deserializer;
use rmp_serde::decode::Error;

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

#[test]
fn pass_newtype() {
    let buf = [0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Struct(u32);

    let mut de = Deserializer::new(cur);
    let actual: Struct = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Struct(42), actual);
}

#[test]
fn pass_tuple_struct() {
    let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Decoded(u32, u32);

    let mut de = Deserializer::new(cur);
    let actual: Decoded = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Decoded(42, 100500), actual);
}

#[test]
fn pass_struct() {
    let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Decoded {
        id: u32,
        value: u32
    };

    let mut de = Deserializer::new(cur);
    let actual: Decoded = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Decoded { id: 42, value: 100500 }, actual);
}

#[test]
fn pass_struct_from_map() {
    #[derive(Debug, PartialEq, Deserialize)]
    struct Struct {
        et: String,
        le: u8,
        shit: u8,
    }

    let buf = [
        0x83, // 3 (size)
        0xa2, 0x65, 0x74, // "et"
        0xa5, 0x76, 0x6f, 0x69, 0x6c, 0x61, // "voila"
        0xa2, 0x6c, 0x65, // "le"
        0x00, // 0
        0xa4, 0x73, 0x68, 0x69, 0x74, // "shit"
        0x01, // 1
    ];
    let cur = Cursor::new(&buf[..]);

    // It appears no special behavior is needed for deserializing structs encoded as maps.
    let mut de = Deserializer::new(cur);
    let actual: Struct = Deserialize::deserialize(&mut de).unwrap();
    let expected = Struct { et: "voila".into(), le: 0, shit: 1 };

    assert_eq!(expected, actual);
}

#[test]
fn pass_unit_variant() {
    // We expect enums to be endoded as [id, [...]]

    let buf = [0x92, 0x01, 0x90];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B, actual);
    assert_eq!(3, de.get_ref().position());
}

#[test]
fn pass_tuple_enum_with_arg() {
    // The encoded bytearray is: [1, [42]].
    let buf = [0x92, 0x01, 0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B(u32),
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B(42), actual);
    assert_eq!(4, de.get_ref().position())
}

#[test]
fn pass_tuple_enum_with_args() {
    // The encoded bytearray is: [1, [42, 58]].
    let buf = [0x92, 0x01, 0x92, 0x2a, 0x3a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B(u32, u32),
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B(42, 58), actual);
    assert_eq!(5, de.get_ref().position())
}

#[test]
fn fail_enum_sequence_mismatch() {
    // The encoded bytearray is: [1, 2, 100500].
    let buf = [0x93, 0x1, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum> = Deserialize::deserialize(&mut de);

    match actual.err().unwrap() {
        Error::LengthMismatch(3) => (),
        other => panic!("unexpected result: {:?}", other)
    }
}

#[test]
fn fail_enum_overflow() {
    // The encoded bytearray is: [1, [42]].
    let buf = [0x92, 0x01, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    // TODO: Rename to Enum: A, B, C, ...
    enum Enum {
        A,
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum> = Deserialize::deserialize(&mut de);

    match actual.err().unwrap() {
        Error::Syntax(..) => (),
        other => panic!("unexpected result: {:?}", other)
    }
}

#[test]
fn pass_struct_enum_with_arg() {
    // The encoded bytearray is: [1, [42]].
    let buf = [0x92, 0x01, 0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B { id: u32 },
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B { id: 42 }, actual);
    assert_eq!(4, de.get_ref().position())
}

#[test]
fn pass_newtype_variant() {
    // The encoded bytearray is: [0, [['le message']]].
    let buf = [0x92, 0x0, 0x91, 0x91, 0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Nested(String);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A(Nested),
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::A(Nested("le message".into())), actual);
    assert_eq!(buf.len() as u64, de.get_ref().position())
}

#[cfg(disabled)]  // This test doesn't actually compile anymore
#[test]
fn pass_enum_custom_policy() {
    use std::io::Read;
    use rmp_serde::decode::VariantVisitor;

    // We expect enums to be endoded as id, [...] (without wrapping tuple).

    let buf = [0x01, 0x90];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    struct CustomDeserializer<R: Read> {
        inner: Deserializer<R>,
    }

    impl<R: Read> serde::Deserializer for CustomDeserializer<R> {
        type Error = Error;

        fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value>
            where V: serde::de::Visitor
        {
            self.inner.deserialize(visitor)
        }

        fn deserialize_enum<V>(&mut self, _enum: &str, _variants: &'static [&'static str], mut visitor: V)
            -> Result<V::Value>
            where V: serde::de::EnumVisitor
        {
            visitor.visit(VariantVisitor::new(&mut self.inner))
        }

        forward_to_deserialize! {
            bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string unit seq
            seq_fixed_size bytes map tuple_struct unit_struct struct struct_field
            tuple option newtype_struct ignored_any
        }
    }

    let mut de = CustomDeserializer { inner: Deserializer::new(cur) };
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B, actual);
    assert_eq!(2, de.inner.get_ref().position());
}

#[test]
fn pass_struct_variant() {
    #[derive(Debug, PartialEq, Deserialize)]
    enum Custom {
        First { data: u32 },
        Second { data: u32 },
    }
    let out_first = vec![0x92, 0x00, 0x91, 0x2a];
    let out_second = vec![0x92, 0x01, 0x91, 0x2a];

    for (expected, out) in vec![(Custom::First{ data: 42 }, out_first), (Custom::Second { data: 42 }, out_second)] {
        let mut de = Deserializer::new(Cursor::new(&out[..]));
        let val: Custom = Deserialize::deserialize(&mut de).unwrap();
        assert_eq!(expected, val);
    }
}

#[test]
fn pass_enum_with_one_arg() {
    // The encoded bytearray is: [0, [[1, 2]]].
    let buf = [0x92, 0x0, 0x91, 0x92, 0x01, 0x02];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        V1(Vec<u32>),
        V2,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::V1(vec![1, 2]), actual);
    assert_eq!(buf.len() as u64, de.get_ref().position())
}
<commit_msg>refactor: prettifying in tests<commit_after>use std::io::Cursor;

use serde::Deserialize;

use rmp_serde::Deserializer;
use rmp_serde::decode::Error;

#[test]
fn pass_newtype() {
    let buf = [0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Struct(u32);

    let mut de = Deserializer::new(cur);
    let actual: Struct = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Struct(42), actual);
}

#[test]
fn pass_tuple_struct() {
    let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Decoded(u32, u32);

    let mut de = Deserializer::new(cur);
    let actual: Decoded = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Decoded(42, 100500), actual);
}

#[test]
fn pass_struct() {
    let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Decoded {
        id: u32,
        value: u32
    };

    let mut de = Deserializer::new(cur);
    let actual: Decoded = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Decoded { id: 42, value: 100500 }, actual);
}

#[test]
fn pass_struct_from_map() {
    #[derive(Debug, PartialEq, Deserialize)]
    struct Struct {
        et: String,
        le: u8,
        shit: u8,
    }

    let buf = [
        0x83, // 3 (size)
        0xa2, 0x65, 0x74, // "et"
        0xa5, 0x76, 0x6f, 0x69, 0x6c, 0x61, // "voila"
        0xa2, 0x6c, 0x65, // "le"
        0x00, // 0
        0xa4, 0x73, 0x68, 0x69, 0x74, // "shit"
        0x01, // 1
    ];
    let cur = Cursor::new(&buf[..]);

    // It appears no special behavior is needed for deserializing structs encoded as maps.
    let mut de = Deserializer::new(cur);
    let actual: Struct = Deserialize::deserialize(&mut de).unwrap();
    let expected = Struct { et: "voila".into(), le: 0, shit: 1 };

    assert_eq!(expected, actual);
}

#[test]
fn pass_unit_variant() {
    // We expect enums to be endoded as [id, [...]]

    let buf = [0x92, 0x01, 0x90];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B, actual);
    assert_eq!(3, de.get_ref().position());
}

#[test]
fn pass_tuple_enum_with_arg() {
    // The encoded bytearray is: [1, [42]].
    let buf = [0x92, 0x01, 0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B(u32),
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B(42), actual);
    assert_eq!(4, de.get_ref().position())
}

#[test]
fn pass_tuple_enum_with_args() {
    // The encoded bytearray is: [1, [42, 58]].
    let buf = [0x92, 0x01, 0x92, 0x2a, 0x3a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B(u32, u32),
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B(42, 58), actual);
    assert_eq!(5, de.get_ref().position())
}

#[test]
fn fail_enum_sequence_mismatch() {
    // The encoded bytearray is: [1, 2, 100500].
    let buf = [0x93, 0x1, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum, Error> = Deserialize::deserialize(&mut de);

    match actual.err().unwrap() {
        Error::LengthMismatch(3) => (),
        other => panic!("unexpected result: {:?}", other)
    }
}

#[test]
fn fail_enum_overflow() {
    // The encoded bytearray is: [1, [42]].
    let buf = [0x92, 0x01, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    // TODO: Rename to Enum: A, B, C, ...
    enum Enum {
        A,
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum, Error> = Deserialize::deserialize(&mut de);

    match actual.err().unwrap() {
        Error::Syntax(..) => (),
        other => panic!("unexpected result: {:?}", other)
    }
}

#[test]
fn pass_struct_enum_with_arg() {
    // The encoded bytearray is: [1, [42]].
    let buf = [0x92, 0x01, 0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B { id: u32 },
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B { id: 42 }, actual);
    assert_eq!(4, de.get_ref().position())
}

#[test]
fn pass_newtype_variant() {
    // The encoded bytearray is: [0, [['le message']]].
    let buf = [0x92, 0x0, 0x91, 0x91, 0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Nested(String);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A(Nested),
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::A(Nested("le message".into())), actual);
    assert_eq!(buf.len() as u64, de.get_ref().position())
}

#[cfg(disabled)]  // This test doesn't actually compile anymore
#[test]
fn pass_enum_custom_policy() {
    use std::io::Read;
    use rmp_serde::decode::VariantVisitor;

    // We expect enums to be endoded as id, [...] (without wrapping tuple).

    let buf = [0x01, 0x90];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    struct CustomDeserializer<R: Read> {
        inner: Deserializer<R>,
    }

    impl<R: Read> serde::Deserializer for CustomDeserializer<R> {
        type Error = Error;

        fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Error>
            where V: serde::de::Visitor
        {
            self.inner.deserialize(visitor)
        }

        fn deserialize_enum<V>(&mut self, _enum: &str, _variants: &'static [&'static str], mut visitor: V)
            -> Result<V::Value, Error>
            where V: serde::de::EnumVisitor
        {
            visitor.visit(VariantVisitor::new(&mut self.inner))
        }

        forward_to_deserialize! {
            bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string unit seq
            seq_fixed_size bytes map tuple_struct unit_struct struct struct_field
            tuple option newtype_struct ignored_any
        }
    }

    let mut de = CustomDeserializer { inner: Deserializer::new(cur) };
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B, actual);
    assert_eq!(2, de.inner.get_ref().position());
}

#[test]
fn pass_struct_variant() {
    #[derive(Debug, PartialEq, Deserialize)]
    enum Custom {
        First { data: u32 },
        Second { data: u32 },
    }
    let out_first = vec![0x92, 0x00, 0x91, 0x2a];
    let out_second = vec![0x92, 0x01, 0x91, 0x2a];

    for (expected, out) in vec![(Custom::First{ data: 42 }, out_first), (Custom::Second { data: 42 }, out_second)] {
        let mut de = Deserializer::new(Cursor::new(&out[..]));
        let val: Custom = Deserialize::deserialize(&mut de).unwrap();
        assert_eq!(expected, val);
    }
}

#[test]
fn pass_enum_with_one_arg() {
    // The encoded bytearray is: [0, [[1, 2]]].
    let buf = [0x92, 0x0, 0x91, 0x92, 0x01, 0x02];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        V1(Vec<u32>),
        V2,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::V1(vec![1, 2]), actual);
    assert_eq!(buf.len() as u64, de.get_ref().position())
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::collections::HashMap;
use request::Request;
use urlencoded;
use http::server::request::RequestUri;
use http::server::request::RequestUri::{Star, AbsoluteUri, AbsolutePath, Authority};
use url::UrlParser;
use plugin::{Phantom, Plugin, Pluggable};
use typemap::Key;

type QueryStore = HashMap<String, Vec<String>>;

// Plugin boilerplate
struct QueryStringParser;
impl Key for QueryStringParser { type Value = QueryStore; }

impl<'a, 'b> Plugin<Request<'a, 'b>> for QueryStringParser {
    fn eval(req: &mut Request, _: Phantom<QueryStringParser>) -> Option<QueryStore> {
        Some(parse(&req.origin.request_uri))
    }
}

pub trait QueryString {
    // FIXME: This would probably be better to return Cow<Vec<String>, [String]>
    // but ToOwned isn't implemented for that combination yet.
    fn query(&mut self, key: &str, default: &str) -> Cow<Vec<String>, Vec<String>>;
}

impl<'a, 'b> QueryString for Request<'a, 'b> {
    fn query(&mut self, key: &str, default: &str) -> Cow<Vec<String>, Vec<String>> {
        let store = self.get_ref::<QueryStringParser>()
                        .expect("Bug: QueryStringParser returned None");

        match store.get(key) {
            Some(result) => Cow::Borrowed(result),
            _ => Cow::Owned(vec![default.to_string()])
        }
    }
}

fn parse(origin: &RequestUri) -> QueryStore {
    let f = |&: query: Option<&String>| query.map(|q| urlencoded::parse(&q[]));

    let result = match *origin {
        AbsoluteUri(ref url) => f(url.query.as_ref()),
        AbsolutePath(ref s) => UrlParser::new().parse_path(&s[])
                                                // FIXME: If this fails to parse,
                                                // then it really shouldn't have
                                                // reached here.
                                               .ok()
                                               .and_then(|(_, query, _)| f(query.as_ref())),
        Star | Authority(..) => None
    };

    result.unwrap_or_else(|| HashMap::new())
}

#[test]
fn splits_and_parses_an_url() {
    use url::Url;
    let t = |&: url|{
        let store = parse(&url);
        assert_eq!(store["foo".to_string()], vec!["bar".to_string()]);
        assert_eq!(store["message".to_string()],
                        vec!["hello".to_string(), "world".to_string()]);
    };

    let raw = "http://www.foo.bar/query/test?foo=bar&message=hello&message=world";
    t(AbsoluteUri(Url::parse(raw).unwrap()));

    t(AbsolutePath("/query/test?foo=bar&message=hello&message=world".to_string()));

    assert_eq!(parse(&Star), HashMap::new());

    let store = parse(&Authority("host.com".to_string()));
    assert_eq!(store, HashMap::new());
}
<commit_msg>fix(query_string): Update to work with latest rust-plugin.<commit_after>use std::borrow::Cow;
use std::collections::HashMap;
use request::Request;
use urlencoded;
use http::server::request::RequestUri;
use http::server::request::RequestUri::{Star, AbsoluteUri, AbsolutePath, Authority};
use url::UrlParser;
use plugin::{Plugin, Pluggable};
use typemap::Key;

type QueryStore = HashMap<String, Vec<String>>;

// Plugin boilerplate
struct QueryStringParser;
impl Key for QueryStringParser { type Value = QueryStore; }

impl<'a, 'b> Plugin<Request<'a, 'b>> for QueryStringParser {
    type Error = ();

    fn eval(req: &mut Request) -> Result<QueryStore, ()> {
        Ok(parse(&req.origin.request_uri))
    }
}

pub trait QueryString {
    // FIXME: This would probably be better to return Cow<Vec<String>, [String]>
    // but ToOwned isn't implemented for that combination yet.
    fn query(&mut self, key: &str, default: &str) -> Cow<Vec<String>, Vec<String>>;
}

impl<'a, 'b> QueryString for Request<'a, 'b> {
    fn query(&mut self, key: &str, default: &str) -> Cow<Vec<String>, Vec<String>> {
        let store = self.get_ref::<QueryStringParser>()
                        .ok()
                        .expect("Bug: QueryStringParser returned None");

        match store.get(key) {
            Some(result) => Cow::Borrowed(result),
            _ => Cow::Owned(vec![default.to_string()])
        }
    }
}

fn parse(origin: &RequestUri) -> QueryStore {
    let f = |&: query: Option<&String>| query.map(|q| urlencoded::parse(&q[]));

    let result = match *origin {
        AbsoluteUri(ref url) => f(url.query.as_ref()),
        AbsolutePath(ref s) => UrlParser::new().parse_path(&s[])
                                                // FIXME: If this fails to parse,
                                                // then it really shouldn't have
                                                // reached here.
                                               .ok()
                                               .and_then(|(_, query, _)| f(query.as_ref())),
        Star | Authority(..) => None
    };

    result.unwrap_or_else(|| HashMap::new())
}

#[test]
fn splits_and_parses_an_url() {
    use url::Url;
    let t = |&: url|{
        let store = parse(&url);
        assert_eq!(store["foo".to_string()], vec!["bar".to_string()]);
        assert_eq!(store["message".to_string()],
                        vec!["hello".to_string(), "world".to_string()]);
    };

    let raw = "http://www.foo.bar/query/test?foo=bar&message=hello&message=world";
    t(AbsoluteUri(Url::parse(raw).unwrap()));

    t(AbsolutePath("/query/test?foo=bar&message=hello&message=world".to_string()));

    assert_eq!(parse(&Star), HashMap::new());

    let store = parse(&Authority("host.com".to_string()));
    assert_eq!(store, HashMap::new());
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc::hir::*;
use utils::{is_range_expression, match_var, span_lint_and_sugg};

/// **What it does:** Checks for fields in struct literals where shorthands
/// could be used.
///
/// **Why is this bad?** If the field and variable names are the same,
/// the field name is redundant.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let bar: u8 = 123;
///
/// struct Foo {
///     bar: u8,
/// }
///
/// let foo = Foo{ bar: bar }
/// ```
declare_lint! {
    pub REDUNDANT_FIELD_NAMES,
    Warn,
    "checks for fields in struct literals where shorthands could be used"
}

pub struct RedundantFieldNames;

impl LintPass for RedundantFieldNames {
    fn get_lints(&self) -> LintArray {
        lint_array!(REDUNDANT_FIELD_NAMES)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if let ExprStruct(ref path, ref fields, _) = expr.node {
            for field in fields {
                let name = field.name.node;

                // Do not care about range expressions.
                // They could have redundant field name when desugared to structs.
                // e.g. `start..end` is desugared to `Range { start: start, end: end }`
                if is_range_expression(expr.span) {
                    continue;
                }

                if match_var(&field.expr, name) && !field.is_shorthand {
                    span_lint_and_sugg (
                        cx,
                        REDUNDANT_FIELD_NAMES,
                        field.span,
                        "redundant field names in struct initialization",
                        "replace it with",
                        name.to_string()
                    );
                }
            }
        }
    }
}
<commit_msg>Unused variable is left<commit_after>use rustc::lint::*;
use rustc::hir::*;
use utils::{is_range_expression, match_var, span_lint_and_sugg};

/// **What it does:** Checks for fields in struct literals where shorthands
/// could be used.
///
/// **Why is this bad?** If the field and variable names are the same,
/// the field name is redundant.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let bar: u8 = 123;
///
/// struct Foo {
///     bar: u8,
/// }
///
/// let foo = Foo{ bar: bar }
/// ```
declare_lint! {
    pub REDUNDANT_FIELD_NAMES,
    Warn,
    "checks for fields in struct literals where shorthands could be used"
}

pub struct RedundantFieldNames;

impl LintPass for RedundantFieldNames {
    fn get_lints(&self) -> LintArray {
        lint_array!(REDUNDANT_FIELD_NAMES)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantFieldNames {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if let ExprStruct(_, ref fields, _) = expr.node {
            for field in fields {
                let name = field.name.node;

                // Do not care about range expressions.
                // They could have redundant field name when desugared to structs.
                // e.g. `start..end` is desugared to `Range { start: start, end: end }`
                if is_range_expression(expr.span) {
                    continue;
                }

                if match_var(&field.expr, name) && !field.is_shorthand {
                    span_lint_and_sugg (
                        cx,
                        REDUNDANT_FIELD_NAMES,
                        field.span,
                        "redundant field names in struct initialization",
                        "replace it with",
                        name.to_string()
                    );
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Rules to update the codebase using Rerast

/// Converts try!() to ?
fn try_to_question_mark<T, E, X: From<E>>(r: Result<T, E>) -> Result<T, X> {
    replace!(try!(r) => r?);
    unreachable!()
}

fn trim_left_to_start(s: &str) {
    replace!(s.trim_left() => s.trim_start());
    replace!(s.trim_right() => s.trim_end());
}

fn trim_left_matches_to_start<P: FnMut(char) -> bool>(s: &str, inner: P) {
    replace!(s.trim_left_matches(inner) => s.trim_start_matches(inner));
    replace!(s.trim_right_matches(inner) => s.trim_end_matches(inner));
}

<commit_msg>rustfmt rewrite_rules.rs<commit_after>//! Rules to update the codebase using Rerast

/// Converts try!() to ?
fn try_to_question_mark<T, E, X: From<E>>(r: Result<T, E>) -> Result<T, X> {
    replace!(try!(r) => r?);
    unreachable!()
}

fn trim_left_to_start(s: &str) {
    replace!(s.trim_left() => s.trim_start());
    replace!(s.trim_right() => s.trim_end());
}

fn trim_left_matches_to_start<P: FnMut(char) -> bool>(s: &str, inner: P) {
    replace!(s.trim_left_matches(inner) => s.trim_start_matches(inner));
    replace!(s.trim_right_matches(inner) => s.trim_end_matches(inner));
}
<|endoftext|>


<commit_before>use sdl::{pixels, keycode};
use sdl::rect::Point;
use std::default::Default;

use game::entity::{Entity,Asteroid};
use game::location::Location;
use game::Renderer;

static TURN_SPEED: f32 = 0.001;
static ACCELERATION: f32 = 0.1;

pub struct Loop {
    renderer: Renderer,
    state: State,
}

impl Loop {
    pub fn new(renderer: Renderer) -> Loop {
        let output_size = renderer.get_output_size().unwrap();
        Loop {
            renderer: renderer,
            state: State::new(output_size)
        }
    }

    pub fn handlekey(&mut self, keyDown: bool, key: keycode::KeyCode) {
        // I'm feeling a bit iffy about this. Ideally, no dummy variable
        // should be needed.
        let mut dummy = false;
        let keys = &mut self.state.keys;
        let oldkeys = *keys;
        *match key {
            keycode::UpKey => &mut keys.up,
            keycode::DownKey => &mut keys.down,
            keycode::LeftKey => &mut keys.left,
            keycode::RightKey => &mut keys.right,
            keycode::SpaceKey => &mut keys.space,
            _ => &mut dummy // Ignore any other keys
        } = keyDown;
        if *keys != oldkeys {
            println!("{}", *keys);
        }
    }

    pub fn update(&mut self) {
        {
            let keys = self.state.keys;
            let player = &mut self.state.player1;
            if keys.up { player.accelerate() }
            if keys.down { player.decelerate() }
            if keys.left { player.turn_left() }
            if keys.right { player.turn_right() }
        }
        self.state.player1.update();
        for entity in self.state.entities.iter() {
            match entity.update(self.state.entities.as_slice(), &mut self.state.delete_list, &mut self.state.add_list) {
                Some(e) => self.state.updated_entities.push(e),
                None => {}
            }
        }
        ::std::mem::swap(&mut self.state.entities, &mut self.state.updated_entities);
        self.state.updated_entities.truncate(0);
        self.draw();
    }

    pub fn draw(&self) {
        let renderer = &self.renderer;
        renderer.set_draw_color(pixels::RGB(0, 0, 0)).unwrap();
        renderer.clear().unwrap();
        self.state.player1.draw(renderer);
        let screen_centre = self.state.player1.position();
        for entity in self.state.entities.iter() {
            entity.draw(renderer, self.state.output_size, screen_centre);
        }
        renderer.present();
    }
}

struct State {
    keys: KeyState,
    player1: PlayerShip,
    entities: Vec<Entity>,
    updated_entities: Vec<Entity>,
    delete_list: Vec<uint>,
    add_list: Vec<Entity>,
    output_size: (int, int),
}

impl State {
    fn new(output_size: (int, int)) -> State {
        State {
            keys: Default::default(),
            player1: PlayerShip::new(output_size),
            entities: vec![Asteroid.new_entity(Location::new(0.1, 0.1).unwrap(), 4.0)],
            updated_entities: vec![],
            delete_list: vec![],
            add_list: vec![],
            output_size: output_size,
        }
    }
}

#[deriving(Default, PartialEq, Eq, Show)]
struct KeyState {
    down: bool,
    left: bool,
    right: bool,
    up: bool,
    space: bool,
}

// For smoother movement, everything is stored to 64th of a pixel accuracy
struct PlayerShip {
    pos: Point,
    vel: Point,
    angle: f32, // Zero points upwards.
    shape: Vec<(f32,f32)>,
    midpoint: Point,
}

impl PlayerShip {
    fn new((xmax, ymax): (int, int)) -> PlayerShip {
        let midpoint = {
            Point::new((xmax/2) as i32,(ymax/2) as i32)
        };

        let mut shape = Vec::new();
        shape.push_all([(0.0,-10.0),(-5.0,10.0),(0.0,3.0),(5.0,10.0),(0.0,-10.0)]);

        PlayerShip {
            pos: Point::new(0, 0),
            vel: Point::new(0, 0),
            angle: 0.0,
            shape: shape,
            midpoint: midpoint
        }
    }

    fn accelerate(&mut self) {
    }
    fn decelerate(&mut self) {
    }
    fn turn_left(&mut self) {
        self.angle = self.angle + TURN_SPEED;
    }
    fn turn_right(&mut self) {
        self.angle = self.angle - TURN_SPEED;
    }

    fn update(&mut self) {
    }

    fn draw(&self, renderer: &Renderer) {
        let rotated_shape = self.shape
            .iter()
            .map(|&point| rotate(point, self.angle))
            .map(|(x,y)| translate(Point::new(x as i32, y as i32),self.midpoint))
            .collect::<Vec<Point>>();
        renderer.set_draw_color(pixels::RGB(255, 255, 255)).unwrap();
        renderer.draw_lines(rotated_shape.as_slice());
    }

    fn position(&self) -> Point {
        self.pos
    }
}

fn rotate((x,y): (f32,f32), angle: f32) -> (f32,f32) {
    (x * angle.cos() + y * angle.sin(), - x * angle.sin() + y * angle.cos())
}

fn translate(point: Point, by: Point) -> Point {
    Point::new(point.x + by.x, point.y + by.y)
}
<commit_msg>Remove unnecessary debugging code.<commit_after>use sdl::{pixels, keycode};
use sdl::rect::Point;
use std::default::Default;

use game::entity::{Entity,Asteroid};
use game::location::Location;
use game::Renderer;

static TURN_SPEED: f32 = 0.001;
static ACCELERATION: f32 = 0.1;

pub struct Loop {
    renderer: Renderer,
    state: State,
}

impl Loop {
    pub fn new(renderer: Renderer) -> Loop {
        let output_size = renderer.get_output_size().unwrap();
        Loop {
            renderer: renderer,
            state: State::new(output_size)
        }
    }

    pub fn handlekey(&mut self, keyDown: bool, key: keycode::KeyCode) {
        // I'm feeling a bit iffy about this. Ideally, no dummy variable
        // should be needed.
        let mut dummy = false;
        let keys = &mut self.state.keys;
        *match key {
            keycode::UpKey => &mut keys.up,
            keycode::DownKey => &mut keys.down,
            keycode::LeftKey => &mut keys.left,
            keycode::RightKey => &mut keys.right,
            keycode::SpaceKey => &mut keys.space,
            _ => &mut dummy // Ignore any other keys
        } = keyDown;
    }

    pub fn update(&mut self) {
        {
            let keys = self.state.keys;
            let player = &mut self.state.player1;
            if keys.up { player.accelerate() }
            if keys.down { player.decelerate() }
            if keys.left { player.turn_left() }
            if keys.right { player.turn_right() }
        }
        self.state.player1.update();
        for entity in self.state.entities.iter() {
            match entity.update(self.state.entities.as_slice(), &mut self.state.delete_list, &mut self.state.add_list) {
                Some(e) => self.state.updated_entities.push(e),
                None => {}
            }
        }
        ::std::mem::swap(&mut self.state.entities, &mut self.state.updated_entities);
        self.state.updated_entities.truncate(0);
        self.draw();
    }

    pub fn draw(&self) {
        let renderer = &self.renderer;
        renderer.set_draw_color(pixels::RGB(0, 0, 0)).unwrap();
        renderer.clear().unwrap();
        self.state.player1.draw(renderer);
        let screen_centre = self.state.player1.position();
        for entity in self.state.entities.iter() {
            entity.draw(renderer, self.state.output_size, screen_centre);
        }
        renderer.present();
    }
}

struct State {
    keys: KeyState,
    player1: PlayerShip,
    entities: Vec<Entity>,
    updated_entities: Vec<Entity>,
    delete_list: Vec<uint>,
    add_list: Vec<Entity>,
    output_size: (int, int),
}

impl State {
    fn new(output_size: (int, int)) -> State {
        State {
            keys: Default::default(),
            player1: PlayerShip::new(output_size),
            entities: vec![Asteroid.new_entity(Location::new(0.1, 0.1).unwrap(), 4.0)],
            updated_entities: vec![],
            delete_list: vec![],
            add_list: vec![],
            output_size: output_size,
        }
    }
}

#[deriving(Default, PartialEq, Eq, Show)]
struct KeyState {
    down: bool,
    left: bool,
    right: bool,
    up: bool,
    space: bool,
}

// For smoother movement, everything is stored to 64th of a pixel accuracy
struct PlayerShip {
    pos: Point,
    vel: Point,
    angle: f32, // Zero points upwards.
    shape: Vec<(f32,f32)>,
    midpoint: Point,
}

impl PlayerShip {
    fn new((xmax, ymax): (int, int)) -> PlayerShip {
        let midpoint = {
            Point::new((xmax/2) as i32,(ymax/2) as i32)
        };

        let mut shape = Vec::new();
        shape.push_all([(0.0,-10.0),(-5.0,10.0),(0.0,3.0),(5.0,10.0),(0.0,-10.0)]);

        PlayerShip {
            pos: Point::new(0, 0),
            vel: Point::new(0, 0),
            angle: 0.0,
            shape: shape,
            midpoint: midpoint
        }
    }

    fn accelerate(&mut self) {
    }
    fn decelerate(&mut self) {
    }
    fn turn_left(&mut self) {
        self.angle = self.angle + TURN_SPEED;
    }
    fn turn_right(&mut self) {
        self.angle = self.angle - TURN_SPEED;
    }

    fn update(&mut self) {
    }

    fn draw(&self, renderer: &Renderer) {
        let rotated_shape = self.shape
            .iter()
            .map(|&point| rotate(point, self.angle))
            .map(|(x,y)| translate(Point::new(x as i32, y as i32),self.midpoint))
            .collect::<Vec<Point>>();
        renderer.set_draw_color(pixels::RGB(255, 255, 255)).unwrap();
        renderer.draw_lines(rotated_shape.as_slice());
    }

    fn position(&self) -> Point {
        self.pos
    }
}

fn rotate((x,y): (f32,f32), angle: f32) -> (f32,f32) {
    (x * angle.cos() + y * angle.sin(), - x * angle.sin() + y * angle.cos())
}

fn translate(point: Point, by: Point) -> Point {
    Point::new(point.x + by.x, point.y + by.y)
}
<|endoftext|>


<commit_before>use crate::index::btree::level::*;
use crate::index::btree::*;
use crate::index::trees::*;
use crate::ram::types::*;
use crate::ram::schema::{Field, Schema};
use crate::server;
use crate::client::AsyncClient;
use crate::ram::cell::Cell;
use std::{mem, ptr};
use std::sync::Arc;
use futures::stream::futures_unordered::FuturesUnordered;

pub const LSM_TREE_SCHEMA_NAME: &'static str = "NEB_LSM_TREE";
pub const LSM_TREE_LEVELS_NAME: &'static str = "levels";

lazy_static! {
    pub static ref LSM_TREE_SCHEMA_ID: u32 = key_hash(LSM_TREE_SCHEMA_NAME) as u32;
    pub static ref LSM_TREE_LEVELS_HASH: u64 = key_hash(LSM_TREE_LEVELS_NAME);
    pub static ref LSM_TREE_SCHEMA: Schema = lsm_treee_schema();
}

pub struct LSMTree {
    trees: [Box<dyn LevelTree>; NUM_LEVELS]
}

impl LSMTree {
    pub async fn create(neb: &Arc<server::NebServer>, neb_client: &Arc<AsyncClient>) -> Self {
        let trees: [Box<dyn LevelTree>; NUM_LEVELS];
        let tree_m = LevelMTree::new();
        let tree_1 = Level1Tree::new();
        let tree_2 = Level2Tree::new();
        let tree_3 = Level3Tree::new();
        let tree_4 = Level4Tree::new();
        tree_m.persist_root(neb).await;
        tree_1.persist_root(neb).await;
        tree_2.persist_root(neb).await;
        tree_3.persist_root(neb).await;
        tree_4.persist_root(neb).await;
        let level_ids = vec![
            tree_m.head_id(),
            tree_1.head_id(),
            tree_2.head_id(),
            tree_3.head_id(),
            tree_4.head_id()
        ];
        let mut cell_map = Map::new();
        cell_map.insert_key_id(*LSM_TREE_LEVELS_HASH, Value::Array(level_ids.iter().map(|id| id.value()).collect()));
        let lsm_tree_cell = Cell::new(&*LSM_TREE_SCHEMA, Value::Map(cell_map)).unwrap();
        neb_client.write_cell(lsm_tree_cell).await.unwrap().unwrap();
        trees = [box tree_m, box tree_1, box tree_2, box tree_3, box tree_4];
        Self {
            trees
        }
    }

}

fn lsm_treee_schema() -> Schema {
    Schema {
        id: *LSM_TREE_SCHEMA_ID,
        name: String::from(LSM_TREE_SCHEMA_NAME),
        key_field: None,
        str_key_field: None,
        is_dynamic: false,
        fields: Field::new(
            "*",
            0,
            false,
            false,
            Some(vec![
                Field::new(
                    LSM_TREE_LEVELS_NAME,
                    type_id_of(Type::Id),
                    false,
                    true,
                    None,
                    vec![],
                ),
            ]),
            vec![],
        ),
    }
}

impl_btree_level!(LEVEL_M);
type LevelMTreeKeySlice = [EntryKey; LEVEL_M];
type LevelMTreePtrSlice = [NodeCellRef; LEVEL_M + 1];
type LevelMTree = BPlusTree<LevelMTreeKeySlice, LevelMTreePtrSlice>;

impl_btree_level!(LEVEL_1);
type Level1TreeKeySlice = [EntryKey; LEVEL_1];
type Level1TreePtrSlice = [NodeCellRef; LEVEL_1 + 1];
type Level1Tree = BPlusTree<Level1TreeKeySlice, Level1TreePtrSlice>;

impl_btree_level!(LEVEL_2);
type Level2TreeKeySlice = [EntryKey; LEVEL_2];
type Level2TreePtrSlice = [NodeCellRef; LEVEL_2 + 1];
type Level2Tree = BPlusTree<Level2TreeKeySlice, Level2TreePtrSlice>;

impl_btree_level!(LEVEL_3);
type Level3TreeKeySlice = [EntryKey; LEVEL_3];
type Level3TreePtrSlice = [NodeCellRef; LEVEL_3 + 1];
type Level3Tree = BPlusTree<Level3TreeKeySlice, Level3TreePtrSlice>;

impl_btree_level!(LEVEL_4);
type Level4TreeKeySlice = [EntryKey; LEVEL_4];
type Level4TreePtrSlice = [NodeCellRef; LEVEL_4 + 1];
type Level4Tree = BPlusTree<Level4TreeKeySlice, Level4TreePtrSlice>;<commit_msg>LSM tree insertion, delete abd recovery<commit_after>// A machine-local concurrent LSM tree based on B-tree implementation

use crate::index::btree::level::*;
use crate::index::btree::*;
use crate::index::trees::*;
use crate::ram::types::*;
use crate::ram::schema::{Field, Schema};
use crate::server;
use crate::client::AsyncClient;
use crate::ram::cell::Cell;
use std::{mem, ptr};
use std::sync::Arc;

pub const LSM_TREE_SCHEMA_NAME: &'static str = "NEB_LSM_TREE";
pub const LSM_TREE_LEVELS_NAME: &'static str = "levels";

lazy_static! {
    pub static ref LSM_TREE_SCHEMA_ID: u32 = key_hash(LSM_TREE_SCHEMA_NAME) as u32;
    pub static ref LSM_TREE_LEVELS_HASH: u64 = key_hash(LSM_TREE_LEVELS_NAME);
    pub static ref LSM_TREE_SCHEMA: Schema = lsm_treee_schema();
}

pub struct LSMTree {
    trees: [Box<dyn LevelTree>; NUM_LEVELS]
}

impl LSMTree {
    pub async fn create(neb: &Arc<server::NebServer>, neb_client: &Arc<AsyncClient>) -> Self {
        let tree_m = LevelMTree::new();
        let tree_1 = Level1Tree::new();
        let tree_2 = Level2Tree::new();
        let tree_3 = Level3Tree::new();
        let tree_4 = Level4Tree::new();
        tree_m.persist_root(neb).await;
        tree_1.persist_root(neb).await;
        tree_2.persist_root(neb).await;
        tree_3.persist_root(neb).await;
        tree_4.persist_root(neb).await;
        let level_ids = vec![
            tree_m.head_id(),
            tree_1.head_id(),
            tree_2.head_id(),
            tree_3.head_id(),
            tree_4.head_id()
        ];
        let mut cell_map = Map::new();
        cell_map.insert_key_id(*LSM_TREE_LEVELS_HASH, Value::Array(level_ids.iter().map(|id| id.value()).collect()));
        let lsm_tree_cell = Cell::new(&*LSM_TREE_SCHEMA, Value::Map(cell_map)).unwrap();
        neb_client.write_cell(lsm_tree_cell).await.unwrap().unwrap();
        Self {
            trees: [box tree_m, box tree_1, box tree_2, box tree_3, box tree_4]
        }
    }

    pub async fn recover(neb_client: &Arc<AsyncClient>, lsm_tree_id: Id) -> Self {
        let cell = neb_client.read_cell(lsm_tree_id).await.unwrap().unwrap();
        let trees = &cell.data[*LSM_TREE_LEVELS_HASH];
        let trees_m_val = &trees[0usize];
        let trees_1_val = &trees[1usize];
        let trees_2_val = &trees[2usize];
        let trees_3_val = &trees[3usize];
        let trees_4_val = &trees[4usize];

        let tree_m = LevelMTree::from_head_id(trees_m_val.Id().unwrap(), neb_client).await;
        let tree_1 = Level1Tree::from_head_id(trees_1_val.Id().unwrap(), neb_client).await;
        let tree_2 = Level2Tree::from_head_id(trees_2_val.Id().unwrap(), neb_client).await;
        let tree_3 = Level3Tree::from_head_id(trees_3_val.Id().unwrap(), neb_client).await;
        let tree_4 = Level4Tree::from_head_id(trees_4_val.Id().unwrap(), neb_client).await;

        Self {
            trees: [box tree_m, box tree_1, box tree_2, box tree_3, box tree_4]
        }
    }

    pub fn insert(&self, entry: &EntryKey) -> bool {
        self.trees[0].insert_into(entry)
    }

    pub fn delete(&self, entry: &EntryKey) -> bool {
        for tree in &self.trees {
            if tree.mark_key_deleted(entry) {
                return true;
            }
        }
        false
    }

}
fn lsm_treee_schema() -> Schema {
    Schema {
        id: *LSM_TREE_SCHEMA_ID,
        name: String::from(LSM_TREE_SCHEMA_NAME),
        key_field: None,
        str_key_field: None,
        is_dynamic: false,
        fields: Field::new(
            "*",
            0,
            false,
            false,
            Some(vec![
                Field::new(
                    LSM_TREE_LEVELS_NAME,
                    type_id_of(Type::Id),
                    false,
                    true,
                    None,
                    vec![],
                ),
            ]),
            vec![],
        ),
    }
}

impl_btree_level!(LEVEL_M);
type LevelMTreeKeySlice = [EntryKey; LEVEL_M];
type LevelMTreePtrSlice = [NodeCellRef; LEVEL_M + 1];
type LevelMTree = BPlusTree<LevelMTreeKeySlice, LevelMTreePtrSlice>;

impl_btree_level!(LEVEL_1);
type Level1TreeKeySlice = [EntryKey; LEVEL_1];
type Level1TreePtrSlice = [NodeCellRef; LEVEL_1 + 1];
type Level1Tree = BPlusTree<Level1TreeKeySlice, Level1TreePtrSlice>;

impl_btree_level!(LEVEL_2);
type Level2TreeKeySlice = [EntryKey; LEVEL_2];
type Level2TreePtrSlice = [NodeCellRef; LEVEL_2 + 1];
type Level2Tree = BPlusTree<Level2TreeKeySlice, Level2TreePtrSlice>;

impl_btree_level!(LEVEL_3);
type Level3TreeKeySlice = [EntryKey; LEVEL_3];
type Level3TreePtrSlice = [NodeCellRef; LEVEL_3 + 1];
type Level3Tree = BPlusTree<Level3TreeKeySlice, Level3TreePtrSlice>;

impl_btree_level!(LEVEL_4);
type Level4TreeKeySlice = [EntryKey; LEVEL_4];
type Level4TreePtrSlice = [NodeCellRef; LEVEL_4 + 1];
type Level4Tree = BPlusTree<Level4TreeKeySlice, Level4TreePtrSlice>;<|endoftext|>


<commit_before>//! Interpolation algorithms.
//!
//! Interpolation is used in animation, to describe smooth shapes and to make transitions.
//! Any object that fullfill certain mathematical properties can be interpolated.
//! A common technique is using one ore more 'numbers' controlling the mixture of states.
//! The choice of interpolation algorithm depends often on the circumstances where it used.

/// Performs linear interpolation.
/// A linear interpolation consists of two states 'a' and 'b'.
/// The 't' variable is a factor between 0 and 1 that gives weight to 'a' or 'b'.
/// When 't' is zero then 'a' has full weight.
/// When 't' is one then 'b' has full weight.
#[inline(always)]
pub fn lerp<T: Add<T, T> + Sub<T, T> + Mul, U>(a: &T, b: &T, t: &U) -> T {
    *a + (*b - *a) * *t
}

/// Performs quadratic beziér interpolation.
/// This is done by nesting linear interpolations.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn quad_bez<T: Add<T, T> + Sub<T, T> + Mul, U>(x0: &T, x1: &T, x2: &T, t: &U) -> T {
    let x_0_1 = lerp(x0, x1, t);
    let x_1_2 = lerp(x1, x2, t);
    lerp(&x_0_1, &x_1_2, t)
}

/// Performs cubic beziér interpolation.
/// This is done by interpolation between two quadratic beziér.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn cub_bez<T: Add<T, T> + Sub<T, T> + Mul, U>(x0: &T, x1: &T, x2: &T, x3: &T, t: &U) -> T {
    let x_0_2 = quad_bez(x0, x1, x2, t);
    let x_1_3 = quad_bez(x1, x2, x3, t);
    lerp(&x_0_2, &x_1_3, t)
}

<commit_msg>Added `lerp_x` for x = 2, 3, 4, 5<commit_after>//! Interpolation algorithms.
//!
//! Interpolation is used in animation, to describe smooth shapes and to make transitions.
//! Any object that fullfill certain mathematical properties can be interpolated.
//! A common technique is using one ore more 'numbers' controlling the mixture of states.
//! The choice of interpolation algorithm depends often on the circumstances where it used.

/// Performs linear interpolation.
/// A linear interpolation consists of two states 'a' and 'b'.
/// The 't' variable is a factor between 0 and 1 that gives weight to 'a' or 'b'.
/// When 't' is zero then 'a' has full weight.
/// When 't' is one then 'b' has full weight.
#[inline(always)]
pub fn lerp<T: Add<T, T> + Sub<T, T> + Mul, U>(a: &T, b: &T, t: &U) -> T {
    *a + (*b - *a) * *t
}

/// Performs linear interpolation on array of size 3.
#[inline(always)]
pub fn lerp_2<T: Add<T, T> + Sub<T, T> + Mul, U>(a: &[T, ..2], b: &[T, ..2], t: &U) -> [T, ..2] {
    [lerp(&a[0], &b[0], t),
    lerp(&a[1], &b[1], t)]
}

/// Performs linear interpolation on array of size 3.
#[inline(always)]
pub fn lerp_3<T: Add<T, T> + Sub<T, T> + Mul, U>(a: &[T, ..3], b: &[T, ..3], t: &U) -> [T, ..3] {
    [lerp(&a[0], &b[0], t),
    lerp(&a[1], &b[1], t),
    lerp(&a[2], &b[2], t)]
}

/// Performs linear interpolation on array of size 4.
#[inline(always)]
pub fn lerp_4<T: Add<T, T> + Sub<T, T> + Mul, U>(a: &[T, ..4], b: &[T, ..4], t: &U) -> [T, ..4] {
    [lerp(&a[0], &b[0], t),
    lerp(&a[1], &b[1], t),
    lerp(&a[2], &b[2], t),
    lerp(&a[3], &b[3], t)]
}

/// Performs linear interpolation on array of size 5.
#[inline(always)]
pub fn lerp_5<T: Add<T, T> + Sub<T, T> + Mul, U>(a: &[T, ..5], b: &[T, ..5], t: &U) -> [T, ..5] {
    [lerp(&a[0], &b[0], t),
    lerp(&a[1], &b[1], t),
    lerp(&a[2], &b[2], t),
    lerp(&a[3], &b[3], t),
    lerp(&a[4], &b[4], t)]
}

/// Performs quadratic beziér interpolation.
/// This is done by nesting linear interpolations.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn quad_bez<T: Add<T, T> + Sub<T, T> + Mul, U>(x0: &T, x1: &T, x2: &T, t: &U) -> T {
    let x_0_1 = lerp(x0, x1, t);
    let x_1_2 = lerp(x1, x2, t);
    lerp(&x_0_1, &x_1_2, t)
}

/// Performs cubic beziér interpolation.
/// This is done by interpolation between two quadratic beziér.
/// For more information, see:
///
/// Beziér Curve at Wikipedia
#[inline(always)]
pub fn cub_bez<T: Add<T, T> + Sub<T, T> + Mul, U>(x0: &T, x1: &T, x2: &T, x3: &T, t: &U) -> T {
    let x_0_2 = quad_bez(x0, x1, x2, t);
    let x_1_3 = quad_bez(x1, x2, x3, t);
    lerp(&x_0_2, &x_1_3, t)
}

<|endoftext|>


<commit_before>//! Panic support in the standard library.

#![unstable(feature = "core_panic_info",
            reason = "newly available in libcore",
            issue = "44489")]

use crate::any::Any;
use crate::fmt;

/// A struct providing information about a panic.
///
/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
/// function.
///
/// [`set_hook`]: ../../std/panic/fn.set_hook.html
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
///     if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
///         println!("panic occurred: {:?}", s);
///     } else {
///         println!("panic occurred");
///     }
/// }));
///
/// panic!("Normal panic");
/// ```
#[lang = "panic_info"]
#[stable(feature = "panic_hooks", since = "1.10.0")]
#[derive(Debug)]
pub struct PanicInfo<'a> {
    payload: &'a (dyn Any + Send),
    message: Option<&'a fmt::Arguments<'a>>,
    location: &'a Location<'a>,
}

impl<'a> PanicInfo<'a> {
    #![unstable(feature = "panic_internals",
                reason = "internal details of the implementation of the `panic!` \
                          and related macros",
                issue = "0")]
    #[doc(hidden)]
    #[inline]
    pub fn internal_constructor(
        message: Option<&'a fmt::Arguments<'a>>,
        location: &'a Location<'a>,
    ) -> Self {
        struct NoPayload;
        PanicInfo {
            location,
            message,
            payload: &NoPayload,
        }
    }

    #[doc(hidden)]
    #[inline]
    pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
        self.payload = info;
    }

    /// Returns the payload associated with the panic.
    ///
    /// This will commonly, but not always, be a `&'static str` or [`String`].
    ///
    /// [`String`]: ../../std/string/struct.String.html
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     println!("panic occurred: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap());
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn payload(&self) -> &(dyn Any + Send) {
        self.payload
    }

    /// If the `panic!` macro from the `core` crate (not from `std`)
    /// was used with a formatting string and some additional arguments,
    /// returns that message ready to be used for example with [`fmt::write`]
    ///
    /// [`fmt::write`]: ../fmt/fn.write.html
    #[unstable(feature = "panic_info_message", issue = "44489")]
    pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
        self.message
    }

    /// Returns information about the location from which the panic originated,
    /// if available.
    ///
    /// This method will currently always return [`Some`], but this may change
    /// in future versions.
    ///
    /// [`Some`]: ../../std/option/enum.Option.html#variant.Some
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred in file '{}' at line {}", location.file(),
    ///             location.line());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn location(&self) -> Option<&Location<'_>> {
        // NOTE: If this is changed to sometimes return None,
        // deal with that case in std::panicking::default_hook and std::panicking::begin_panic_fmt.
        Some(&self.location)
    }
}

#[stable(feature = "panic_hook_display", since = "1.26.0")]
impl fmt::Display for PanicInfo<'_> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("panicked at ")?;
        if let Some(message) = self.message {
            write!(formatter, "'{}', ", message)?
        } else if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
            write!(formatter, "'{}', ", payload)?
        }
        // NOTE: we cannot use downcast_ref::<String>() here
        // since String is not available in libcore!
        // The payload is a String when `std::panic!` is called with multiple arguments,
        // but in that case the message is also available.

        self.location.fmt(formatter)
    }
}

/// A struct containing information about the location of a panic.
///
/// This structure is created by the [`location`] method of [`PanicInfo`].
///
/// [`location`]: ../../std/panic/struct.PanicInfo.html#method.location
/// [`PanicInfo`]: ../../std/panic/struct.PanicInfo.html
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
///     if let Some(location) = panic_info.location() {
///         println!("panic occurred in file '{}' at line {}", location.file(), location.line());
///     } else {
///         println!("panic occurred but can't get location information...");
///     }
/// }));
///
/// panic!("Normal panic");
/// ```
#[lang = "panic_location"]
#[derive(Debug)]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub struct Location<'a> {
    file: &'a str,
    line: u32,
    col: u32,
}

impl<'a> Location<'a> {
    #![unstable(feature = "panic_internals",
                reason = "internal details of the implementation of the `panic!` \
                          and related macros",
                issue = "0")]
    #[doc(hidden)]
    pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
        Location { file, line, col }
    }

    /// Returns the name of the source file from which the panic originated.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred in file '{}'", location.file());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn file(&self) -> &str {
        self.file
    }

    /// Returns the line number from which the panic originated.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred at line {}", location.line());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn line(&self) -> u32 {
        self.line
    }

    /// Returns the column from which the panic originated.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred at column {}", location.column());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_col", since = "1.25.0")]
    pub fn column(&self) -> u32 {
        self.col
    }
}

#[stable(feature = "panic_hook_display", since = "1.26.0")]
impl fmt::Display for Location<'_> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "{}:{}:{}", self.file, self.line, self.col)
    }
}

/// An internal trait used by libstd to pass data from libstd to `panic_unwind`
/// and other panic runtimes. Not intended to be stabilized any time soon, do
/// not use.
#[unstable(feature = "std_internals", issue = "0")]
#[doc(hidden)]
pub unsafe trait BoxMeUp {
    fn box_me_up(&mut self) -> *mut (dyn Any + Send);
    fn get(&mut self) -> &(dyn Any + Send);
}
<commit_msg>Fix unstable attribute accidentally applying to the entire impl<commit_after>//! Panic support in the standard library.

#![unstable(feature = "core_panic_info",
            reason = "newly available in libcore",
            issue = "44489")]

use crate::any::Any;
use crate::fmt;

/// A struct providing information about a panic.
///
/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
/// function.
///
/// [`set_hook`]: ../../std/panic/fn.set_hook.html
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
///     if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
///         println!("panic occurred: {:?}", s);
///     } else {
///         println!("panic occurred");
///     }
/// }));
///
/// panic!("Normal panic");
/// ```
#[lang = "panic_info"]
#[stable(feature = "panic_hooks", since = "1.10.0")]
#[derive(Debug)]
pub struct PanicInfo<'a> {
    payload: &'a (dyn Any + Send),
    message: Option<&'a fmt::Arguments<'a>>,
    location: &'a Location<'a>,
}

impl<'a> PanicInfo<'a> {
    #[unstable(feature = "panic_internals",
               reason = "internal details of the implementation of the `panic!` \
                         and related macros",
               issue = "0")]
    #[doc(hidden)]
    #[inline]
    pub fn internal_constructor(
        message: Option<&'a fmt::Arguments<'a>>,
        location: &'a Location<'a>,
    ) -> Self {
        struct NoPayload;
        PanicInfo {
            location,
            message,
            payload: &NoPayload,
        }
    }

    #[unstable(feature = "panic_internals",
               reason = "internal details of the implementation of the `panic!` \
                         and related macros",
               issue = "0")]
    #[doc(hidden)]
    #[inline]
    pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
        self.payload = info;
    }

    /// Returns the payload associated with the panic.
    ///
    /// This will commonly, but not always, be a `&'static str` or [`String`].
    ///
    /// [`String`]: ../../std/string/struct.String.html
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     println!("panic occurred: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap());
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn payload(&self) -> &(dyn Any + Send) {
        self.payload
    }

    /// If the `panic!` macro from the `core` crate (not from `std`)
    /// was used with a formatting string and some additional arguments,
    /// returns that message ready to be used for example with [`fmt::write`]
    ///
    /// [`fmt::write`]: ../fmt/fn.write.html
    #[unstable(feature = "panic_info_message", issue = "44489")]
    pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
        self.message
    }

    /// Returns information about the location from which the panic originated,
    /// if available.
    ///
    /// This method will currently always return [`Some`], but this may change
    /// in future versions.
    ///
    /// [`Some`]: ../../std/option/enum.Option.html#variant.Some
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred in file '{}' at line {}", location.file(),
    ///             location.line());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn location(&self) -> Option<&Location<'_>> {
        // NOTE: If this is changed to sometimes return None,
        // deal with that case in std::panicking::default_hook and std::panicking::begin_panic_fmt.
        Some(&self.location)
    }
}

#[stable(feature = "panic_hook_display", since = "1.26.0")]
impl fmt::Display for PanicInfo<'_> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("panicked at ")?;
        if let Some(message) = self.message {
            write!(formatter, "'{}', ", message)?
        } else if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
            write!(formatter, "'{}', ", payload)?
        }
        // NOTE: we cannot use downcast_ref::<String>() here
        // since String is not available in libcore!
        // The payload is a String when `std::panic!` is called with multiple arguments,
        // but in that case the message is also available.

        self.location.fmt(formatter)
    }
}

/// A struct containing information about the location of a panic.
///
/// This structure is created by the [`location`] method of [`PanicInfo`].
///
/// [`location`]: ../../std/panic/struct.PanicInfo.html#method.location
/// [`PanicInfo`]: ../../std/panic/struct.PanicInfo.html
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
///     if let Some(location) = panic_info.location() {
///         println!("panic occurred in file '{}' at line {}", location.file(), location.line());
///     } else {
///         println!("panic occurred but can't get location information...");
///     }
/// }));
///
/// panic!("Normal panic");
/// ```
#[lang = "panic_location"]
#[derive(Debug)]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub struct Location<'a> {
    file: &'a str,
    line: u32,
    col: u32,
}

impl<'a> Location<'a> {
    #![unstable(feature = "panic_internals",
                reason = "internal details of the implementation of the `panic!` \
                          and related macros",
                issue = "0")]
    #[doc(hidden)]
    pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
        Location { file, line, col }
    }

    /// Returns the name of the source file from which the panic originated.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred in file '{}'", location.file());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn file(&self) -> &str {
        self.file
    }

    /// Returns the line number from which the panic originated.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred at line {}", location.line());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn line(&self) -> u32 {
        self.line
    }

    /// Returns the column from which the panic originated.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred at column {}", location.column());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_col", since = "1.25.0")]
    pub fn column(&self) -> u32 {
        self.col
    }
}

#[stable(feature = "panic_hook_display", since = "1.26.0")]
impl fmt::Display for Location<'_> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "{}:{}:{}", self.file, self.line, self.col)
    }
}

/// An internal trait used by libstd to pass data from libstd to `panic_unwind`
/// and other panic runtimes. Not intended to be stabilized any time soon, do
/// not use.
#[unstable(feature = "std_internals", issue = "0")]
#[doc(hidden)]
pub unsafe trait BoxMeUp {
    fn box_me_up(&mut self) -> *mut (dyn Any + Send);
    fn get(&mut self) -> &(dyn Any + Send);
}
<|endoftext|>


<commit_before>use std::f32::consts::PI;
use std::sync::Arc;

use uuid::Uuid;

use {Point3f, Vector3f, Point2f, Transform};
use interaction::{Interaction, SurfaceInteraction};
use light::{Light, LightFlags, VisibilityTester};
use paramset::ParamSet;
use scene::Scene;
use spectrum::Spectrum;

#[derive(Debug)]
pub struct DistantLight {
    pub id: Uuid,
    pub dir: Vector3f,
    pub emission_colour: Spectrum,
    w_center: Point3f,
    w_radius: f32,
}

impl DistantLight {
    pub fn new(dir: Vector3f, ec: Spectrum) -> DistantLight {
        DistantLight {
            id: Uuid::new_v4(),
            dir: dir.normalize(),
            emission_colour: ec,
            w_center: Point3f::new(0.0, 0.0, 0.0),
            w_radius: 100.0, // TODO
        }
    }

    pub fn create(l2w: &Transform, params: &mut ParamSet) -> Arc<Light + Send + Sync> {
        let L = params.find_one_spectrum("L", Spectrum::white());
        let scale = params.find_one_spectrum("scale", Spectrum::white());
        let from = params.find_one_point3f("from", Point3f::origin());
        let to = params.find_one_point3f("to", Point3f::new(0.0, 0.0, 1.0));
        let dir = from - to;
        Arc::new(DistantLight::new(l2w * &dir, L * scale))
    }
}

impl Light for DistantLight {
    fn id(&self) -> Uuid {
        self.id
    }

    fn preprocess(&mut self, scene: &Scene) {
        let (w_center, w_radius) = scene.world_bounds().bounding_sphere();
        self.w_center = w_center;
        self.w_radius = w_radius;
    }

    fn sample_li(&self,
                 isect: &SurfaceInteraction,
                 _u: &Point2f)
                 -> (Spectrum, Vector3f, f32, VisibilityTester) {
        let p_outside = isect.p - self.dir * (2.0 * self.w_radius);
        (self.emission_colour,
         -self.dir,
         1.0,
         VisibilityTester::new(isect.into(), Interaction::from_point(&p_outside)))
    }

    fn pdf_li(&self, _si: &SurfaceInteraction, _wi: &Vector3f) -> f32 {
        0.0
    }

    fn n_samples(&self) -> u32 {
        1
    }

    fn flags(&self) -> LightFlags {
        LightFlags::DELTA_DIRECTION
    }

    fn power(&self) -> Spectrum {
        self.emission_colour * PI * self.w_radius * self.w_radius
    }
}
<commit_msg>Fix bug in DistantLight<commit_after>use std::f32::consts::PI;
use std::sync::Arc;

use uuid::Uuid;

use {Point2f, Point3f, Transform, Vector3f};
use interaction::{Interaction, SurfaceInteraction};
use light::{Light, LightFlags, VisibilityTester};
use paramset::ParamSet;
use scene::Scene;
use spectrum::Spectrum;

#[derive(Debug)]
pub struct DistantLight {
    pub id: Uuid,
    pub dir: Vector3f,
    pub emission_colour: Spectrum,
    w_center: Point3f,
    w_radius: f32,
}

impl DistantLight {
    pub fn new(dir: Vector3f, ec: Spectrum) -> DistantLight {
        DistantLight {
            id: Uuid::new_v4(),
            dir: dir.normalize(),
            emission_colour: ec,
            w_center: Point3f::new(0.0, 0.0, 0.0),
            w_radius: 100.0, // TODO
        }
    }

    pub fn create(l2w: &Transform, params: &mut ParamSet) -> Arc<Light + Send + Sync> {
        let L = params.find_one_spectrum("L", Spectrum::white());
        let scale = params.find_one_spectrum("scale", Spectrum::white());
        let from = params.find_one_point3f("from", Point3f::origin());
        let to = params.find_one_point3f("to", Point3f::new(0.0, 0.0, 1.0));
        let dir = from - to;
        Arc::new(DistantLight::new(l2w * &dir, L * scale))
    }
}

impl Light for DistantLight {
    fn id(&self) -> Uuid {
        self.id
    }

    fn preprocess(&mut self, scene: &Scene) {
        let (w_center, w_radius) = scene.world_bounds().bounding_sphere();
        self.w_center = w_center;
        self.w_radius = w_radius;
    }

    fn sample_li(
        &self,
        isect: &SurfaceInteraction,
        _u: &Point2f,
    ) -> (Spectrum, Vector3f, f32, VisibilityTester) {
        let p_outside = isect.p - self.dir * (2.0 * self.w_radius);
        (
            self.emission_colour,
            self.dir,
            1.0,
            VisibilityTester::new(isect.into(), Interaction::from_point(&p_outside)),
        )
    }

    fn pdf_li(&self, _si: &SurfaceInteraction, _wi: &Vector3f) -> f32 {
        0.0
    }

    fn n_samples(&self) -> u32 {
        1
    }

    fn flags(&self) -> LightFlags {
        LightFlags::DELTA_DIRECTION
    }

    fn power(&self) -> Spectrum {
        self.emission_colour * PI * self.w_radius * self.w_radius
    }
}
<|endoftext|>


<commit_before>extern mod extra;

use parse::parse_recursive;
use state::ParseState;
use compile::{Instruction, compile_recursive};
use error::ParseError::*;

mod parse;
mod state;
mod compile;
mod error;

static PARSE_ERR: &'static str = "Parse Error: ";

struct Regexp {
  input: ~str
}

impl Regexp {
  pub fn new(s: &str) -> Regexp {
    Regexp { input: s.clone().to_owned() }
  }
}

impl Regexp {
  // we should hide the underlying parsing algorithm
  // from the user
  fn parse(&mut self) -> Result<state::Regexp, ParseCode> {
    let mut ps = ParseState::new();
    match parse_recursive(&mut self.input, &mut ps) {
      ParseOk => {
        ps.pop()
      }
      e => {
        println(Regexp::parse_err_to_str(e));
        Err(e)
      }
    }
  }
  fn compile(&mut self) {
    let mut stack: ~[Instruction] = ~[];
    match self.parse() {
      Ok(ref re) => {
        compile_recursive(re, &mut stack);
      }
      Err(e) => {
        println(Regexp::parse_err_to_str(e));
      }
    };
  }
}

impl Regexp {
  fn parse_err_to_str(code: ParseCode) -> ~str {
    match code {
      ParseOk                     => ~"Ok",
      ParseEmptyAlternate         => PARSE_ERR + "Nothing to alternate",
      ParseEmptyConcatenate       => PARSE_ERR + "Nothing to concatenate",
      ParseRepeatedRepetition     => PARSE_ERR + "Multiple repeat operations",
      ParseEmptyRepetition        => PARSE_ERR + "Nothing to repeat",
      ParseEmptyRepetitionRange   => PARSE_ERR + "Repeat range is empty",
      ParseExpectedClosingParen   => PARSE_ERR + "Expected ')'",
      ParseExpectedClosingBracket => PARSE_ERR + "Expected ']'",
      ParseExpectedClosingBrace   => PARSE_ERR + "Expected '}'",
      ParseExpectedComma          => PARSE_ERR + "Expected ','",
      ParseExpectedAlpha          => PARSE_ERR + "Expected alpha character",
      ParseExpectedNumeric        => PARSE_ERR + "Expected number",
      ParseExpectedOperand        => PARSE_ERR + "Expected an operand on the stack",
      ParseUnexpectedClosingParen => PARSE_ERR + "Unexpected closing parenthases in input",
      ParseUnexpectedOperand      => PARSE_ERR + "Unexpected operand was on the stack",
      ParseUnexpectedCharacter    => PARSE_ERR + "Unexpected character in input",
      ParseEmptyCharClassRange    => PARSE_ERR + "Empty character class",
      ParseInternalError |
      ParseUnknownError           => PARSE_ERR + "Unknown error (probably a bug)",
      ParseEmptyStack             => PARSE_ERR + "Nothing on the stack"
    }
  }
}

fn main() {
  // println("--Case 0--");
  // Regexp::new("abc").compile();

  // println("--Case 1--");
  // Regexp::new("a|b").compile();

  // println("--Case 2--");
  // Regexp::new("a|b|c").compile();

  // println("--Case 3--");
  // Regexp::new("a|(Bcf)|dez").compile();

  // println("--Case 4--");
  // //Regexp::new("abc*|d").parse();

  // println("--Case 5--");
  // //Regexp::new("io(ab|c)*zz|(bcd)*").parse();

  // println("--Case 6--");
  // //Regexp::new("あ(ab(cd|d)|e)|f").parse();

  println("--Case 7--");
  //Regexp::new("[[A-Z]0-9(fgh)]]]|[abc]").parse();
  Regexp::new("[1-]]").parse();

  println("--Case 8--");
  Regexp::new("(abc){1,}").parse();

  println("--Case 9--");
  Regexp::new("abc{3,4}?").parse();

  println("--Case 10--");
  Regexp::new("a|b{3}").parse();

  println("--Case 11--");
  Regexp::new("a{4,3}?").parse();

  println("--Case 12--");
  Regexp::new("[C[e-h]arlemange]|bs|c").compile();

  println("--Case 13--");
  Regexp::new("[^aA-ZA]").parse();

  println("--Case 14--");
  Regexp::new("[^\U00000000-\U0010FFFF]").parse();
}
<commit_msg>added test case<commit_after>extern mod extra;

use parse::parse_recursive;
use state::ParseState;
use compile::{Instruction, compile_recursive};
use error::ParseError::*;

mod parse;
mod state;
mod compile;
mod error;

static PARSE_ERR: &'static str = "Parse Error: ";

struct Regexp {
  input: ~str
}

impl Regexp {
  pub fn new(s: &str) -> Regexp {
    Regexp { input: s.clone().to_owned() }
  }
}

impl Regexp {
  // we should hide the underlying parsing algorithm
  // from the user
  fn parse(&mut self) -> Result<state::Regexp, ParseCode> {
    let mut ps = ParseState::new();
    match parse_recursive(&mut self.input, &mut ps) {
      ParseOk => {
        ps.pop()
      }
      e => {
        println(Regexp::parse_err_to_str(e));
        Err(e)
      }
    }
  }
  fn compile(&mut self) {
    let mut stack: ~[Instruction] = ~[];
    match self.parse() {
      Ok(ref re) => {
        compile_recursive(re, &mut stack);
      }
      Err(e) => {
        println(Regexp::parse_err_to_str(e));
      }
    };
  }
}

impl Regexp {
  fn parse_err_to_str(code: ParseCode) -> ~str {
    match code {
      ParseOk                     => ~"Ok",
      ParseEmptyAlternate         => PARSE_ERR + "Nothing to alternate",
      ParseEmptyConcatenate       => PARSE_ERR + "Nothing to concatenate",
      ParseRepeatedRepetition     => PARSE_ERR + "Multiple repeat operations",
      ParseEmptyRepetition        => PARSE_ERR + "Nothing to repeat",
      ParseEmptyRepetitionRange   => PARSE_ERR + "Repeat range is empty",
      ParseExpectedClosingParen   => PARSE_ERR + "Expected ')'",
      ParseExpectedClosingBracket => PARSE_ERR + "Expected ']'",
      ParseExpectedClosingBrace   => PARSE_ERR + "Expected '}'",
      ParseExpectedComma          => PARSE_ERR + "Expected ','",
      ParseExpectedAlpha          => PARSE_ERR + "Expected alpha character",
      ParseExpectedNumeric        => PARSE_ERR + "Expected number",
      ParseExpectedOperand        => PARSE_ERR + "Expected an operand on the stack",
      ParseUnexpectedClosingParen => PARSE_ERR + "Unexpected closing parenthases in input",
      ParseUnexpectedOperand      => PARSE_ERR + "Unexpected operand was on the stack",
      ParseUnexpectedCharacter    => PARSE_ERR + "Unexpected character in input",
      ParseEmptyCharClassRange    => PARSE_ERR + "Empty character class",
      ParseInternalError |
      ParseUnknownError           => PARSE_ERR + "Unknown error (probably a bug)",
      ParseEmptyStack             => PARSE_ERR + "Nothing on the stack"
    }
  }
}

fn main() {
  // println("--Case 0--");
  // Regexp::new("abc").compile();

  // println("--Case 1--");
  // Regexp::new("a|b").compile();

  // println("--Case 2--");
  // Regexp::new("a|b|c").compile();

  // println("--Case 3--");
  // Regexp::new("a|(Bcf)|dez").compile();

  // println("--Case 4--");
  // //Regexp::new("abc*|d").parse();

  // println("--Case 5--");
  // //Regexp::new("io(ab|c)*zz|(bcd)*").parse();

  // println("--Case 6--");
  // //Regexp::new("あ(ab(cd|d)|e)|f").parse();

  println("--Case 7--");
  //Regexp::new("[[A-Z]0-9(fgh)]]]|[abc]").parse();
  Regexp::new("[1-]]").parse();

  println("--Case 8--");
  Regexp::new("(abc){1,}").parse();

  println("--Case 9--");
  Regexp::new("abc{3,4}?").parse();

  println("--Case 10--");
  Regexp::new("a|b{3}").parse();

  println("--Case 11--");
  Regexp::new("a{4,3}?").parse();

  println("--Case 12--");
  Regexp::new("[C[e-h]arlemange]|bs|c").compile();

  println("--Case 13--");
  Regexp::new("[^aA-ZA]").compile();

  println("--Case 14--");
  Regexp::new("[^\U00000000-\U0010FFFF]").parse();
}
<|endoftext|>


<commit_before>extern crate sputnikvm;
extern crate serde_json;

mod blockchain;

pub use self::blockchain::{JSONBlock, create_block, create_context};

use serde_json::Value;
use std::str::FromStr;
use sputnikvm::{Gas, M256, U256, Address, read_hex};
use sputnikvm::vm::errors::RequireError;
use sputnikvm::vm::{VM, SeqVM, AccountCommitment, Context, Account, HashMapStorage, Patch, VMStatus};

pub fn fire_with_block(machine: &mut SeqVM, block: &JSONBlock) {
    loop {
        match machine.fire() {
            Err(RequireError::Account(address)) => {
                let account = block.request_account(address);
                machine.commit_account(account);
            },
            Err(RequireError::AccountCode(address)) => {
                let account = block.request_account_code(address);
                machine.commit_account(account);
            },
            Err(RequireError::Blockhash(number)) => {
                // The test JSON file doesn't expose any block
                // information. So those numbers are crafted by hand.
                let hash1 = M256::from_str("0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6").unwrap();
                let hash2 = M256::from_str("0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5").unwrap();
                let hash256 = M256::from_str("0x6ca54da2c4784ea43fd88b3402de07ae4bced597cbb19f323b7595857a6720ae").unwrap();

                let hash = if number == M256::from(1u64) {
                    hash1
                } else if number == M256::from(2u64) {
                    hash2
                } else if number == M256::from(256u64) {
                    hash256
                } else {
                    panic!();
                };

                machine.commit_blockhash(number, hash);
            },
            Ok(()) => return,
        }
    }
}

pub fn apply_to_block(machine: &SeqVM, block: &mut JSONBlock) {
    for account in machine.accounts() {
        let account = (*account).clone();
        block.apply_account(account);
    }
    // for log in machine.appending_logs() {
    //     let log = (*log).clone();
    //     block.apply_log(log);
    // }
}

pub fn create_machine(v: &Value, block: &JSONBlock) -> SeqVM {
    let transaction = create_context(v);

    SeqVM::new(transaction, block.block_header(), Patch::None)
}

pub fn test_machine(v: &Value, machine: &SeqVM, block: &JSONBlock, debug: bool) -> bool {
    // let ref callcreates = v["callcreates"];

    // if callcreates.as_array().is_some() {
    //     let mut i = 0;
    //     for callcreate in callcreates.as_array().unwrap() {
    //         let data = read_hex(callcreate["data"].as_str().unwrap()).unwrap();
    //         let destination = {
    //             let destination = callcreate["destination"].as_str().unwrap();
    //             if destination == "" {
    //                 None
    //             } else {
    //                 Some(Address::from_str(destination).unwrap())
    //             }
    //         };
    //         let gas_limit = Gas::from_str(callcreate["gasLimit"].as_str().unwrap()).unwrap();
    //         let value = U256::from_str(callcreate["value"].as_str().unwrap()).unwrap();

    //         if i >= machine.transactions().len() {
    //             if debug {
    //                 print!("\n");
    //                 println!("Transaction check failed, expected more than {} items.", i);
    //             }
    //             return false;
    //         }
    //         let ref transaction = machine.transactions()[i];
    //         if destination.is_none() {
    //             match transaction {
    //                 &Transaction::ContractCreation(ref create) => {
    //                     if create.gas_limit != gas_limit || create.value != value || create.init != data {
    //                         if debug {
    //                             print!("\n");
    //                             println!("Transaction mismatch. Received gas_limit 0x{:x}, value 0x{:x}", create.gas_limit, create.value);
    //                         }
    //                         return false;
    //                     }
    //                 }
    //                 &Transaction::MessageCall(ref call) => {
    //                     if debug {
    //                         print!("\n");
    //                         println!("Transaction mismatch. Received: {:?}", call);
    //                     }
    //                 }
    //             }
    //         } else {
    //             match transaction {
    //                 &Transaction::MessageCall(ref call) => {
    //                     if call.gas_limit != gas_limit || call.value != value || call.data != data || call.to != destination.unwrap() {
    //                         if debug {
    //                             print!("\n");
    //                             println!("Transaction mismatch. Received gas_limit 0x{:x}, value: 0x{:x}", call.gas_limit, call.value);
    //                         }
    //                         return false;
    //                     }
    //                 }
    //                 &Transaction::ContractCreation(ref create) => {
    //                     if debug {
    //                         print!("\n");
    //                         println!("Transaction mismatch. Received: {:?}", create);
    //                     }
    //                 }
    //             }
    //         }

    //         i = i + 1;
    //     }
    // }

    let out = v["out"].as_str();
    let gas = v["gas"].as_str();

    if out.is_some() {
        let out = read_hex(out.unwrap()).unwrap();
        let out_ref: &[u8] = out.as_ref();
        if machine.out() != out_ref {
            if debug {
                print!("\n");
                println!("Return value check failed. {:?} != {:?}", machine.out(), out_ref);
            }

            return false;
        }
    }

    if gas.is_some() {
        let gas = Gas::from_str(gas.unwrap()).unwrap();
        if machine.available_gas() != gas {
            if debug {
                print!("\n");
                println!("Gas check failed, VM returned: 0x{:x}, expected: 0x{:x}",
                         machine.available_gas(), gas);
            }

            return false;
        }
    }

    let ref post_addresses = v["post"];

    for (address, data) in post_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();
        let code_ref: &[u8] = code.as_ref();

        if code_ref != block.account_code(address) {
            if debug {
                print!("\n");
                println!("Account code check failed for address 0x{:x}.", address);
            }

            return false;
        }
        if balance != block.balance(address) {
            if debug {
                print!("\n");
                println!("Balance check failed for address 0x{:x}.", address);
            }

            return false;
        }

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = M256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            if value != block.account_storage(address, index) {
                if debug {
                    print!("\n");
                    println!("Storage check failed for address 0x{:x} in storage index 0x{:x}",
                             address, index);
                    println!("Expected: 0x{:x}", value);
                    println!("Actual:   0x{:x}", block.account_storage(address, index));
                }
                return false;
            }
        }
    }

    let ref expect = v["expect"];

    if expect.as_object().is_some() {
        for (address, data) in expect.as_object().unwrap() {
            let address = Address::from_str(address.as_str()).unwrap();

            let storage = data["storage"].as_object().unwrap();
            for (index, value) in storage {
                let index = M256::from_str(index.as_str()).unwrap();
                let value = M256::from_str(value.as_str().unwrap()).unwrap();
                if value != block.account_storage(address, index) {
                    if debug {
                        print!("\n");
                        println!("Storage check (expect) failed for address 0x{:x} in storage index 0x{:x}",
                                 address, index);
                        println!("Expected: 0x{:x}", value);
                        println!("Actual:   0x{:x}", block.account_storage(address, index));
                    }
                    return false;
                }
            }
        }
    }

    let ref logs = v["logs"].as_array();

    if logs.is_some() {
        let logs = logs.unwrap();

        for log in logs {
            let log = log.as_object().unwrap();

            let address = Address::from_str(log["address"].as_str().unwrap()).unwrap();
            let data = read_hex(log["data"].as_str().unwrap()).unwrap();
            let mut topics: Vec<M256> = Vec::new();

            for topic in log["topics"].as_array().unwrap() {
                topics.push(M256::from_str(topic.as_str().unwrap()).unwrap());
            }

            if !block.find_log(address, data.as_slice(), topics.as_slice()) {
                if debug {
                    print!("\n");
                    println!("Log match failed.");
                }
                return false;
            }
        }
    }

    return true;
}

fn is_ok(status: VMStatus) -> bool {
    match status {
        VMStatus::ExitedOk => true,
        _ => false,
    }
}

pub fn test_transaction(name: &str, v: &Value, debug: bool) -> bool {
    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    println!("status: {:?}", machine.status());
    let out = v["out"].as_str();

    if out.is_some() {
        if is_ok(machine.status()) {
            if test_machine(v, &machine, &block, debug) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        if !is_ok(machine.status()) {
            return true;
        } else {
            return false;
        }
    }
}
<commit_msg>Problem: forgot to apply logs back to block Solution: uncomment the code commented due to refactoring<commit_after>extern crate sputnikvm;
extern crate serde_json;

mod blockchain;

pub use self::blockchain::{JSONBlock, create_block, create_context};

use serde_json::Value;
use std::str::FromStr;
use sputnikvm::{Gas, M256, U256, Address, read_hex};
use sputnikvm::vm::errors::RequireError;
use sputnikvm::vm::{VM, SeqVM, AccountCommitment, Context, Account, HashMapStorage, Patch, VMStatus};

pub fn fire_with_block(machine: &mut SeqVM, block: &JSONBlock) {
    loop {
        match machine.fire() {
            Err(RequireError::Account(address)) => {
                let account = block.request_account(address);
                machine.commit_account(account);
            },
            Err(RequireError::AccountCode(address)) => {
                let account = block.request_account_code(address);
                machine.commit_account(account);
            },
            Err(RequireError::Blockhash(number)) => {
                // The test JSON file doesn't expose any block
                // information. So those numbers are crafted by hand.
                let hash1 = M256::from_str("0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6").unwrap();
                let hash2 = M256::from_str("0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5").unwrap();
                let hash256 = M256::from_str("0x6ca54da2c4784ea43fd88b3402de07ae4bced597cbb19f323b7595857a6720ae").unwrap();

                let hash = if number == M256::from(1u64) {
                    hash1
                } else if number == M256::from(2u64) {
                    hash2
                } else if number == M256::from(256u64) {
                    hash256
                } else {
                    panic!();
                };

                machine.commit_blockhash(number, hash);
            },
            Ok(()) => return,
        }
    }
}

pub fn apply_to_block(machine: &SeqVM, block: &mut JSONBlock) {
    for account in machine.accounts() {
        let account = (*account).clone();
        block.apply_account(account);
    }
    for log in machine.logs() {
        let log = (*log).clone();
        block.apply_log(log);
    }
}

pub fn create_machine(v: &Value, block: &JSONBlock) -> SeqVM {
    let transaction = create_context(v);

    SeqVM::new(transaction, block.block_header(), Patch::None)
}

pub fn test_machine(v: &Value, machine: &SeqVM, block: &JSONBlock, debug: bool) -> bool {
    // let ref callcreates = v["callcreates"];

    // if callcreates.as_array().is_some() {
    //     let mut i = 0;
    //     for callcreate in callcreates.as_array().unwrap() {
    //         let data = read_hex(callcreate["data"].as_str().unwrap()).unwrap();
    //         let destination = {
    //             let destination = callcreate["destination"].as_str().unwrap();
    //             if destination == "" {
    //                 None
    //             } else {
    //                 Some(Address::from_str(destination).unwrap())
    //             }
    //         };
    //         let gas_limit = Gas::from_str(callcreate["gasLimit"].as_str().unwrap()).unwrap();
    //         let value = U256::from_str(callcreate["value"].as_str().unwrap()).unwrap();

    //         if i >= machine.transactions().len() {
    //             if debug {
    //                 print!("\n");
    //                 println!("Transaction check failed, expected more than {} items.", i);
    //             }
    //             return false;
    //         }
    //         let ref transaction = machine.transactions()[i];
    //         if destination.is_none() {
    //             match transaction {
    //                 &Transaction::ContractCreation(ref create) => {
    //                     if create.gas_limit != gas_limit || create.value != value || create.init != data {
    //                         if debug {
    //                             print!("\n");
    //                             println!("Transaction mismatch. Received gas_limit 0x{:x}, value 0x{:x}", create.gas_limit, create.value);
    //                         }
    //                         return false;
    //                     }
    //                 }
    //                 &Transaction::MessageCall(ref call) => {
    //                     if debug {
    //                         print!("\n");
    //                         println!("Transaction mismatch. Received: {:?}", call);
    //                     }
    //                 }
    //             }
    //         } else {
    //             match transaction {
    //                 &Transaction::MessageCall(ref call) => {
    //                     if call.gas_limit != gas_limit || call.value != value || call.data != data || call.to != destination.unwrap() {
    //                         if debug {
    //                             print!("\n");
    //                             println!("Transaction mismatch. Received gas_limit 0x{:x}, value: 0x{:x}", call.gas_limit, call.value);
    //                         }
    //                         return false;
    //                     }
    //                 }
    //                 &Transaction::ContractCreation(ref create) => {
    //                     if debug {
    //                         print!("\n");
    //                         println!("Transaction mismatch. Received: {:?}", create);
    //                     }
    //                 }
    //             }
    //         }

    //         i = i + 1;
    //     }
    // }

    let out = v["out"].as_str();
    let gas = v["gas"].as_str();

    if out.is_some() {
        let out = read_hex(out.unwrap()).unwrap();
        let out_ref: &[u8] = out.as_ref();
        if machine.out() != out_ref {
            if debug {
                print!("\n");
                println!("Return value check failed. {:?} != {:?}", machine.out(), out_ref);
            }

            return false;
        }
    }

    if gas.is_some() {
        let gas = Gas::from_str(gas.unwrap()).unwrap();
        if machine.available_gas() != gas {
            if debug {
                print!("\n");
                println!("Gas check failed, VM returned: 0x{:x}, expected: 0x{:x}",
                         machine.available_gas(), gas);
            }

            return false;
        }
    }

    let ref post_addresses = v["post"];

    for (address, data) in post_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();
        let code_ref: &[u8] = code.as_ref();

        if code_ref != block.account_code(address) {
            if debug {
                print!("\n");
                println!("Account code check failed for address 0x{:x}.", address);
            }

            return false;
        }
        if balance != block.balance(address) {
            if debug {
                print!("\n");
                println!("Balance check failed for address 0x{:x}.", address);
            }

            return false;
        }

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = M256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            if value != block.account_storage(address, index) {
                if debug {
                    print!("\n");
                    println!("Storage check failed for address 0x{:x} in storage index 0x{:x}",
                             address, index);
                    println!("Expected: 0x{:x}", value);
                    println!("Actual:   0x{:x}", block.account_storage(address, index));
                }
                return false;
            }
        }
    }

    let ref expect = v["expect"];

    if expect.as_object().is_some() {
        for (address, data) in expect.as_object().unwrap() {
            let address = Address::from_str(address.as_str()).unwrap();

            let storage = data["storage"].as_object().unwrap();
            for (index, value) in storage {
                let index = M256::from_str(index.as_str()).unwrap();
                let value = M256::from_str(value.as_str().unwrap()).unwrap();
                if value != block.account_storage(address, index) {
                    if debug {
                        print!("\n");
                        println!("Storage check (expect) failed for address 0x{:x} in storage index 0x{:x}",
                                 address, index);
                        println!("Expected: 0x{:x}", value);
                        println!("Actual:   0x{:x}", block.account_storage(address, index));
                    }
                    return false;
                }
            }
        }
    }

    let ref logs = v["logs"].as_array();

    if logs.is_some() {
        let logs = logs.unwrap();

        for log in logs {
            let log = log.as_object().unwrap();

            let address = Address::from_str(log["address"].as_str().unwrap()).unwrap();
            let data = read_hex(log["data"].as_str().unwrap()).unwrap();
            let mut topics: Vec<M256> = Vec::new();

            for topic in log["topics"].as_array().unwrap() {
                topics.push(M256::from_str(topic.as_str().unwrap()).unwrap());
            }

            if !block.find_log(address, data.as_slice(), topics.as_slice()) {
                if debug {
                    print!("\n");
                    println!("Log match failed.");
                }
                return false;
            }
        }
    }

    return true;
}

fn is_ok(status: VMStatus) -> bool {
    match status {
        VMStatus::ExitedOk => true,
        _ => false,
    }
}

pub fn test_transaction(name: &str, v: &Value, debug: bool) -> bool {
    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    println!("status: {:?}", machine.status());
    let out = v["out"].as_str();

    if out.is_some() {
        if is_ok(machine.status()) {
            if test_machine(v, &machine, &block, debug) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        if !is_ok(machine.status()) {
            return true;
        } else {
            return false;
        }
    }
}
<|endoftext|>