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

//! The `servo` test application.
//!
//! Creates a `Browser` instance with a simple implementation of
//! the compositor's `WindowMethods` to create a working web browser.
//!
//! This browser's implementation of `WindowMethods` is built on top
//! of [glutin], the cross-platform OpenGL utility and windowing
//! library.
//!
//! For the engine itself look next door in `components/servo/lib.rs`.
//!
//! [glutin]: https://github.com/tomaka/glutin

#![feature(start, core_intrinsics)]

#[cfg(target_os = "android")]
extern crate android_injected_glue;
extern crate backtrace;
// The window backed by glutin
extern crate glutin_app as app;
#[macro_use]
extern crate log;
// The Servo engine
extern crate servo;
#[cfg(not(target_os = "android"))]
#[macro_use]
extern crate sig;

use backtrace::Backtrace;
use servo::Browser;
use servo::compositing::windowing::WindowEvent;
#[cfg(target_os = "android")]
use servo::config;
use servo::config::opts::{self, ArgumentParsingResult};
use servo::config::servo_version;
use servo::servo_config::prefs::PREFS;
use servo::servo_url::ServoUrl;
use std::env;
use std::panic;
use std::process;
use std::rc::Rc;
use std::thread;

pub mod platform {
    #[cfg(target_os = "macos")]
    pub use platform::macos::deinit;

    #[cfg(target_os = "macos")]
    pub mod macos;

    #[cfg(not(target_os = "macos"))]
    pub fn deinit() {}
}

#[cfg(not(target_os = "android"))]
fn install_crash_handler() {
    use backtrace::Backtrace;
    use sig::ffi::Sig;
    use std::intrinsics::abort;
    use std::thread;

    fn handler(_sig: i32) {
        let name = thread::current()
            .name()
            .map(|n| format!(" for thread \"{}\"", n))
            .unwrap_or("".to_owned());
        println!("Stack trace{}\n{:?}", name, Backtrace::new());
        unsafe {
            // N.B. Using process::abort() here causes the crash handler to be
            //      triggered recursively.
            abort();
        }
    }

    signal!(Sig::SEGV, handler); // handle segfaults
    signal!(Sig::ILL, handler); // handle stack overflow and unsupported CPUs
    signal!(Sig::IOT, handler); // handle double panics
    signal!(Sig::BUS, handler); // handle invalid memory access
}

#[cfg(target_os = "android")]
fn install_crash_handler() {}

fn main() {
    install_crash_handler();

    // Parse the command line options and store them globally
    let opts_result = opts::from_cmdline_args(&*args());

    let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result {
        Some(token)
    } else {
        if opts::get().is_running_problem_test && ::std::env::var("RUST_LOG").is_err() {
            ::std::env::set_var("RUST_LOG", "compositing::constellation");
        }

        None
    };

    // TODO: once log-panics is released, can this be replaced by
    // log_panics::init()?
    panic::set_hook(Box::new(|info| {
        warn!("Panic hook called.");
        let msg = match info.payload().downcast_ref::<&'static str>() {
            Some(s) => *s,
            None => {
                match info.payload().downcast_ref::<String>() {
                    Some(s) => &**s,
                    None => "Box<Any>",
                }
            },
        };
        let current_thread = thread::current();
        let name = current_thread.name().unwrap_or("<unnamed>");
        if let Some(location) = info.location() {
            println!("{} (thread {}, at {}:{})",
                     msg,
                     name,
                     location.file(),
                     location.line());
        } else {
            println!("{} (thread {})", msg, name);
        }
        if env::var("RUST_BACKTRACE").is_ok() {
            println!("{:?}", Backtrace::new());
        }

        error!("{}", msg);
    }));

    setup_logging();

    if let Some(token) = content_process_token {
        return servo::run_content_process(token);
    }

    if opts::get().is_printing_version {
        println!("{}", servo_version());
        process::exit(0);
    }

    let window = app::create_window(None);

    // If the url is not provided, we fallback to the homepage in PREFS,
    // or a blank page in case the homepage is not set either.
    let target_url = opts::get().url.clone()
                .unwrap_or(ServoUrl::parse(PREFS.get("shell.homepage").as_string()
                    .unwrap_or("about:blank")).unwrap());

    // Our wrapper around `Browser` that also implements some
    // callbacks required by the glutin window implementation.
    let mut browser = BrowserWrapper {
        browser: Browser::new(window.clone(), target_url)
    };

    browser.browser.setup_logging();

    register_glutin_resize_handler(&window, &mut browser);

    browser.browser.handle_events(vec![WindowEvent::InitializeCompositing]);

    // Feed events from the window to the browser until the browser
    // says to stop.
    loop {
        let should_continue = browser.browser.handle_events(window.wait_events());
        if !should_continue {
            break;
        }
    }

    unregister_glutin_resize_handler(&window);

    platform::deinit()
}

fn register_glutin_resize_handler(window: &Rc<app::window::Window>, browser: &mut BrowserWrapper) {
    unsafe {
        window.set_nested_event_loop_listener(browser);
    }
}

fn unregister_glutin_resize_handler(window: &Rc<app::window::Window>) {
    unsafe {
        window.remove_nested_event_loop_listener();
    }
}

struct BrowserWrapper {
    browser: Browser<app::window::Window>,
}

impl app::NestedEventLoopListener for BrowserWrapper {
    fn handle_event_from_nested_event_loop(&mut self, event: WindowEvent) -> bool {
        let is_resize = match event {
            WindowEvent::Resize(..) => true,
            _ => false,
        };
        if !self.browser.handle_events(vec![event]) {
            return false;
        }
        if is_resize {
            self.browser.repaint_synchronously()
        }
        true
    }
}

#[cfg(target_os = "android")]
fn setup_logging() {
    // Piping logs from stdout/stderr to logcat happens in android_injected_glue.
    ::std::env::set_var("RUST_LOG", "error");

    unsafe { android_injected_glue::ffi::app_dummy() };
}

#[cfg(not(target_os = "android"))]
fn setup_logging() {}

#[cfg(target_os = "android")]
/// Attempt to read parameters from a file since they are not passed to us in Android environments.
/// The first line should be the "servo" argument and the last should be the URL to load.
/// Blank lines and those beginning with a '#' are ignored.
/// Each line should be a separate parameter as would be parsed by the shell.
/// For example, "servo -p 10 http://en.wikipedia.org/wiki/Rust" would take 4 lines.
fn args() -> Vec<String> {
    use std::error::Error;
    use std::fs::File;
    use std::io::{BufRead, BufReader};

    let mut params_file = config::basedir::default_config_dir().unwrap();
    params_file.push("android_params");
    match File::open(params_file.to_str().unwrap()) {
        Ok(f) => {
            let mut vec = Vec::new();
            let file = BufReader::new(&f);
            for line in file.lines() {
                let l = line.unwrap().trim().to_owned();
                // ignore blank lines and those that start with a '#'
                match l.is_empty() || l.as_bytes()[0] == b'#' {
                    true => (),
                    false => vec.push(l),
                }
            }
            vec
        },
        Err(e) => {
            debug!("Failed to open params file '{}': {}",
                   params_file.to_str().unwrap(),
                   Error::description(&e));
            vec!["servo".to_owned(), "http://en.wikipedia.org/wiki/Rust".to_owned()]
        },
    }
}

#[cfg(not(target_os = "android"))]
fn args() -> Vec<String> {
    use std::env;
    env::args().collect()
}

#[cfg(target_os = "android")]
#[no_mangle]
#[inline(never)]
#[allow(non_snake_case)]
pub extern "C" fn android_main(app: *mut ()) {
    android_injected_glue::android_main2(app as *mut _, move |_, _| main());
}
<commit_msg>Auto merge of #17312 - sadmansk:fix/broken_windows_build, r=paulrouget<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The `servo` test application.
//!
//! Creates a `Browser` instance with a simple implementation of
//! the compositor's `WindowMethods` to create a working web browser.
//!
//! This browser's implementation of `WindowMethods` is built on top
//! of [glutin], the cross-platform OpenGL utility and windowing
//! library.
//!
//! For the engine itself look next door in `components/servo/lib.rs`.
//!
//! [glutin]: https://github.com/tomaka/glutin

#![feature(start, core_intrinsics)]

#[cfg(target_os = "android")]
extern crate android_injected_glue;
extern crate backtrace;
// The window backed by glutin
extern crate glutin_app as app;
#[macro_use]
extern crate log;
// The Servo engine
extern crate servo;
#[cfg(not(target_os = "android"))]
#[macro_use]
extern crate sig;

use backtrace::Backtrace;
use servo::Browser;
use servo::compositing::windowing::WindowEvent;
#[cfg(target_os = "android")]
use servo::config;
use servo::config::opts::{self, ArgumentParsingResult, parse_url_or_filename};
use servo::config::servo_version;
use servo::servo_config::prefs::PREFS;
use servo::servo_url::ServoUrl;
use std::env;
use std::panic;
use std::process;
use std::rc::Rc;
use std::thread;

pub mod platform {
    #[cfg(target_os = "macos")]
    pub use platform::macos::deinit;

    #[cfg(target_os = "macos")]
    pub mod macos;

    #[cfg(not(target_os = "macos"))]
    pub fn deinit() {}
}

#[cfg(not(target_os = "android"))]
fn install_crash_handler() {
    use backtrace::Backtrace;
    use sig::ffi::Sig;
    use std::intrinsics::abort;
    use std::thread;

    fn handler(_sig: i32) {
        let name = thread::current()
            .name()
            .map(|n| format!(" for thread \"{}\"", n))
            .unwrap_or("".to_owned());
        println!("Stack trace{}\n{:?}", name, Backtrace::new());
        unsafe {
            // N.B. Using process::abort() here causes the crash handler to be
            //      triggered recursively.
            abort();
        }
    }

    signal!(Sig::SEGV, handler); // handle segfaults
    signal!(Sig::ILL, handler); // handle stack overflow and unsupported CPUs
    signal!(Sig::IOT, handler); // handle double panics
    signal!(Sig::BUS, handler); // handle invalid memory access
}

#[cfg(target_os = "android")]
fn install_crash_handler() {}

fn main() {
    install_crash_handler();

    // Parse the command line options and store them globally
    let opts_result = opts::from_cmdline_args(&*args());

    let content_process_token = if let ArgumentParsingResult::ContentProcess(token) = opts_result {
        Some(token)
    } else {
        if opts::get().is_running_problem_test && ::std::env::var("RUST_LOG").is_err() {
            ::std::env::set_var("RUST_LOG", "compositing::constellation");
        }

        None
    };

    // TODO: once log-panics is released, can this be replaced by
    // log_panics::init()?
    panic::set_hook(Box::new(|info| {
        warn!("Panic hook called.");
        let msg = match info.payload().downcast_ref::<&'static str>() {
            Some(s) => *s,
            None => {
                match info.payload().downcast_ref::<String>() {
                    Some(s) => &**s,
                    None => "Box<Any>",
                }
            },
        };
        let current_thread = thread::current();
        let name = current_thread.name().unwrap_or("<unnamed>");
        if let Some(location) = info.location() {
            println!("{} (thread {}, at {}:{})",
                     msg,
                     name,
                     location.file(),
                     location.line());
        } else {
            println!("{} (thread {})", msg, name);
        }
        if env::var("RUST_BACKTRACE").is_ok() {
            println!("{:?}", Backtrace::new());
        }

        error!("{}", msg);
    }));

    setup_logging();

    if let Some(token) = content_process_token {
        return servo::run_content_process(token);
    }

    if opts::get().is_printing_version {
        println!("{}", servo_version());
        process::exit(0);
    }

    let window = app::create_window(None);

    // If the url is not provided, we fallback to the homepage in PREFS,
    // or a blank page in case the homepage is not set either.
    let cwd = env::current_dir().unwrap();
    let cmdline_url = opts::get().url.clone();
    let pref_url = PREFS.get("shell.homepage").as_string()
        .and_then(|str| parse_url_or_filename(&cwd, str).ok());
    let blank_url = ServoUrl::parse("about:blank").ok();

    let target_url = cmdline_url.or(pref_url).or(blank_url).unwrap();

    // Our wrapper around `Browser` that also implements some
    // callbacks required by the glutin window implementation.
    let mut browser = BrowserWrapper {
        browser: Browser::new(window.clone(), target_url)
    };

    browser.browser.setup_logging();

    register_glutin_resize_handler(&window, &mut browser);

    browser.browser.handle_events(vec![WindowEvent::InitializeCompositing]);

    // Feed events from the window to the browser until the browser
    // says to stop.
    loop {
        let should_continue = browser.browser.handle_events(window.wait_events());
        if !should_continue {
            break;
        }
    }

    unregister_glutin_resize_handler(&window);

    platform::deinit()
}

fn register_glutin_resize_handler(window: &Rc<app::window::Window>, browser: &mut BrowserWrapper) {
    unsafe {
        window.set_nested_event_loop_listener(browser);
    }
}

fn unregister_glutin_resize_handler(window: &Rc<app::window::Window>) {
    unsafe {
        window.remove_nested_event_loop_listener();
    }
}

struct BrowserWrapper {
    browser: Browser<app::window::Window>,
}

impl app::NestedEventLoopListener for BrowserWrapper {
    fn handle_event_from_nested_event_loop(&mut self, event: WindowEvent) -> bool {
        let is_resize = match event {
            WindowEvent::Resize(..) => true,
            _ => false,
        };
        if !self.browser.handle_events(vec![event]) {
            return false;
        }
        if is_resize {
            self.browser.repaint_synchronously()
        }
        true
    }
}

#[cfg(target_os = "android")]
fn setup_logging() {
    // Piping logs from stdout/stderr to logcat happens in android_injected_glue.
    ::std::env::set_var("RUST_LOG", "error");

    unsafe { android_injected_glue::ffi::app_dummy() };
}

#[cfg(not(target_os = "android"))]
fn setup_logging() {}

#[cfg(target_os = "android")]
/// Attempt to read parameters from a file since they are not passed to us in Android environments.
/// The first line should be the "servo" argument and the last should be the URL to load.
/// Blank lines and those beginning with a '#' are ignored.
/// Each line should be a separate parameter as would be parsed by the shell.
/// For example, "servo -p 10 http://en.wikipedia.org/wiki/Rust" would take 4 lines.
fn args() -> Vec<String> {
    use std::error::Error;
    use std::fs::File;
    use std::io::{BufRead, BufReader};

    let mut params_file = config::basedir::default_config_dir().unwrap();
    params_file.push("android_params");
    match File::open(params_file.to_str().unwrap()) {
        Ok(f) => {
            let mut vec = Vec::new();
            let file = BufReader::new(&f);
            for line in file.lines() {
                let l = line.unwrap().trim().to_owned();
                // ignore blank lines and those that start with a '#'
                match l.is_empty() || l.as_bytes()[0] == b'#' {
                    true => (),
                    false => vec.push(l),
                }
            }
            vec
        },
        Err(e) => {
            debug!("Failed to open params file '{}': {}",
                   params_file.to_str().unwrap(),
                   Error::description(&e));
            vec!["servo".to_owned(), "http://en.wikipedia.org/wiki/Rust".to_owned()]
        },
    }
}

#[cfg(not(target_os = "android"))]
fn args() -> Vec<String> {
    use std::env;
    env::args().collect()
}

#[cfg(target_os = "android")]
#[no_mangle]
#[inline(never)]
#[allow(non_snake_case)]
pub extern "C" fn android_main(app: *mut ()) {
    android_injected_glue::android_main2(app as *mut _, move |_, _| main());
}
<|endoftext|>


<commit_before>#[macro_use] extern crate bart_derive;

#[test]
fn it_works() {
    #[derive(BartDisplay)]
    #[template_string="Hello, {{name}}"]
    struct Test { name: String }

    assert_eq!(
        "Hello, World",
        format!("{}", Test { name: "World".to_owned() })
    );
}

#[test]
fn it_handles_names_with_underscore() {
    #[derive(BartDisplay)]
    #[template_string="Hello, {{your_name}}"]
    struct Test { your_name: String }

    assert_eq!(
        "Hello, World",
        format!("{}", Test { your_name: "World".to_owned() })
    );
}

#[test]
fn it_can_borrow() {
    #[derive(BartDisplay)]
    #[template_string="Hello, {{name}}"]
    struct Test<'a> { name: &'a str }

    assert_eq!(
        "Hello, World",
        format!("{}", Test { name: "World" })
    );
}

#[test]
fn it_performs_escaping() {
    #[derive(BartDisplay)]
    #[template_string="{{txt}}"]
    struct Test<'a> { txt: &'a str }

    assert_eq!(
        "<&"'",
        format!("{}", Test { txt: "<&\"'" })
    );
}

#[test]
fn it_passes_through() {
    #[derive(BartDisplay)]
    #[template_string="{{{txt}}}"]
    struct Test<'a> { txt: &'a str }

    assert_eq!(
        "<&\"'",
        format!("{}", Test { txt: "<&\"'" })
    );
}

#[test]
fn it_can_iterate() {
    #[derive(BartDisplay)]
    #[template_string="{{#vec}}{{.}}{{/vec}}"]
    struct Test { vec: Vec<i32> }

    assert_eq!(
        "123",
        format!("{}", Test { vec: vec![1, 2, 3] })
    );
}

#[test]
fn it_can_iterate_option() {
    #[derive(BartDisplay)]
    #[template_string="{{#a}}({{.}}){{/a}}"]
    struct Test { a: Option<i32> }

    assert_eq!(
        "(1)",
        format!("{}", Test { a: Some(1) })
    );

    assert_eq!(
        "",
        format!("{}", Test { a: None })
    );
}

#[test]
fn it_can_iterate_borrowed_slice() {
    #[derive(BartDisplay)]
    #[template_string="{{#slice}}{{.}}{{/slice}}"]
    struct Test<'a> { slice: &'a [i32] }

    assert_eq!(
        "123",
        format!("{}", Test { slice: &[1, 2, 3] })
    );
}

#[test]
fn it_can_access_nested_fields() {
    struct Nested { a: i32 }

    #[derive(BartDisplay)]
    #[template_string="{{nested.a}}"]
    struct Test { nested: Nested }

    assert_eq!(
        "42",
        format!("{}", Test { nested: Nested { a: 42 } })
    );
}

#[test]
fn it_can_scope_into_nested_values() {
    struct Nested { a: i32 }

    #[derive(BartDisplay)]
    #[template_string="{{#nested.}}{{.a}}{{/nested}}"]
    struct Test { nested: Nested }

    assert_eq!(
        "42",
        format!("{}", Test { nested: Nested { a: 42 } })
    );
}

#[test]
fn it_supports_conditional_scope_with_boolean() {
    #[derive(BartDisplay)]
    #[template_string="{{#a?}}yes{{/a}}"]
    struct Test { a: bool }

    assert_eq!(
        "yes",
        format!("{}", Test { a: true })
    );

    assert_eq!(
        "",
        format!("{}", Test { a: false })
    );
}

#[test]
fn it_supports_conditional_scope_with_non_bool() {
    extern crate bart;

    struct TestBool<'a> {
        name: &'a str,
    }

    impl<'a> bart::Conditional for TestBool<'a> {
        fn val(&self) -> bool {
            self.name.len() > 2
        }
    }

    #[derive(BartDisplay)]
    #[template_string="{{cond.name}}: {{#cond?}}Hello {{.name}}{{/cond}}"]
    struct Test<'a> { cond: TestBool<'a> }

    assert_eq!(
        "Joe: Hello Joe",
        format!("{}", Test { cond: TestBool { name: "Joe" } })
    );

    assert_eq!(
        "No: ",
        format!("{}", Test { cond: TestBool { name: "No" } })
    );
}
<commit_msg>Add test demonstrating negative conditional sections. This is a part of #9<commit_after>#[macro_use] extern crate bart_derive;

#[test]
fn it_works() {
    #[derive(BartDisplay)]
    #[template_string="Hello, {{name}}"]
    struct Test { name: String }

    assert_eq!(
        "Hello, World",
        format!("{}", Test { name: "World".to_owned() })
    );
}

#[test]
fn it_handles_names_with_underscore() {
    #[derive(BartDisplay)]
    #[template_string="Hello, {{your_name}}"]
    struct Test { your_name: String }

    assert_eq!(
        "Hello, World",
        format!("{}", Test { your_name: "World".to_owned() })
    );
}

#[test]
fn it_can_borrow() {
    #[derive(BartDisplay)]
    #[template_string="Hello, {{name}}"]
    struct Test<'a> { name: &'a str }

    assert_eq!(
        "Hello, World",
        format!("{}", Test { name: "World" })
    );
}

#[test]
fn it_performs_escaping() {
    #[derive(BartDisplay)]
    #[template_string="{{txt}}"]
    struct Test<'a> { txt: &'a str }

    assert_eq!(
        "<&"'",
        format!("{}", Test { txt: "<&\"'" })
    );
}

#[test]
fn it_passes_through() {
    #[derive(BartDisplay)]
    #[template_string="{{{txt}}}"]
    struct Test<'a> { txt: &'a str }

    assert_eq!(
        "<&\"'",
        format!("{}", Test { txt: "<&\"'" })
    );
}

#[test]
fn it_can_iterate() {
    #[derive(BartDisplay)]
    #[template_string="{{#vec}}{{.}}{{/vec}}"]
    struct Test { vec: Vec<i32> }

    assert_eq!(
        "123",
        format!("{}", Test { vec: vec![1, 2, 3] })
    );
}

#[test]
fn it_can_iterate_option() {
    #[derive(BartDisplay)]
    #[template_string="{{#a}}({{.}}){{/a}}"]
    struct Test { a: Option<i32> }

    assert_eq!(
        "(1)",
        format!("{}", Test { a: Some(1) })
    );

    assert_eq!(
        "",
        format!("{}", Test { a: None })
    );
}

#[test]
fn it_can_iterate_borrowed_slice() {
    #[derive(BartDisplay)]
    #[template_string="{{#slice}}{{.}}{{/slice}}"]
    struct Test<'a> { slice: &'a [i32] }

    assert_eq!(
        "123",
        format!("{}", Test { slice: &[1, 2, 3] })
    );
}

#[test]
fn it_can_access_nested_fields() {
    struct Nested { a: i32 }

    #[derive(BartDisplay)]
    #[template_string="{{nested.a}}"]
    struct Test { nested: Nested }

    assert_eq!(
        "42",
        format!("{}", Test { nested: Nested { a: 42 } })
    );
}

#[test]
fn it_can_scope_into_nested_values() {
    struct Nested { a: i32 }

    #[derive(BartDisplay)]
    #[template_string="{{#nested.}}{{.a}}{{/nested}}"]
    struct Test { nested: Nested }

    assert_eq!(
        "42",
        format!("{}", Test { nested: Nested { a: 42 } })
    );
}

#[test]
fn it_supports_conditional_scope_with_boolean() {
    #[derive(BartDisplay)]
    #[template_string="{{#a?}}yes{{/a}}"]
    struct Test { a: bool }

    assert_eq!(
        "yes",
        format!("{}", Test { a: true })
    );

    assert_eq!(
        "",
        format!("{}", Test { a: false })
    );
}

#[test]
fn it_supports_negative_conditional_scope_with_boolean() {
    #[derive(BartDisplay)]
    #[template_string="{{^a?}}no{{/a}}"]
    struct Test { a: bool }

    assert_eq!(
        "",
        format!("{}", Test { a: true })
    );

    assert_eq!(
        "no",
        format!("{}", Test { a: false })
    );
}

#[test]
fn it_supports_conditional_scope_with_non_bool() {
    extern crate bart;

    struct TestBool<'a> {
        name: &'a str,
    }

    impl<'a> bart::Conditional for TestBool<'a> {
        fn val(&self) -> bool {
            self.name.len() > 2
        }
    }

    #[derive(BartDisplay)]
    #[template_string="{{cond.name}}: {{#cond?}}Hello {{.name}}{{/cond}}"]
    struct Test<'a> { cond: TestBool<'a> }

    assert_eq!(
        "Joe: Hello Joe",
        format!("{}", Test { cond: TestBool { name: "Joe" } })
    );

    assert_eq!(
        "No: ",
        format!("{}", Test { cond: TestBool { name: "No" } })
    );
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use crate::LOG_MESSAGES;
use lazy_static::lazy_static;
use log::{LevelFilter, Log, Metadata};
use ref_thread_local::RefThreadLocal;

struct TestLogger {
    delegate: env_logger::Logger,
}

impl Log for TestLogger {
    #[inline]
    fn enabled(&self, _metadata: &Metadata) -> bool {
        true
    }

    fn log(&self, record: &log::Record) {
        if self.enabled(record.metadata()) {
            LOG_MESSAGES.borrow_mut().push(format!("{}", record.args()));

            self.delegate.log(record);
        }
    }

    fn flush(&self) {}
}

lazy_static! {
    // Lazy static because the Logger has to be 'static
    static ref TEST_LOGGER: TestLogger = TestLogger {
        delegate: env_logger::Builder::from_default_env()
            .filter_level(LevelFilter::Off)
            .parse_default_env()
            .build(),
    };
}

pub fn clear_log_messages() {
    LOG_MESSAGES.borrow_mut().clear();
}

pub fn assert_not_logged(unexpected_message: &str) {
    if let Some(_last_log) = LOG_MESSAGES.borrow().last() {
        panic!(
            "The following log message should not have been logged: '{}'",
            unexpected_message
        );
    }
}

pub fn assert_logged(expected_message: &str) {
    assert_eq!(LOG_MESSAGES.borrow_mut().pop().unwrap(), expected_message);
}

#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn install() {
    log::set_logger(&*TEST_LOGGER)
        .map(|_| log::set_max_level(LevelFilter::Trace))
        .map_err(|err| {
            eprintln!("Failed to set the custom logger: {:?}", err);
        })
        .unwrap();
}
<commit_msg>AVRO-3621: Check the argument of assert_not_logged() against the last logged message before panicing<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use crate::LOG_MESSAGES;
use lazy_static::lazy_static;
use log::{LevelFilter, Log, Metadata};
use ref_thread_local::RefThreadLocal;

struct TestLogger {
    delegate: env_logger::Logger,
}

impl Log for TestLogger {
    #[inline]
    fn enabled(&self, _metadata: &Metadata) -> bool {
        true
    }

    fn log(&self, record: &log::Record) {
        if self.enabled(record.metadata()) {
            LOG_MESSAGES.borrow_mut().push(format!("{}", record.args()));

            self.delegate.log(record);
        }
    }

    fn flush(&self) {}
}

lazy_static! {
    // Lazy static because the Logger has to be 'static
    static ref TEST_LOGGER: TestLogger = TestLogger {
        delegate: env_logger::Builder::from_default_env()
            .filter_level(LevelFilter::Off)
            .parse_default_env()
            .build(),
    };
}

pub fn clear_log_messages() {
    LOG_MESSAGES.borrow_mut().clear();
}

pub fn assert_not_logged(unexpected_message: &str) {
    match LOG_MESSAGES.borrow().last() {
        Some(last_log) if last_log == unexpected_message => panic!(
            "The following log message should not have been logged: '{}'",
            unexpected_message
        ),
        _ => (),
    }
}

pub fn assert_logged(expected_message: &str) {
    assert_eq!(LOG_MESSAGES.borrow_mut().pop().unwrap(), expected_message);
}

#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn install() {
    log::set_logger(&*TEST_LOGGER)
        .map(|_| log::set_max_level(LevelFilter::Trace))
        .map_err(|err| {
            eprintln!("Failed to set the custom logger: {:?}", err);
        })
        .unwrap();
}
<|endoftext|>


<commit_before>use super::{CHUNK_SIZE, HexPillar, PillarIndexComponent};
use std::ops;
use std::iter;
use math::*;

/// Represents one part of the game world.
///
/// A chunk saves `CHUNK_SIZE`² many hex pillars which are arranged rougly in
/// the form of a parallelogram. See [this blog post][1] for more information
/// (the shape is called "rhombus" there).
///
/// This type implements the `Index` trait and can be indexed with an
/// `AxialPoint`.
///
/// [1]: http://www.redblobgames.com/grids/hexagons/#map-storage
pub struct Chunk {
    /// All pillars are layed out in this one dimensional vector which saves
    /// all rows (same r-value) consecutive.
    pillars: Vec<HexPillar>,
}

impl Chunk {
    /// Creates a dummy chunk for early testing. FIXME: remove
    pub fn dummy() -> Self {
        let pillars = iter::repeat(HexPillar::dummy())
            .take(CHUNK_SIZE.pow(2) as usize)
            .collect();
        Chunk { pillars: pillars }
    }

    /// Creates a chunk from a Vector<HexPillar>
    pub fn from_pillars(pillars: Vec<HexPillar>) -> Self {
        assert_eq!(pillars.len(), CHUNK_SIZE.pow(2));

        Chunk { pillars: pillars }
    }

    pub fn pillars(&self) -> &[HexPillar] {
        &self.pillars
    }
    /// Safer method to get through a chunk with an ìndex
    pub fn get(&self, pos: AxialPoint) -> Option<&HexPillar> {
        let chunk_size: PillarIndexComponent = CHUNK_SIZE.into();

        if pos.q >= 0 && pos.q < chunk_size && pos.r >= 0 && pos.r < chunk_size {
            None
        } else {
            Some(&self.pillars[(pos.r as usize) * (CHUNK_SIZE as usize) + (pos.q as usize)])
        }
    }
}

impl ops::Index<AxialPoint> for Chunk {
    type Output = HexPillar;

    fn index(&self, pos: AxialPoint) -> &Self::Output {
        self.get(pos).unwrap_or_else(|| {
            panic!("Index out of Bounds length is: {} index was {:?}",
                   self.pillars.len(),
                   pos)
        })
    }
}
<commit_msg>improve documentation<commit_after>use super::{CHUNK_SIZE, HexPillar, PillarIndexComponent};
use std::ops;
use std::iter;
use math::*;

/// Represents one part of the game world.
///
/// A chunk saves `CHUNK_SIZE`² many hex pillars which are arranged rougly in
/// the form of a parallelogram. See [this blog post][1] for more information
/// (the shape is called "rhombus" there).
///
/// This type implements the `Index` trait and can be indexed with an
/// `AxialPoint`.
///
/// [1]: http://www.redblobgames.com/grids/hexagons/#map-storage
pub struct Chunk {
    /// All pillars are layed out in this one dimensional vector which saves
    /// all rows (same r-value) consecutive.
    pillars: Vec<HexPillar>,
}

impl Chunk {
    /// Creates a dummy chunk for early testing. FIXME: remove
    pub fn dummy() -> Self {
        let pillars = iter::repeat(HexPillar::dummy())
            .take(CHUNK_SIZE.pow(2) as usize)
            .collect();
        Chunk { pillars: pillars }
    }

    /// Creates a chunk from a `Vec<HexPillar>`
    pub fn from_pillars(pillars: Vec<HexPillar>) -> Self {
        assert_eq!(pillars.len(), CHUNK_SIZE.pow(2));

        Chunk { pillars: pillars }
    }

    pub fn pillars(&self) -> &[HexPillar] {
        &self.pillars
    }
    /// Safer method to get through a chunk with an ìndex
    pub fn get(&self, pos: AxialPoint) -> Option<&HexPillar> {
        let chunk_size: PillarIndexComponent = CHUNK_SIZE.into();

        if pos.q >= 0 && pos.q < chunk_size && pos.r >= 0 && pos.r < chunk_size {
            None
        } else {
            Some(&self.pillars[(pos.r as usize) * (CHUNK_SIZE as usize) + (pos.q as usize)])
        }
    }
}

impl ops::Index<AxialPoint> for Chunk {
    type Output = HexPillar;

    fn index(&self, pos: AxialPoint) -> &Self::Output {
        self.get(pos).unwrap_or_else(|| {
            panic!("Index out of Bounds length is: {} index was {:?}",
                   self.pillars.len(),
                   pos)
        })
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;
extern crate rlp;
extern crate sha3;
extern crate generic_array;
extern crate digest;

use self::rlp::*;
use std::collections::HashMap;
use std::iter::Iterator;
use std::fmt::LowerHex;

#[derive(Debug, Serialize, Deserialize)]
enum Node {
    Leaf(Leaf),
    Extension(Extension),
    Full(FullNode),
    Hash(Vec<u8>),
}

#[derive(Debug, Serialize, Deserialize)]
struct FullNode {
    nodes: [Option<Box<Node>>; 16],
    value: Option<Vec<u8>>
}

#[derive(Debug, Serialize, Deserialize)]
struct Leaf {
    path: Vec<u8>,
    value: Vec<u8>,
}

#[derive(Debug, Serialize, Deserialize)]
struct Extension {
    path: Vec<u8>,
    next: Box<Node>,
}

impl Encodable for Node {
    fn rlp_append(&self, s: &mut RlpStream) {
        match self {
            &Node::Hash(ref hash) => {
                s.append_internal(&hash.as_slice());
            }
            &Node::Leaf(ref pair) => {
                s.begin_list(2);
                s.append(&pair.path);
                s.append(&pair.value);
            }
            &Node::Extension(ref ext) => {
                s.begin_list(2);
                s.append(&ext.path);
                s.append(ext.next.as_ref());
            }
            &Node::Full(ref node) => {
                s.begin_list(17);
                for node in &node.nodes {
                    if let &Some(ref node) = node {
                        s.append(node.as_ref());
                    } else {
                        s.append_empty_data();
                    }
                }
                if let Some(ref value) = node.value {
                    s.append(value);
                } else {
                    s.append_empty_data();
                }
            }
        }
    }
}

impl Decodable for Node {
    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
        match rlp.prototype()? {
            Prototype::List(2) => {
                let path = rlp.at(0)?.as_raw();
                if path[0] & 0x20 == 0x20 {
                    return Ok(Node::Leaf(Leaf {
                        path: rlp::decode(path),
                        value: rlp::decode(rlp.at(1)?.as_raw()),
                    }));
                } else if path[0] & 0x20 == 0x00 {
                    return Ok(Node::Extension(Extension {
                        path: rlp::decode(path),
                        next: Box::new(rlp::decode(rlp.at(1)?.as_raw())),
                    }));
                } else {
                    panic!("Incorrect path");
                }
            }
            Prototype::List(17) => {
                let mut nodes: [Option<Box<Node>>; 16] = [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None];
                for i in 0..16 {
                    let cur = rlp.at(i)?;
                    match cur.prototype()? {
                        Prototype::Data(0) => {
                            continue
                        }
                        _ => {
                            nodes[i] = Some(Box::new(rlp::decode(cur.as_raw())));
                        }
                    }
                }
                let mut value: Option<Vec<u8>> = None;
                if !rlp.at(16)?.is_empty() {
                    value = Some(rlp::decode(rlp.at(16)?.as_raw()))
                }
                return Ok(Node::Full(FullNode {
                    nodes: nodes,
                    value: value,
                }));
            }
            Prototype::Data(32) => {
                return Ok(Node::Hash(rlp::decode(rlp.as_raw())));
            }
            _ => panic!("Decode not implemented for {:?}", rlp.prototype())
        }
    }
}

type NodeHash = generic_array::GenericArray<u8, <sha3::Sha3_256 as digest::FixedOutput>::OutputSize>;
type TrieDB<'a> = HashMap<NodeHash, &'a Node>;

impl Node {
    pub fn get_value<'a, 'b>(&'a self, db: &'a TrieDB, path: &'b str) -> Option<Vec<u8>> {
        let nibble_path = Node::path_to_nibbles(path.as_bytes());
        self._get_value(db, nibble_path.as_slice()).map(|v| {
            print_iter_hex(v.iter());
            let mut v = rlp::decode_list(v.as_slice());
            assert_eq!(v.len(), 1);
            v.pop().unwrap()
        })
    }
    fn _get_value<'a, 'b>(&'a self, db: &'a TrieDB, path: &'b [u8]) -> Option<&'a Vec<u8>> {
        println!("{:?}", self);
        match self {
            &Node::Full(ref node) => {
                if path.is_empty() {
                    return node.value.as_ref();
                }
                if let Some(ref next) = node.nodes[path[0] as usize] {
                    return next._get_value(db, &path[1..]);
                }
                return None;
            }
            &Node::Hash(ref hash) => {
                let hash = NodeHash::from_slice(hash.as_slice());
                if let Some(ref next) = db.get(hash) {
                    return next._get_value(db, path);
                }
                return None;
            }
            &Node::Leaf(ref pair) => {
                let (is_leaf, pair_path) = Node::parse_path(pair.path.as_slice());
                if !is_leaf {
                    panic!("Should be leaf");
                }
                if pair_path == path {
                    return Some(&pair.value)
                } else {
                    return None;
                }
            }
            &Node::Extension(ref pair) => {
                let (is_leaf, pair_path) = Node::parse_path(pair.path.as_slice());
                if is_leaf {
                    panic!("Should be extension");
                }
                if path.starts_with(&pair_path) {
                    return pair.next._get_value(db, &path[pair_path.len()..])
                } else {
                    return None;
                }
            }
        }
    }
    fn path_to_nibbles(path: &[u8]) -> Vec<u8> {
        let mut nibble_path: Vec<u8> = Vec::new();
        for s in path {
            nibble_path.push(s >> 4);
            nibble_path.push(s & 0x0F);
        }
        return nibble_path;
    }
    fn parse_path(path: &[u8]) -> (bool, Vec<u8>) {
        let is_leaf: bool = path[0] & 0x20 == 0x20;
        let is_odd: bool = path[0] & 0x10 == 0x10;
        let mut nibbles: Vec<u8> = Node::path_to_nibbles(&path[1..]); //TODO avoid copy
        if is_odd {
            nibbles.insert(0, path[0] & 0x0F);
        }
        return (is_leaf, nibbles)
    }
}

fn print_iter_hex<T, V>(iter: T) where T: Iterator<Item=V>, V: LowerHex {
    for i in iter {
        print!("{:02x} ", i);
    }
    println!();
}

#[cfg(test)]
mod tests {
    use super::*;
    use self::sha3::Digest;
    #[test]
    fn state_proof_works() {
        let str = "f8c0f7808080a0762fc4967c792ef3d22fefd3f43209e2185b25e9a97640f09bb4b61657f67cf3c62084c3827634808080808080808080808080f4808080dd808080c62084c3827631c62084c3827632808080808080808080808080c63384c3827633808080808080808080808080f851808080a0099d752f1d5a4b9f9f0034540153d2d2a7c14c11290f27e5d877b57c801848caa06267640081beb8c77f14f30c68f30688afc3e5d5a388194c6a42f699fe361b2f808080808080808080808080".to_string();
        let mut vec: Vec<u8> = Vec::new();
        for i in 0..str.len() / 2 {
            let x = &str[(i * 2)..(i * 2 + 2)];
            vec.push(u8::from_str_radix(&x, 16).unwrap())
        }
        let rlp = rlp::Rlp::new(vec.as_slice());
        let proofs: Vec<Node> = rlp.as_list();
        println!("Input");
        for rlp in rlp.iter() {
            print_iter_hex(rlp.as_raw().iter());
        }
        println!("parsed");
        let mut map: TrieDB = HashMap::new();
        for node in &proofs {
            println!("{:?}", node);
            let encoded = encode(node);
            print_iter_hex(encoded.iter());
            let mut hasher = sha3::Sha3_256::default();
            hasher.input(encoded.to_vec().as_slice());
            let out = hasher.result();
            print_iter_hex(out.iter());
            map.insert(out, node);
        }
        for k in 33..35 {
            println!("Try get {}", k);
            let x = proofs[2].get_value(&map, k.to_string().as_str());
            println!("{:?}", x.map(String::from_utf8));
        }
    }
}
<commit_msg>Add function state_proof::verify_proof with normal test cases.<commit_after>extern crate serde;
extern crate serde_json;
extern crate rlp;
extern crate sha3;
extern crate generic_array;
extern crate digest;

use self::rlp::*;
use self::sha3::Digest;
use std::collections::HashMap;
use std::fmt::LowerHex;
use std::iter::Iterator;

#[derive(Debug, Serialize, Deserialize)]
enum Node {
    Leaf(Leaf),
    Extension(Extension),
    Full(FullNode),
    Hash(Vec<u8>),
}

#[derive(Debug, Serialize, Deserialize)]
struct FullNode {
    nodes: [Option<Box<Node>>; 16],
    value: Option<Vec<u8>>
}

#[derive(Debug, Serialize, Deserialize)]
struct Leaf {
    path: Vec<u8>,
    value: Vec<u8>,
}

#[derive(Debug, Serialize, Deserialize)]
struct Extension {
    path: Vec<u8>,
    next: Box<Node>,
}

impl Encodable for Node {
    fn rlp_append(&self, s: &mut RlpStream) {
        match self {
            &Node::Hash(ref hash) => {
                s.append_internal(&hash.as_slice());
            }
            &Node::Leaf(ref pair) => {
                s.begin_list(2);
                s.append(&pair.path);
                s.append(&pair.value);
            }
            &Node::Extension(ref ext) => {
                s.begin_list(2);
                s.append(&ext.path);
                s.append(ext.next.as_ref());
            }
            &Node::Full(ref node) => {
                s.begin_list(17);
                for node in &node.nodes {
                    if let &Some(ref node) = node {
                        s.append(node.as_ref());
                    } else {
                        s.append_empty_data();
                    }
                }
                if let Some(ref value) = node.value {
                    s.append(value);
                } else {
                    s.append_empty_data();
                }
            }
        }
    }
}

impl Decodable for Node {
    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
        match rlp.prototype()? {
            Prototype::List(2) => {
                let path = rlp.at(0)?.as_raw();
                if path[0] & 0x20 == 0x20 {
                    return Ok(Node::Leaf(Leaf {
                        path: rlp::decode(path),
                        value: rlp::decode(rlp.at(1)?.as_raw()),
                    }));
                } else if path[0] & 0x20 == 0x00 {
                    return Ok(Node::Extension(Extension {
                        path: rlp::decode(path),
                        next: Box::new(rlp::decode(rlp.at(1)?.as_raw())),
                    }));
                } else {
                    panic!("Incorrect path");
                }
            }
            Prototype::List(17) => {
                let mut nodes: [Option<Box<Node>>; 16] = [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None];
                for i in 0..16 {
                    let cur = rlp.at(i)?;
                    match cur.prototype()? {
                        Prototype::Data(0) => {
                            continue
                        }
                        _ => {
                            nodes[i] = Some(Box::new(rlp::decode(cur.as_raw())));
                        }
                    }
                }
                let mut value: Option<Vec<u8>> = None;
                if !rlp.at(16)?.is_empty() {
                    value = Some(rlp::decode(rlp.at(16)?.as_raw()))
                }
                return Ok(Node::Full(FullNode {
                    nodes: nodes,
                    value: value,
                }));
            }
            Prototype::Data(32) => {
                return Ok(Node::Hash(rlp::decode(rlp.as_raw())));
            }
            _ => panic!("Decode not implemented for {:?}", rlp.prototype())
        }
    }
}

type NodeHash = generic_array::GenericArray<u8, <sha3::Sha3_256 as digest::FixedOutput>::OutputSize>;
type TrieDB<'a> = HashMap<NodeHash, &'a Node>;

impl Node {
    pub fn get_value<'a, 'b>(&'a self, db: &'a TrieDB, path: &'b str) -> Option<Vec<u8>> {
        let nibble_path = Node::path_to_nibbles(path.as_bytes());
        self._get_value(db, nibble_path.as_slice()).map(|v| {
            print_iter_hex(v.iter());
            let mut v = rlp::decode_list(v.as_slice());
            assert_eq!(v.len(), 1);
            v.pop().unwrap()
        })
    }
    fn _get_value<'a, 'b>(&'a self, db: &'a TrieDB, path: &'b [u8]) -> Option<&'a Vec<u8>> {
        println!("{:?}", self);
        match self {
            &Node::Full(ref node) => {
                if path.is_empty() {
                    return node.value.as_ref();
                }
                if let Some(ref next) = node.nodes[path[0] as usize] {
                    return next._get_value(db, &path[1..]);
                }
                return None;
            }
            &Node::Hash(ref hash) => {
                let hash = NodeHash::from_slice(hash.as_slice());
                if let Some(ref next) = db.get(hash) {
                    return next._get_value(db, path);
                } else {
                    panic!("Broken TrieDB");
                }
            }
            &Node::Leaf(ref pair) => {
                let (is_leaf, pair_path) = Node::parse_path(pair.path.as_slice());
                if !is_leaf {
                    panic!("Should be leaf");
                }
                if pair_path == path {
                    return Some(&pair.value);
                } else {
                    return None;
                }
            }
            &Node::Extension(ref pair) => {
                let (is_leaf, pair_path) = Node::parse_path(pair.path.as_slice());
                if is_leaf {
                    panic!("Should be extension");
                }
                if path.starts_with(&pair_path) {
                    return pair.next._get_value(db, &path[pair_path.len()..]);
                } else {
                    return None;
                }
            }
        }
    }
    fn path_to_nibbles(path: &[u8]) -> Vec<u8> {
        let mut nibble_path: Vec<u8> = Vec::new();
        for s in path {
            nibble_path.push(s >> 4);
            nibble_path.push(s & 0x0F);
        }
        return nibble_path;
    }
    fn parse_path(path: &[u8]) -> (bool, Vec<u8>) {
        let is_leaf: bool = path[0] & 0x20 == 0x20;
        let is_odd: bool = path[0] & 0x10 == 0x10;
        let mut nibbles: Vec<u8> = Node::path_to_nibbles(&path[1..]); //TODO avoid copy
        if is_odd {
            nibbles.insert(0, path[0] & 0x0F);
        }
        return (is_leaf, nibbles);
    }
}

fn print_iter_hex<T, V>(iter: T) where T: Iterator<Item=V>, V: LowerHex {
    for i in iter {
        print!("{:02x} ", i);
    }
    println!();
}

pub fn verify_proof(proofs_rlp: &[u8], root_hash: &[u8], key: &str, expected_value: Option<&str>) -> bool {
    let nodes: Vec<Node> = rlp::decode_list(proofs_rlp);
    let mut map: TrieDB = HashMap::new();
    for node in &nodes {
        let encoded = rlp::encode(node);
        let mut hasher = sha3::Sha3_256::default();
        hasher.input(encoded.to_vec().as_slice());
        let hash = hasher.result();
        map.insert(hash, node);
    }
    map.get(root_hash).map(|root| {
        root
            .get_value(&map, key)
            .map_or(Ok(None), |value| {
                String::from_utf8(value).map(Some)
            })
            .map(|value| value.eq(&expected_value.map(String::from)))
            .unwrap_or(false)
    }).unwrap_or(false)
}

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

    fn hex_str_to_bytes(hex_str: &str) -> Vec<u8> {
        let mut vec: Vec<u8> = Vec::new();
        for i in 0..hex_str.len() / 2 {
            let x = &hex_str[(i * 2)..(i * 2 + 2)];
            vec.push(u8::from_str_radix(&x, 16).unwrap())
        }
        return vec;
    }

    #[test]
    fn state_proof_works() {
        let str = "f8c0f7808080a0762fc4967c792ef3d22fefd3f43209e2185b25e9a97640f09bb4b61657f67cf3c62084c3827634808080808080808080808080f4808080dd808080c62084c3827631c62084c3827632808080808080808080808080c63384c3827633808080808080808080808080f851808080a0099d752f1d5a4b9f9f0034540153d2d2a7c14c11290f27e5d877b57c801848caa06267640081beb8c77f14f30c68f30688afc3e5d5a388194c6a42f699fe361b2f808080808080808080808080";
        let vec = hex_str_to_bytes(str);
        let rlp = rlp::Rlp::new(vec.as_slice());
        let proofs: Vec<Node> = rlp.as_list();
        println!("Input");
        for rlp in rlp.iter() {
            print_iter_hex(rlp.as_raw().iter());
        }
        println!("parsed");
        let mut map: TrieDB = HashMap::new();
        for node in &proofs {
            println!("{:?}", node);
            let encoded = encode(node);
            print_iter_hex(encoded.iter());
            let mut hasher = sha3::Sha3_256::default();
            hasher.input(encoded.to_vec().as_slice());
            let out = hasher.result();
            print_iter_hex(out.iter());
            map.insert(out, node);
        }
        for k in 33..35 {
            println!("Try get {}", k);
            let x = proofs[2].get_value(&map, k.to_string().as_str());
            println!("{:?}", x.map(String::from_utf8));
        }
    }

    #[test]
    fn state_proof_verify_proof_works_for_get_value_from_leaf() {
        /*
            '33' -> 'v1'
            '34' -> 'v2'
            '3C' -> 'v3'
            '4'  -> 'v4'
            'D'  -> 'v5asdfasdf'
            'E'  -> 'v6fdsfdfs'
        */
        let proofs = hex_str_to_bytes("f8c0f7808080a0762fc4967c792ef3d22fefd3f43209e2185b25e9a97640f09bb4b61657f67cf3c62084c3827634808080808080808080808080f4808080dd808080c62084c3827631c62084c3827632808080808080808080808080c63384c3827633808080808080808080808080f851808080a0099d752f1d5a4b9f9f0034540153d2d2a7c14c11290f27e5d877b57c801848caa06267640081beb8c77f14f30c68f30688afc3e5d5a388194c6a42f699fe361b2f808080808080808080808080");
        let root_hash = hex_str_to_bytes("badc906111df306c6afac17b62f29792f0e523b67ba831651d6056529b6bf690");
        assert!(verify_proof(proofs.as_slice(), root_hash.as_slice(), "33", Some("v1")));
        assert!(verify_proof(proofs.as_slice(), root_hash.as_slice(), "34", Some("v2")));
        assert!(verify_proof(proofs.as_slice(), root_hash.as_slice(), "3C", Some("v3")));
        assert!(verify_proof(proofs.as_slice(), root_hash.as_slice(), "4", Some("v4")));
    }

    #[test]
    fn state_proof_verify_proof_works_for_get_value_from_leaf_through_extension() {
        /*
            '33'  -> 'v1'
            'D'   -> 'v2'
            'E'   -> 'v3'
            '333' -> 'v4'
            '334' -> 'v5'
        */
        let proofs = hex_str_to_bytes("f8a8e4821333a05fff9765fa0c56a26b361c81b7883478da90259d0c469896e8da7edd6ad7c756f2808080dd808080c62084c3827634c62084c382763580808080808080808080808080808080808080808080808084c3827631f84e808080a06a4096e59e980d2f2745d0ed2d1779eb135a1831fd3763f010316d99fd2adbb3dd80808080c62084c3827632c62084c38276338080808080808080808080808080808080808080808080");
        let root_hash = hex_str_to_bytes("d01bd87a6105a945c5eb83e328489390e2843a9b588f03d222ab1a51db7b9fab");
        assert!(verify_proof(proofs.as_slice(), root_hash.as_slice(), "333", Some("v4")));
    }

    #[test]
    fn state_proof_verify_proof_works_for_get_value_from_full_node() {
        /*
            '33'  -> 'v1'
            'D'   -> 'v2'
            'E'   -> 'v3'
            '333' -> 'v4'
            '334' -> 'v5'
        */
        let proofs = hex_str_to_bytes("f8a8e4821333a05fff9765fa0c56a26b361c81b7883478da90259d0c469896e8da7edd6ad7c756f2808080dd808080c62084c3827634c62084c382763580808080808080808080808080808080808080808080808084c3827631f84e808080a06a4096e59e980d2f2745d0ed2d1779eb135a1831fd3763f010316d99fd2adbb3dd80808080c62084c3827632c62084c38276338080808080808080808080808080808080808080808080");
        let root_hash = hex_str_to_bytes("d01bd87a6105a945c5eb83e328489390e2843a9b588f03d222ab1a51db7b9fab");
        assert!(verify_proof(proofs.as_slice(), root_hash.as_slice(), "33", Some("v1")));
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use glium::{self, DrawParameters, IndexBuffer, Program, VertexBuffer};
use glium::index::PrimitiveType;
use GameContext;
use Camera;
use glium::draw_parameters::DepthTest;
use util::ToArr;
use base::math::*;
use noise::{PermutationTable, open_simplex2, open_simplex3};
use rand::Rand;
use base::gen::seeded_rng;
use glium::texture::Texture2d;

pub struct SkyView {
    vertex_buffer: VertexBuffer<Vertex>,
    index_buffer: IndexBuffer<u32>,
    program: Program,
    sun_position: Point3f,
    star_map: Texture2d,
}

impl SkyView {
    pub fn new(context: Rc<GameContext>) -> Self {
        const SKYDOME_SIZE: f32 = 1000.0;
        let raw_vertex_buffer = vec![
            // a: part of xy-plane
            Vertex { i_position: [0.0, -SKYDOME_SIZE, 0.0], i_unit_coords: [0.0, -1.0, 0.0]},
            // b: part of xy-plane
            Vertex { i_position: [SKYDOME_SIZE, 0.0, 0.0], i_unit_coords: [1.0, 0.0, 0.0]},
            // c: part of xy-plane
            Vertex { i_position: [0.0, SKYDOME_SIZE, 0.0], i_unit_coords: [0.0, 1.0, 0.0]},
            // d: part of xy-plane
            Vertex { i_position: [-SKYDOME_SIZE, 0.0, 0.0], i_unit_coords: [-1.0, 0.0, 0.0]},
            // e: peak of lower hemisphere
            Vertex { i_position: [0.0, 0.0, -SKYDOME_SIZE], i_unit_coords: [0.0, 0.0, -1.0]},
            // f: peak of upper hemisphere
            Vertex { i_position: [0.0, 0.0, SKYDOME_SIZE], i_unit_coords: [0.0, 0.0, 1.0]},
        ];

        let vbuf = VertexBuffer::new(context.get_facade(), &raw_vertex_buffer).unwrap();

        // Indices
        // Index-Buffer corresponds to the planes of the octaeder
        // [a, b, e] [b, c, e] [c, d, e] [d, a, e] [b, a, f] [a, d, f] [d, c, f] [c, b,
        // f]
        let raw_index_buffer = [0, 1, 4, 1, 2, 4, 2, 3, 4, 3, 0, 4, 1, 0, 5, 0, 3, 5, 3, 2, 5, 2,
                                1, 5]; //TrianglesList
        let ibuf = IndexBuffer::new(context.get_facade(),
                                    PrimitiveType::TrianglesList,
                                    &raw_index_buffer)
            .unwrap();

        let seed = 54342354434;
        let mut star_rng = seeded_rng(seed, 0, ());
        let mut star_table = PermutationTable::rand(&mut star_rng);

        // values between 0 and 0.5
        const TEX_SIZE: usize = 3000;
        let mut v = vec![Vec::new(); TEX_SIZE];

        for i in 0..TEX_SIZE {
            for j in 0..TEX_SIZE * 2 {
                v[i].push((open_simplex2::<f32>(&star_table,
                                                &[(i as f32) * 0.1, (j as f32) * 0.1]) +
                           0.6) / 2.0);
            }
        }

        SkyView {
            vertex_buffer: vbuf,
            index_buffer: ibuf,
            program: context.load_program("skydome").unwrap(),
            sun_position: Point3f::new(0.0, 0.0, -1000.0),
            star_map: match Texture2d::new(context.get_facade(), v) {
                Ok(p) => p,
                Err(_) => panic!("Could not load stars"),
            },
        }
    }

    pub fn draw_skydome<S: glium::Surface>(&self, surface: &mut S, camera: &Camera) {

        let pos = Point3::new(0.0, 0.0, 0.0);

        // skydome-octaeder position is set to camera position
        let view_matrix =
            Matrix4::look_at(pos, pos + camera.get_look_at_vector(), Vector3::unit_z());

        let uniforms = uniform! {
            u_proj_matrix: camera.proj_matrix().to_arr(),
            u_view_matrix: view_matrix.to_arr(),
            u_sun_pos: self.sun_position.to_arr(),
            u_star_map: &self.star_map,
        };
        let params = DrawParameters {
            depth: glium::Depth {
                write: false,
                test: DepthTest::IfLess,
                ..Default::default()
            },
            ..Default::default()
        };

        surface.draw(&self.vertex_buffer,
                  &self.index_buffer,
                  &self.program,
                  &uniforms,
                  &params)
            .unwrap();
    }

    pub fn update(&mut self, pos: Point3f) {
        self.sun_position = pos;
    }
}

/// Vertex type used to render chunks (or hex pillars).
#[derive(Debug, Copy, Clone)]
struct Vertex {
    pub i_position: [f32; 3],
    pub i_unit_coords: [f32; 3],
}

implement_vertex!(Vertex, i_position, i_unit_coords);
<commit_msg>fix warnings<commit_after>use std::rc::Rc;
use glium::{self, DrawParameters, IndexBuffer, Program, VertexBuffer};
use glium::index::PrimitiveType;
use GameContext;
use Camera;
use glium::draw_parameters::DepthTest;
use util::ToArr;
use base::math::*;
use noise::{PermutationTable, open_simplex2};
use rand::Rand;
use base::gen::seeded_rng;
use glium::texture::Texture2d;

pub struct SkyView {
    vertex_buffer: VertexBuffer<Vertex>,
    index_buffer: IndexBuffer<u32>,
    program: Program,
    sun_position: Point3f,
    star_map: Texture2d,
}

impl SkyView {
    pub fn new(context: Rc<GameContext>) -> Self {
        const SKYDOME_SIZE: f32 = 1000.0;
        let raw_vertex_buffer = vec![
            // a: part of xy-plane
            Vertex { i_position: [0.0, -SKYDOME_SIZE, 0.0], i_unit_coords: [0.0, -1.0, 0.0]},
            // b: part of xy-plane
            Vertex { i_position: [SKYDOME_SIZE, 0.0, 0.0], i_unit_coords: [1.0, 0.0, 0.0]},
            // c: part of xy-plane
            Vertex { i_position: [0.0, SKYDOME_SIZE, 0.0], i_unit_coords: [0.0, 1.0, 0.0]},
            // d: part of xy-plane
            Vertex { i_position: [-SKYDOME_SIZE, 0.0, 0.0], i_unit_coords: [-1.0, 0.0, 0.0]},
            // e: peak of lower hemisphere
            Vertex { i_position: [0.0, 0.0, -SKYDOME_SIZE], i_unit_coords: [0.0, 0.0, -1.0]},
            // f: peak of upper hemisphere
            Vertex { i_position: [0.0, 0.0, SKYDOME_SIZE], i_unit_coords: [0.0, 0.0, 1.0]},
        ];

        let vbuf = VertexBuffer::new(context.get_facade(), &raw_vertex_buffer).unwrap();

        // Indices
        // Index-Buffer corresponds to the planes of the octaeder
        // [a, b, e] [b, c, e] [c, d, e] [d, a, e] [b, a, f] [a, d, f] [d, c, f] [c, b,
        // f]
        let raw_index_buffer = [0, 1, 4, 1, 2, 4, 2, 3, 4, 3, 0, 4, 1, 0, 5, 0, 3, 5, 3, 2, 5, 2,
                                1, 5]; //TrianglesList
        let ibuf = IndexBuffer::new(context.get_facade(),
                                    PrimitiveType::TrianglesList,
                                    &raw_index_buffer)
            .unwrap();

        let seed = 54342354434;
        let mut star_rng = seeded_rng(seed, 0, ());
        let star_table = PermutationTable::rand(&mut star_rng);

        // values between 0 and 0.5
        const TEX_SIZE: usize = 3000;
        let mut v = vec![Vec::new(); TEX_SIZE];

        for i in 0..TEX_SIZE {
            for j in 0..TEX_SIZE * 2 {
                v[i].push((open_simplex2::<f32>(&star_table,
                                                &[(i as f32) * 0.1, (j as f32) * 0.1]) +
                           0.6) / 2.0);
            }
        }

        SkyView {
            vertex_buffer: vbuf,
            index_buffer: ibuf,
            program: context.load_program("skydome").unwrap(),
            sun_position: Point3f::new(0.0, 0.0, -1000.0),
            star_map: match Texture2d::new(context.get_facade(), v) {
                Ok(p) => p,
                Err(_) => panic!("Could not load stars"),
            },
        }
    }

    pub fn draw_skydome<S: glium::Surface>(&self, surface: &mut S, camera: &Camera) {

        let pos = Point3::new(0.0, 0.0, 0.0);

        // skydome-octaeder position is set to camera position
        let view_matrix =
            Matrix4::look_at(pos, pos + camera.get_look_at_vector(), Vector3::unit_z());

        let uniforms = uniform! {
            u_proj_matrix: camera.proj_matrix().to_arr(),
            u_view_matrix: view_matrix.to_arr(),
            u_sun_pos: self.sun_position.to_arr(),
            u_star_map: &self.star_map,
        };
        let params = DrawParameters {
            depth: glium::Depth {
                write: false,
                test: DepthTest::IfLess,
                ..Default::default()
            },
            ..Default::default()
        };

        surface.draw(&self.vertex_buffer,
                  &self.index_buffer,
                  &self.program,
                  &uniforms,
                  &params)
            .unwrap();
    }

    pub fn update(&mut self, pos: Point3f) {
        self.sun_position = pos;
    }
}

/// Vertex type used to render chunks (or hex pillars).
#[derive(Debug, Copy, Clone)]
struct Vertex {
    pub i_position: [f32; 3],
    pub i_unit_coords: [f32; 3],
}

implement_vertex!(Vertex, i_position, i_unit_coords);
<|endoftext|>


<commit_before>#![feature(plugin)]
#![no_std]
#![plugin(macro_zinc)]

extern crate zinc;

#[zinc_main]
fn main() {
  use core::option::Option;
  use zinc::hal::pin::Gpio;
  use zinc::hal::stm32f1::{init, pin, timer};
  use zinc::hal::timer::Timer;
  zinc::hal::mem_init::init_stack();
  zinc::hal::mem_init::init_data();

  let sys_clock = init::ClockConfig::new_default();
  //sys_clock.setup();

  let led1 = pin::Pin::new(pin::Port::PortC, 13, pin::PinConf::OutPushPull50MHz);

  // TODO(kvark): why doesn't "sys_clock.get_apb1_frequency()" work better?
  let timer_clock = sys_clock.source.frequency();
  let timer = timer::Timer::new(timer::TimerPeripheral::Timer2, timer_clock/1000, 0);

  loop {
    led1.set_high();
    timer.wait_ms(1);
    led1.set_low();
    timer.wait_ms(1);
  }
}
<commit_msg>stm32f1-example: for SYSCLK use PLL fed by HSI<commit_after>#![feature(plugin)]
#![no_std]
#![plugin(macro_zinc)]

extern crate zinc;

#[zinc_main]
fn main() {
  use core::option::Option;
  use zinc::hal::pin::Gpio;
  use zinc::hal::stm32f1::{init, pin, timer};
  use zinc::hal::timer::Timer;
  zinc::hal::mem_init::init_stack();
  zinc::hal::mem_init::init_data();

   // configure PLL and set it as System Clock source
  let pll_conf = init::PllConf {
    source: init::PllClockSource::PllSourceHSIDiv2,
    mult: init::PllMult::PllMul12,
    hse_prediv: init::PllHsePrediv::PllHsePrediv1,
    usb_prescaler: init::PllUsbDiv::PllUsbDiv1,
  };
  let sys_clock = init::ClockConfig {
      source:         init::SystemClockSource::SystemClockPLL(pll_conf),
      ahb_prescaler:  init::ClockAhbPrescaler::AhbDivNone,
      apb1_prescaler: init::ClockApbPrescaler::ApbDiv2,
      apb2_prescaler: init::ClockApbPrescaler::ApbDivNone,
      flash_latency:  init::FlashLatency::FlashLatency1,
      mco:            init::McoSource::McoClockPLL,
  };
  sys_clock.setup();

  let led1 = pin::Pin::new(pin::Port::PortC, 13, pin::PinConf::OutPushPull50MHz);

  // TODO(kvark): why doesn't "sys_clock.get_apb1_frequency()" work better?
  let timer_clock = sys_clock.source.frequency();
  let timer = timer::Timer::new(timer::TimerPeripheral::Timer2, timer_clock/1000, 0);

  loop {
    led1.set_high();
    timer.wait_ms(1);
    led1.set_low();
    timer.wait_ms(1);
  }
}
<|endoftext|>


<commit_before>use std::ops::{Add, Mul, Sub, Neg, Index, IndexMut};

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Point(pub i32, pub i32);
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Size(pub i32, pub i32);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Move(pub i32, pub i32);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Rotation(i32, i32, i32, i32);

impl Move {
    pub const UP:    Move = Move(-1, 0);
    pub const RIGHT: Move = Move(0, 1);
    pub const DOWN:  Move = Move(1, 0);
    pub const LEFT:  Move = Move(0, -1);

    pub const ALL_DIRECTIONS: [Move; 4] = [
        Move::UP, Move::RIGHT, Move::DOWN, Move::LEFT
    ];
}

impl Add<Move> for Point {
    type Output = Point;

    #[inline]
    fn add(self, other: Move) -> Point {
        Point(self.0 + other.0, self.1 + other.1)
    }
}

impl Sub<Point> for Point {
    type Output = Move;

    #[inline]
    fn sub(self, other: Point) -> Move {
        Move(self.0 - other.0, self.1 - other.1)
    }
}

impl Add<Move> for Move {
    type Output = Move;

    #[inline]
    fn add(self, other: Move) -> Move {
        Move(self.0 + other.0, self.1 + other.1)
    }
}

impl Sub<Move> for Move {
    type Output = Move;

    #[inline]
    fn sub(self, other: Move) -> Move {
        Move(self.0 - other.0, self.1 - other.1)
    }
}

impl Neg for Move {
    type Output = Move;

    #[inline]
    fn neg(self) -> Move {
        Move(-self.0, -self.1)
    }
}

impl Mul<i32> for Move {
    type Output = Move;

    #[inline]
    fn mul(self, other: i32) -> Move {
        Move(self.0 * other, self.1 * other)
    }
}

impl Rotation {
    pub const UCW0:   Rotation = Rotation( 1,  0,  0,  1);
    pub const UCW90:  Rotation = Rotation( 0, -1,  1,  0);
    pub const UCW180: Rotation = Rotation(-1,  0,  0, -1);
    pub const UCW270: Rotation = Rotation( 0,  1, -1,  0);
    pub const H_FLIP: Rotation = Rotation( 1,  0,  0, -1);
    pub const V_FLIP: Rotation = Rotation(-1,  0,  0,  1);
}

impl Mul<Rotation> for Rotation {
    type Output = Rotation;

    #[inline]
    fn mul(self, other: Rotation) -> Rotation {
        Rotation(self.0 * other.0 + self.1 * other.2,
                 self.0 * other.1 + self.1 * other.3,
                 self.2 * other.0 + self.3 * other.2,
                 self.2 * other.1 + self.3 * other.3)
    }
}

impl Mul<Move> for Rotation {
    type Output = Move;

    #[inline]
    fn mul(self, other: Move) -> Move {
        Move(self.0 * other.0 + self.1 * other.1,
             self.2 * other.0 + self.3 * other.1)
    }
}

pub trait Geom {
    #[inline]
    fn size(&self) -> Size;
    #[inline]
    fn row(&self) -> i32 { self.size().0 }
    #[inline]
    fn column(&self) -> i32 { self.size().1 }

    #[inline]
    fn contains(&self, p: Point) -> bool {
        let size = self.size();
        0 <= p.0 && p.0 < size.0 &&
            0 <= p.1 && p.1 < size.1
    }

    #[inline]
    fn point_to_index(&self, p: Point) -> usize {
        (p.0 * self.column() + p.1) as usize
    }
    #[inline]
    fn index_to_point(&self, idx: usize) -> Point {
        Point((idx as i32) / self.column(), (idx as i32) % self.column())
    }
}

impl Geom for Size {
    #[inline]
    fn size(&self) -> Size { *self }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Matrix<T> {
    size: Size,
    outside: T,
    data: Vec<T>
}

impl<T> Matrix<T> {
    #[inline]
    pub fn new(size: Size, outside: T, data: Vec<T>) -> Matrix<T> {
        assert_eq!((size.0 * size.1) as usize, data.len());
        Matrix {
            size: size, outside: outside, data: data
        }
    }

    #[inline]
    pub fn new_empty(size: Size, outside: T, init: T) -> Matrix<T>
        where T: Clone
    {
        let data = vec![init; (size.0 * size.1) as usize];
        Matrix::new(size, outside, data)
    }
}

impl<T> Geom for Matrix<T> {
    #[inline]
    fn size(&self) -> Size { self.size }
}

impl<T> Index<Point> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, p: Point) -> &T {
        if self.contains(p) {
            &self.data[self.point_to_index(p)]
        } else {
            &self.outside
        }
    }
}

impl<T> IndexMut<Point> for Matrix<T> {
    #[inline]
    fn index_mut(&mut self, p: Point) -> &mut T {
        assert!(self.contains(p));
        let idx = self.point_to_index(p);
        &mut self.data[idx]
    }
}

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

    #[test]
    fn rotate_mat() {
        let mat = [Rotation::UCW0, Rotation::UCW90, Rotation::UCW180, Rotation::UCW270];
        for i in (0 .. mat.len()) {
            for j in (0 .. mat.len()) {
                assert_eq!(mat[(i + j) % mat.len()], mat[i] * mat[j]);
            }
        }
    }

    #[test]
    fn rotate_point() {
        let mat = [Rotation::UCW0, Rotation::UCW90, Rotation::UCW180, Rotation::UCW270];
        let vec = [[Move::UP, Move::LEFT, Move::DOWN, Move::RIGHT],
                   [Move::UP + Move::RIGHT, Move::LEFT + Move::UP, Move::DOWN + Move::LEFT, Move::RIGHT + Move::DOWN]];
        for i in 0 .. mat.len() {
            for v in &vec {
                for j in (0 .. v.len()) {
                    assert_eq!(v[(i + j) % v.len()], mat[i] * v[j]);
                }
            }
        }
    }
}
<commit_msg>core: Fast index operation<commit_after>use std::ops::{Add, Mul, Sub, Neg, Index, IndexMut};

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct Point(pub i32, pub i32);
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Size(pub i32, pub i32);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Move(pub i32, pub i32);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Rotation(i32, i32, i32, i32);

impl Move {
    pub const UP:    Move = Move(-1, 0);
    pub const RIGHT: Move = Move(0, 1);
    pub const DOWN:  Move = Move(1, 0);
    pub const LEFT:  Move = Move(0, -1);

    pub const ALL_DIRECTIONS: [Move; 4] = [
        Move::UP, Move::RIGHT, Move::DOWN, Move::LEFT
    ];
}

impl Add<Move> for Point {
    type Output = Point;

    #[inline]
    fn add(self, other: Move) -> Point {
        Point(self.0 + other.0, self.1 + other.1)
    }
}

impl Sub<Point> for Point {
    type Output = Move;

    #[inline]
    fn sub(self, other: Point) -> Move {
        Move(self.0 - other.0, self.1 - other.1)
    }
}

impl Add<Move> for Move {
    type Output = Move;

    #[inline]
    fn add(self, other: Move) -> Move {
        Move(self.0 + other.0, self.1 + other.1)
    }
}

impl Sub<Move> for Move {
    type Output = Move;

    #[inline]
    fn sub(self, other: Move) -> Move {
        Move(self.0 - other.0, self.1 - other.1)
    }
}

impl Neg for Move {
    type Output = Move;

    #[inline]
    fn neg(self) -> Move {
        Move(-self.0, -self.1)
    }
}

impl Mul<i32> for Move {
    type Output = Move;

    #[inline]
    fn mul(self, other: i32) -> Move {
        Move(self.0 * other, self.1 * other)
    }
}

impl Rotation {
    pub const UCW0:   Rotation = Rotation( 1,  0,  0,  1);
    pub const UCW90:  Rotation = Rotation( 0, -1,  1,  0);
    pub const UCW180: Rotation = Rotation(-1,  0,  0, -1);
    pub const UCW270: Rotation = Rotation( 0,  1, -1,  0);
    pub const H_FLIP: Rotation = Rotation( 1,  0,  0, -1);
    pub const V_FLIP: Rotation = Rotation(-1,  0,  0,  1);
}

impl Mul<Rotation> for Rotation {
    type Output = Rotation;

    #[inline]
    fn mul(self, other: Rotation) -> Rotation {
        Rotation(self.0 * other.0 + self.1 * other.2,
                 self.0 * other.1 + self.1 * other.3,
                 self.2 * other.0 + self.3 * other.2,
                 self.2 * other.1 + self.3 * other.3)
    }
}

impl Mul<Move> for Rotation {
    type Output = Move;

    #[inline]
    fn mul(self, other: Move) -> Move {
        Move(self.0 * other.0 + self.1 * other.1,
             self.2 * other.0 + self.3 * other.1)
    }
}

pub trait Geom {
    #[inline]
    fn size(&self) -> Size;
    #[inline]
    fn row(&self) -> i32 { self.size().0 }
    #[inline]
    fn column(&self) -> i32 { self.size().1 }

    #[inline]
    fn contains(&self, p: Point) -> bool {
        let size = self.size();
        0 <= p.0 && p.0 < size.0 &&
            0 <= p.1 && p.1 < size.1
    }

    #[inline]
    fn point_to_index(&self, p: Point) -> usize {
        (p.0 * self.column() + p.1) as usize
    }
    #[inline]
    fn index_to_point(&self, idx: usize) -> Point {
        Point((idx as i32) / self.column(), (idx as i32) % self.column())
    }
}

impl Geom for Size {
    #[inline]
    fn size(&self) -> Size { *self }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Matrix<T> {
    size: Size,
    outside: T,
    data: Vec<T>
}

impl<T> Matrix<T> {
    #[inline]
    pub fn new(size: Size, outside: T, data: Vec<T>) -> Matrix<T> {
        assert_eq!((size.0 * size.1) as usize, data.len());
        Matrix {
            size: size, outside: outside, data: data
        }
    }

    #[inline]
    pub fn new_empty(size: Size, outside: T, init: T) -> Matrix<T>
        where T: Clone
    {
        let data = vec![init; (size.0 * size.1) as usize];
        Matrix::new(size, outside, data)
    }
}

impl<T> Geom for Matrix<T> {
    #[inline]
    fn size(&self) -> Size { self.size }
}

impl<T> Index<Point> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, p: Point) -> &T {
        unsafe {
            if self.contains(p) {
                let idx = self.point_to_index(p);
                self.data.get_unchecked(idx)
            } else {
                &self.outside
            }
        }
    }
}

impl<T> IndexMut<Point> for Matrix<T> {
    #[inline]
    fn index_mut(&mut self, p: Point) -> &mut T {
        unsafe {
            assert!(self.contains(p));
            let idx = self.point_to_index(p);
            self.data.get_unchecked_mut(idx)
        }
    }
}

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

    #[test]
    fn rotate_mat() {
        let mat = [Rotation::UCW0, Rotation::UCW90, Rotation::UCW180, Rotation::UCW270];
        for i in (0 .. mat.len()) {
            for j in (0 .. mat.len()) {
                assert_eq!(mat[(i + j) % mat.len()], mat[i] * mat[j]);
            }
        }
    }

    #[test]
    fn rotate_point() {
        let mat = [Rotation::UCW0, Rotation::UCW90, Rotation::UCW180, Rotation::UCW270];
        let vec = [[Move::UP, Move::LEFT, Move::DOWN, Move::RIGHT],
                   [Move::UP + Move::RIGHT, Move::LEFT + Move::UP, Move::DOWN + Move::LEFT, Move::RIGHT + Move::DOWN]];
        for i in 0 .. mat.len() {
            for v in &vec {
                for j in (0 .. v.len()) {
                    assert_eq!(v[(i + j) % v.len()], mat[i] * v[j]);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::async::Server;

use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};
use futures_cpupool::CpuPool;

use std::sync::{RwLock, Arc};
use std::thread;
use std::rc::Rc;
use std::fmt::Debug;
use std::time::Duration;
use std::ops::Deref;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let remote = core.remote();
    let server = Server::bind("localhost:8081", &handle).unwrap();
    let pool = Rc::new(CpuPool::new_num_cpus());
    let connections = Arc::new(RwLock::new(Vec::new()));
    let state = Arc::new(RwLock::new(State::new()));
    let (read_channel_out, read_channel_in) = futures::sync::mpsc::unbounded();
    let (write_channel_out, write_channel_in) = futures::sync::mpsc::unbounded();
    let handle_inner = handle.clone();
    let connection_handler = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(move |(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle_inner);
                return Ok(());
            }
            let read_channel_out = read_channel_out.clone();
            let write_channel_out = write_channel_out.clone();
            upgrade
                .use_protocol("rust-websocket")
                .accept()
                .and_then(move |(framed, _)| {
                    let (sink, stream) = framed.split();
                    read_channel_out.send(stream).wait().unwrap();
                    write_channel_out.send(sink).wait().unwrap();
                    Ok(())
                })
                .wait()
                .unwrap();
            Ok(())
        })
        .map_err(|_| ());

    let state_read = state.clone();
    let remote_write = remote.clone();
    let read_handler = pool.spawn_fn( || {
        read_channel_in.for_each(move |stream| {
            let state_read = state_read.clone();
            remote_write.spawn(|_| {
                stream
                    .for_each(move |msg|{
                        handle_incoming(&mut state_read.write().unwrap(), &msg);
                        Ok(())
                    })
                    .map_err(|_| ())
            });
            Ok(())
        })
    });

    let connections_inner = connections.clone();
    let write_handler = pool.spawn_fn(move || {
        write_channel_in.for_each(move |sink| {
            let (write_out, write_in) = futures::sync::mpsc::unbounded();
            connections_inner.write().unwrap().push(write_out);
            remote.spawn(move |_| {
                let send = sink.send(OwnedMessage::Text("Connection established".to_owned()));
                write_in.fold(send, move |send, state:Arc<RwLock<State>>|{
                    let msg = serde_json::to_string(&state.read().unwrap().deref()).unwrap();
                    println!("Sending message: {}", msg);
                    let send = send.wait().unwrap().send(OwnedMessage::Text(msg));
                    Ok(send)
                }).map(|_| ())
            });
            Ok(())
        })
    });

    let game_loop = pool.spawn_fn(move || {
         future::loop_fn(connections, move |connections| {
                thread::sleep(Duration::from_millis(100));
                for conn in connections.write().unwrap().iter() {
                    let state = state.clone();
                    conn.send(state).unwrap();
                }
                match 1 {
                    1=>Ok(Loop::Continue(connections)),
                    2=>Ok(Loop::Break(())),
                    _=>Err(())
                }
        })
    });

    let handlers = game_loop.select2(connection_handler.select2(read_handler.select(write_handler)));
    core.run(handlers).map_err(|_| println!("err")).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State { msg: "git gud".to_string() }
    }
}
<commit_msg>Core: Change send to work individually per connection<commit_after>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::async::Server;

use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};
use futures_cpupool::CpuPool;

use std::sync::{RwLock, Arc, Mutex};
use std::thread;
use std::rc::Rc;
use std::fmt::Debug;
use std::time::Duration;
use std::ops::Deref;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let remote = core.remote();
    let server = Server::bind("localhost:8081", &handle).unwrap();
    let pool = Rc::new(CpuPool::new_num_cpus());
    let connections = Arc::new(RwLock::new(Vec::new()));
    let state = Arc::new(RwLock::new(State::new()));
    let (read_channel_out, read_channel_in) = futures::sync::mpsc::unbounded();
    let handle_inner = handle.clone();
    let connections_inner = connections.clone();
    let connection_handler = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(move |(upgrade, addr)| {
            let connections = connections_inner.clone();
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle_inner);
                return Ok(());
            }
            let read_channel_out = read_channel_out.clone();
            upgrade
                .use_protocol("rust-websocket")
                .accept()
                .and_then(move |(framed, _)| {
                    let (sink, stream) = framed.split();
                    read_channel_out.send(stream).wait().unwrap();
                    connections.write().unwrap().push(Arc::new(RwLock::new(sink)));
                    Ok(())
                })
                .wait()
                .unwrap();
            Ok(())
        })
        .map_err(|_| ());

    let state_read = state.clone();
    let remote_write = remote.clone();
    let read_handler = pool.spawn_fn(|| {
        read_channel_in.for_each(move |stream| {
            let state_read = state_read.clone();
            remote_write.spawn(|_| {
                stream.for_each(move |msg| {
                                    handle_incoming(&mut state_read.write().unwrap(), &msg);
                                    Ok(())
                                })
                    .map_err(|_| ())
            });
            Ok(())
        })
    });

    let connections_inner = connections.clone();
    let (write_channel_out, write_channel_in) = futures::sync::mpsc::unbounded();

    type MessageCodec = websocket::async::MessageCodec<OwnedMessage>;
    type Framed = websocket::client::async::Framed<tokio_core::net::TcpStream, MessageCodec>;
    type SplitSink = futures::stream::SplitSink<Framed>;
    let write_handler = pool.spawn_fn(move || {
        write_channel_in.for_each(move |(sink, state): (Arc<RwLock<SplitSink>>,
                                                        Arc<RwLock<State>>)| {
                let msg = serde_json::to_string(state.read().unwrap().deref()).unwrap();
                println!("Sending message: {}", msg);
                sink.write()
                    .unwrap()
                    .start_send(OwnedMessage::Text(msg))
                    .unwrap();
                sink.write()
                    .unwrap()
                    .poll_complete()
                    .unwrap();
                Ok(())
            })
            .map_err(|_| ())
    });

    let game_loop = pool.spawn_fn(move || {
        future::loop_fn(write_channel_out, move |write_channel_out| {
            thread::sleep(Duration::from_millis(100));
            if !connections.read().unwrap().is_empty() {
                write_channel_out.clone()
                    .send((connections.write().unwrap()[0].clone(), state.clone()))
                    .wait()
                    .unwrap();
            }
            match 1 {
                1 => Ok(Loop::Continue(write_channel_out)),
                2 => Ok(Loop::Break(())),
                _ => Err(()),
            }
        })
    });

    let handlers =
        game_loop.select2(connection_handler.select2(read_handler.select(write_handler)));
    core.run(handlers).map_err(|_| println!("err")).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            //state.msg = txt.clone();
        }
        _ => {}
    }
}

#[derive(Serialize, Deserialize)]
struct State {
    positions: Vec<Pos>,
}

impl State {
    fn new() -> Self {
        Self { positions: Vec::new() }
    }
}

#[derive(Serialize, Deserialize)]
struct Pos {
    x: i32,
    y: i32,
}

impl Pos {
    fn new(x: i32, y: i32) -> Self {
        Self { x, y }
    }

    fn add_x(&mut self, x: i32) -> &mut Self {
        self.x += x;
        self
    }

    fn add_y(&mut self, y: i32) -> &mut Self {
        self.y += y;
        self
    }

    fn add(&mut self, x: i32, y: i32) -> &mut Self {
        self.x += x;
        self.y += y;
        self
    }
}
<|endoftext|>