<commit_before>#![feature(io)]

extern crate compiler;
extern crate argparse;
extern crate walkdir;

use argparse::ArgumentParser;
use walkdir::WalkDir;
use std::process::Command;
use std::borrow::Borrow;

mod tool
{
    /// A constant.
    #[derive(Copy,Clone,Debug,PartialEq,Eq)]
    pub enum Constant
    {
        /// The path of the test that is being run.
        TestPath,
    }

    impl Constant
    {
        /// Maps a constant name to a constant.
        /// Returns `None` if no mapping exists.
        pub fn lookup(name: &str) -> Option<Constant> {
            match name {
                "file" => Some(Constant::TestPath),
                _ => None,
            }
        }
    }

    /// An argument to a tool.
    #[derive(Clone,Debug,PartialEq,Eq)]
    pub enum Argument
    {
        Normal(String),
        Substitute(Constant),
    }

    impl Argument
    {
        /// Parses an argument to a tool.
        ///
        /// If it is prefixed with `@`, then it will be taken
        /// as a constant substitution, otherwise it will
        /// be read verbatim as a tool argument.
        pub fn parse(string: String) -> Result<Self,String> {
            // check if we are parsing a substitution
            if string.chars().next().unwrap() == '@' {
                let name: String = string.chars().skip(1).collect();

                match Constant::lookup(&name) {
                    Some(constant) => Ok(Argument::Substitute(constant)),
                    None => Err(format!("constant does not exist: {}", name)),
                }
            } else { // it is a plain old argument
                Ok(Argument::Normal(string))
            }
        }

        pub fn resolve(&self, test: &super::Test) -> String {
            match *self {
                Argument::Normal(ref s) => s.clone(),
                Argument::Substitute(constant) => match constant {
                    Constant::TestPath => test.path.clone(),
                },
            }
        }
    }

    /// A tool invocation.
    #[derive(Clone,Debug,PartialEq,Eq)]
    pub struct Invocation
    {
        pub executable: String,
        pub arguments: Vec<Argument>,
    }

    impl Invocation
    {
        /// Parses a tool invocation.
        ///
        /// It is in the format:
        ///
        /// ``` bash
        /// <tool-name> [arg1] [arg2] ...
        /// ```
        pub fn parse<'a,I>(mut words: I) -> Result<Self,String>
            where I: Iterator<Item=&'a str> {
            let executable = match words.next() {
                Some(exec) => exec,
                None => return Err("no executable specified".into()),
            }.into();

            let mut arguments = Vec::new();

            for arg_str in words {
                let arg = try!(Argument::parse(arg_str.into()));
                arguments.push(arg);
            }

            Ok(Invocation {
                executable: executable,
                arguments: arguments,
            })
        }
    }
}

#[derive(Clone,Debug,PartialEq,Eq)]
pub enum Directive
{
    Run(tool::Invocation),
}

impl Directive
{
    pub fn maybe_parse(string: String) -> Option<Result<Self,String>> {
        let directive_str = string.split_whitespace().next().unwrap();
        let inner_words = string.split_whitespace().skip(1);

        match directive_str {
            // FIXME: better message if we have 'RUN :'
            "RUN:" => {
                let invocation = match tool::Invocation::parse(inner_words) {
                    Ok(i) => i,
                    Err(e) => return Some(Err(e)),
                };

                Some(Ok(Directive::Run(invocation)))
            },
            _ => {
                if directive_str.ends_with(':') {
                    Some(Err(format!("directive '{}' not known", directive_str)))
                } else {
                    None
                }
            },
        }
    }
}

#[derive(Clone,Debug,PartialEq,Eq)]
pub struct Test
{
    pub path: String,
    pub directives: Vec<Directive>,
}

pub enum TestResultKind
{
    Pass,
    Fail(String, String),
}

pub struct TestResult
{
    pub path: String,
    pub kind: TestResultKind,
}

#[derive(Clone,Debug,PartialEq,Eq)]
pub struct Context
{
    pub exec_search_dirs: Vec<String>,
    pub tests: Vec<Test>,
}

impl Context
{
    pub fn new() -> Self {
        Context {
            exec_search_dirs: Vec::new(),
            tests: Vec::new(),
        }
    }

    pub fn test(mut self, test: Test) -> Self {
        self.tests.push(test);
        self
    }

    pub fn add_search_dir(&mut self, dir: String) {
        self.exec_search_dirs.push(dir);
    }

    pub fn find_in_search_dir(&self, path: &str)
        -> Option<String> {
        for dir in self.exec_search_dirs.iter() {
            for entry in std::fs::read_dir(dir).unwrap() {
                let entry = entry.unwrap();
                let cur_path = entry.path();

                if std::fs::metadata(&cur_path).unwrap().is_file() {
                    if cur_path.file_name().unwrap() == path {
                        return Some(cur_path.to_str().unwrap().to_owned());
                    }
                }

            }
        }
        None
    }

    pub fn executable_path(&self, path: &str) -> String {
        match self.find_in_search_dir(path) {
            Some(p) => p,
            None => path.to_owned(),
        }
    }
}

fn main() {
    let mut files: Vec<String> = Vec::new();

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Runs tests");

        ap.refer(&mut files)
            .add_argument("files", argparse::List,
                          r#"Files to test"#);
        ap.parse_args_or_exit();
    }

    let paths: Vec<&str> = files.iter()
                                 .map(|s| s.borrow())
                                 .collect();

    if paths.is_empty() {
        util::abort("no filenames given")
    }

    let test_paths = find_tests(&paths);

    let mut context = test_paths.into_iter().fold(Context::new(), |c,file| {
        let test = read_test(&file).unwrap();
        c.test(test)
    });

    match util::tool_dir() {
        Some(dir) => context.add_search_dir(dir),
        None => println!("could not find tool directory"),
    }

    let results = run_tests(&context);

    for result in results {
        match result.kind {
            TestResultKind::Pass => {
                println!("PASS :: {}", result.path);
            },
            TestResultKind::Fail(ref msg, ref desc) => {
                println!("");

                println!("FAIL :: {}", result.path);
                println!("\t{}", msg);

                // Only print stderr if there was output
                if !desc.is_empty() {
                    println!("");
                    println!("Program stderr:");
                    println!("");
                    println!("{}", desc);
                }

                println!("");
            },
        }
    }
}

/// Recursively finds tests for the given paths.
fn find_tests(paths: &[&str]) -> Vec<String> {
    paths.iter().flat_map(|path| {
                    find_tests_in_path(path).into_iter()
                })
                .collect()
}

fn find_tests_in_path(path: &str) -> Vec<String> {
    let metadata = match std::fs::metadata(path) {
        Ok(meta) => meta,
        Err(e) => util::abort(format!("failed to open '{}': {}",
                                      path, e)),
    };

    if metadata.is_dir() {
        find_tests_in_dir(path)
    } else {
        vec![path.to_owned()]
    }
}

fn find_tests_in_dir(path: &str) -> Vec<String> {
    find_files_in_dir(path).into_iter()
                           .filter(|f| f.ends_with(".ir"))
                           .collect()
}

fn find_files_in_dir(path: &str) -> Vec<String> {
    let mut dir_tests = Vec::new();

    for entry in WalkDir::new(path) {
        let entry = entry.unwrap();

        // don't go into an infinite loop
        if entry.path().to_str().unwrap() == path {
            continue;
        }

        if entry.metadata().unwrap().is_file() {
            dir_tests.push(entry.path().to_str().unwrap().to_owned());
        }
    }

    dir_tests
}

fn read_test(path: &str) -> Result<Test,String> {
    // TODO: redundant indirection
    util::parse_test(path)
}

fn run_tests(context: &Context) -> Vec<TestResult> {
    context.tests.iter().map(|test| run_test(test, context)).collect()
}

fn run_test(test: &Test, context: &Context) -> TestResult {
    for directive in test.directives.iter() {
        let kind = run_directive(directive, test, context);

        match kind {
            TestResultKind::Pass => continue,
            TestResultKind::Fail(msg, desc) => {
                return TestResult {
                    path: test.path.clone(),
                    kind: TestResultKind::Fail(msg, desc),
                }
            },
        }
    }

    TestResult {
        path: test.path.clone(),
        kind: TestResultKind::Pass,
    }
}

fn run_directive(directive: &Directive, test: &Test, context: &Context)
    -> TestResultKind {
    match *directive {
        Directive::Run(ref invocation) => {
            let exe_path = context.executable_path(&invocation.executable);
            let mut cmd = Command::new(&exe_path);

            for arg in invocation.arguments.iter() {
                let arg_str = arg.resolve(test);
                cmd.arg(arg_str);
            }

            let output = match cmd.output() {
                Ok(o) => o,
                Err(e) => match e.kind() {
                    std::io::ErrorKind::NotFound => {
                        return TestResultKind::Fail(
                            format!("executable not found: {}",
                                    exe_path), "".to_owned());
                    },
                    _ => {
                        return TestResultKind::Fail(
                            format!("could not execute: '{}', {}",
                                    exe_path, e), "".to_owned());
                    },
                },
            };

            if output.status.success() {
                TestResultKind::Pass
            } else {
                let stderr = String::from_utf8(output.stderr).unwrap();

                TestResultKind::Fail(format!(
                    "{} exited with code {}", exe_path,
                    output.status.code().unwrap()),
                    stderr
                    )
            }
        },
    }
}

mod util
{
    use super::{Test,Directive};

    use std::error::Error;
    use std::io::Read;
    use compiler::ir;
    use std;

    pub fn tool_dir() -> Option<String> {
        let current_exec = match std::env::current_exe() {
            Ok(e) => e,
            Err(e) => abort(
                format!("failed to get current executable path: {}", e)),
        };

        current_exec.parent().map(|p| p.to_str().unwrap().to_owned())
    }

    pub fn parse_test(file_name: &str) -> Result<Test,String> {
        use compiler::ir::read::Token;

        let chars = open_file(file_name).chars().map(|c| c.unwrap());

        let tokenizer = ir::read::Tokenizer::new(chars).preserve_comments();
        let tokens = tokenizer.map(|result| result.unwrap());

        let mut directives = Vec::new();

        for token in tokens {
            match token {
                Token::Comment { ref text, .. } => {
                    match maybe_parse_directive(text) {
                        Some(Ok(directive)) => directives.push(directive),
                        Some(Err(e)) => {
                            return Err(format!(
                                "could not parse directive: {}", e)
                            );
                        },
                        None => continue,
                    }
                },
                _ => continue,
            };
        }

        Ok(Test {
            path: file_name.to_owned(),
            directives: directives,
        })
    }

    pub fn maybe_parse_directive(comment_text: &str)
        -> Option<Result<Directive,String>> {
        Directive::maybe_parse(comment_text.trim().to_owned())
    }

    fn open_file(path: &str) -> std::fs::File {
        match std::fs::File::open(path) {
            Ok(f) => f,
            Err(e) => abort(format!("could not open {}: {}",
                                    path, e.description())),
        }
    }

    pub fn abort<S>(msg: S) -> !
        where S: Into<String> {
        println!("failed: {}", msg.into());
        std::process::exit(1);
    }
}
<commit_msg>[test] Warn if no directives are present<commit_after>#![feature(io)]

extern crate compiler;
extern crate argparse;
extern crate walkdir;

use argparse::ArgumentParser;
use walkdir::WalkDir;
use std::process::Command;
use std::borrow::Borrow;

mod tool
{
    /// A constant.
    #[derive(Copy,Clone,Debug,PartialEq,Eq)]
    pub enum Constant
    {
        /// The path of the test that is being run.
        TestPath,
    }

    impl Constant
    {
        /// Maps a constant name to a constant.
        /// Returns `None` if no mapping exists.
        pub fn lookup(name: &str) -> Option<Constant> {
            match name {
                "file" => Some(Constant::TestPath),
                _ => None,
            }
        }
    }

    /// An argument to a tool.
    #[derive(Clone,Debug,PartialEq,Eq)]
    pub enum Argument
    {
        Normal(String),
        Substitute(Constant),
    }

    impl Argument
    {
        /// Parses an argument to a tool.
        ///
        /// If it is prefixed with `@`, then it will be taken
        /// as a constant substitution, otherwise it will
        /// be read verbatim as a tool argument.
        pub fn parse(string: String) -> Result<Self,String> {
            // check if we are parsing a substitution
            if string.chars().next().unwrap() == '@' {
                let name: String = string.chars().skip(1).collect();

                match Constant::lookup(&name) {
                    Some(constant) => Ok(Argument::Substitute(constant)),
                    None => Err(format!("constant does not exist: {}", name)),
                }
            } else { // it is a plain old argument
                Ok(Argument::Normal(string))
            }
        }

        pub fn resolve(&self, test: &super::Test) -> String {
            match *self {
                Argument::Normal(ref s) => s.clone(),
                Argument::Substitute(constant) => match constant {
                    Constant::TestPath => test.path.clone(),
                },
            }
        }
    }

    /// A tool invocation.
    #[derive(Clone,Debug,PartialEq,Eq)]
    pub struct Invocation
    {
        pub executable: String,
        pub arguments: Vec<Argument>,
    }

    impl Invocation
    {
        /// Parses a tool invocation.
        ///
        /// It is in the format:
        ///
        /// ``` bash
        /// <tool-name> [arg1] [arg2] ...
        /// ```
        pub fn parse<'a,I>(mut words: I) -> Result<Self,String>
            where I: Iterator<Item=&'a str> {
            let executable = match words.next() {
                Some(exec) => exec,
                None => return Err("no executable specified".into()),
            }.into();

            let mut arguments = Vec::new();

            for arg_str in words {
                let arg = try!(Argument::parse(arg_str.into()));
                arguments.push(arg);
            }

            Ok(Invocation {
                executable: executable,
                arguments: arguments,
            })
        }
    }
}

#[derive(Clone,Debug,PartialEq,Eq)]
pub enum Directive
{
    Run(tool::Invocation),
}

impl Directive
{
    pub fn maybe_parse(string: String) -> Option<Result<Self,String>> {
        let directive_str = string.split_whitespace().next().unwrap();
        let inner_words = string.split_whitespace().skip(1);

        match directive_str {
            // FIXME: better message if we have 'RUN :'
            "RUN:" => {
                let invocation = match tool::Invocation::parse(inner_words) {
                    Ok(i) => i,
                    Err(e) => return Some(Err(e)),
                };

                Some(Ok(Directive::Run(invocation)))
            },
            _ => {
                if directive_str.ends_with(':') {
                    Some(Err(format!("directive '{}' not known", directive_str)))
                } else {
                    None
                }
            },
        }
    }
}

#[derive(Clone,Debug,PartialEq,Eq)]
pub struct Test
{
    pub path: String,
    pub directives: Vec<Directive>,
}

impl Test
{
    pub fn is_empty(&self) -> bool {
        self.directives.is_empty()
    }
}

pub enum TestResultKind
{
    Pass,
    Fail(String, String),
    Skip,
}

pub struct TestResult
{
    pub path: String,
    pub kind: TestResultKind,
}

#[derive(Clone,Debug,PartialEq,Eq)]
pub struct Context
{
    pub exec_search_dirs: Vec<String>,
    pub tests: Vec<Test>,
}

impl Context
{
    pub fn new() -> Self {
        Context {
            exec_search_dirs: Vec::new(),
            tests: Vec::new(),
        }
    }

    pub fn test(mut self, test: Test) -> Self {
        self.tests.push(test);
        self
    }

    pub fn add_search_dir(&mut self, dir: String) {
        self.exec_search_dirs.push(dir);
    }

    pub fn find_in_search_dir(&self, path: &str)
        -> Option<String> {
        for dir in self.exec_search_dirs.iter() {
            for entry in std::fs::read_dir(dir).unwrap() {
                let entry = entry.unwrap();
                let cur_path = entry.path();

                if std::fs::metadata(&cur_path).unwrap().is_file() {
                    if cur_path.file_name().unwrap() == path {
                        return Some(cur_path.to_str().unwrap().to_owned());
                    }
                }

            }
        }
        None
    }

    pub fn executable_path(&self, path: &str) -> String {
        match self.find_in_search_dir(path) {
            Some(p) => p,
            None => path.to_owned(),
        }
    }
}

fn main() {
    let mut files: Vec<String> = Vec::new();

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Runs tests");

        ap.refer(&mut files)
            .add_argument("files", argparse::List,
                          r#"Files to test"#);
        ap.parse_args_or_exit();
    }

    let paths: Vec<&str> = files.iter()
                                 .map(|s| s.borrow())
                                 .collect();

    if paths.is_empty() {
        util::abort("no filenames given")
    }

    let test_paths = find_tests(&paths);

    let mut context = test_paths.into_iter().fold(Context::new(), |c,file| {
        let test = read_test(&file).unwrap();
        c.test(test)
    });

    match util::tool_dir() {
        Some(dir) => context.add_search_dir(dir),
        None => println!("could not find tool directory"),
    }

    let results = run_tests(&context);

    for result in results {
        match result.kind {
            TestResultKind::Pass => {
                println!("PASS :: {}", result.path);
            },
            TestResultKind::Skip => {
                println!("");
                println!("SKIP :: {} (test does not contain any directives)",
                         result.path);
                println!("");
            },
            TestResultKind::Fail(ref msg, ref desc) => {
                println!("");

                println!("FAIL :: {}", result.path);
                println!("\t{}", msg);

                // Only print stderr if there was output
                if !desc.is_empty() {
                    println!("");
                    println!("Program stderr:");
                    println!("");
                    println!("{}", desc);
                }

                println!("");
            },
        }
    }
}

/// Recursively finds tests for the given paths.
fn find_tests(paths: &[&str]) -> Vec<String> {
    paths.iter().flat_map(|path| {
                    find_tests_in_path(path).into_iter()
                })
                .collect()
}

fn find_tests_in_path(path: &str) -> Vec<String> {
    let metadata = match std::fs::metadata(path) {
        Ok(meta) => meta,
        Err(e) => util::abort(format!("failed to open '{}': {}",
                                      path, e)),
    };

    if metadata.is_dir() {
        find_tests_in_dir(path)
    } else {
        vec![path.to_owned()]
    }
}

fn find_tests_in_dir(path: &str) -> Vec<String> {
    find_files_in_dir(path).into_iter()
                           .filter(|f| f.ends_with(".ir"))
                           .collect()
}

fn find_files_in_dir(path: &str) -> Vec<String> {
    let mut dir_tests = Vec::new();

    for entry in WalkDir::new(path) {
        let entry = entry.unwrap();

        // don't go into an infinite loop
        if entry.path().to_str().unwrap() == path {
            continue;
        }

        if entry.metadata().unwrap().is_file() {
            dir_tests.push(entry.path().to_str().unwrap().to_owned());
        }
    }

    dir_tests
}

fn read_test(path: &str) -> Result<Test,String> {
    // TODO: redundant indirection
    util::parse_test(path)
}

fn run_tests(context: &Context) -> Vec<TestResult> {
    context.tests.iter().map(|test| run_test(test, context)).collect()
}

fn run_test(test: &Test, context: &Context) -> TestResult {
    if test.is_empty() {
        println!("SKIP :: {} (it includes no test directives", test.path);
        return TestResult {
            path: test.path.clone(),
            kind: TestResultKind::Skip,
        }
    }

    for directive in test.directives.iter() {
        let kind = run_directive(directive, test, context);

        match kind {
            TestResultKind::Pass => continue,
            TestResultKind::Skip => continue,
            TestResultKind::Fail(msg, desc) => {
                return TestResult {
                    path: test.path.clone(),
                    kind: TestResultKind::Fail(msg, desc),
                }
            },
        }
    }

    TestResult {
        path: test.path.clone(),
        kind: TestResultKind::Pass,
    }
}

fn run_directive(directive: &Directive, test: &Test, context: &Context)
    -> TestResultKind {
    match *directive {
        Directive::Run(ref invocation) => {
            let exe_path = context.executable_path(&invocation.executable);
            let mut cmd = Command::new(&exe_path);

            for arg in invocation.arguments.iter() {
                let arg_str = arg.resolve(test);
                cmd.arg(arg_str);
            }

            let output = match cmd.output() {
                Ok(o) => o,
                Err(e) => match e.kind() {
                    std::io::ErrorKind::NotFound => {
                        return TestResultKind::Fail(
                            format!("executable not found: {}",
                                    exe_path), "".to_owned());
                    },
                    _ => {
                        return TestResultKind::Fail(
                            format!("could not execute: '{}', {}",
                                    exe_path, e), "".to_owned());
                    },
                },
            };

            if output.status.success() {
                TestResultKind::Pass
            } else {
                let stderr = String::from_utf8(output.stderr).unwrap();

                TestResultKind::Fail(format!(
                    "{} exited with code {}", exe_path,
                    output.status.code().unwrap()),
                    stderr
                    )
            }
        },
    }
}

mod util
{
    use super::{Test,Directive};

    use std::error::Error;
    use std::io::Read;
    use compiler::ir;
    use std;

    pub fn tool_dir() -> Option<String> {
        let current_exec = match std::env::current_exe() {
            Ok(e) => e,
            Err(e) => abort(
                format!("failed to get current executable path: {}", e)),
        };

        current_exec.parent().map(|p| p.to_str().unwrap().to_owned())
    }

    pub fn parse_test(file_name: &str) -> Result<Test,String> {
        use compiler::ir::read::Token;

        let chars = open_file(file_name).chars().map(|c| c.unwrap());

        let tokenizer = ir::read::Tokenizer::new(chars).preserve_comments();
        let tokens = tokenizer.map(|result| result.unwrap());

        let mut directives = Vec::new();

        for token in tokens {
            match token {
                Token::Comment { ref text, .. } => {
                    match maybe_parse_directive(text) {
                        Some(Ok(directive)) => directives.push(directive),
                        Some(Err(e)) => {
                            return Err(format!(
                                "could not parse directive: {}", e)
                            );
                        },
                        None => continue,
                    }
                },
                _ => continue,
            };
        }

        Ok(Test {
            path: file_name.to_owned(),
            directives: directives,
        })
    }

    pub fn maybe_parse_directive(comment_text: &str)
        -> Option<Result<Directive,String>> {
        Directive::maybe_parse(comment_text.trim().to_owned())
    }

    fn open_file(path: &str) -> std::fs::File {
        match std::fs::File::open(path) {
            Ok(f) => f,
            Err(e) => abort(format!("could not open {}: {}",
                                    path, e.description())),
        }
    }

    pub fn abort<S>(msg: S) -> !
        where S: Into<String> {
        println!("failed: {}", msg.into());
        std::process::exit(1);
    }
}
<|endoftext|>


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

use app_units::Au;
% for style_struct in STYLE_STRUCTS:
%if style_struct.gecko_name:
use gecko_style_structs::${style_struct.gecko_name};
% endif
% endfor
use heapsize::HeapSizeOf;
use std::fmt::{self, Debug};
use std::mem::zeroed;
use std::sync::Arc;
use style::custom_properties::ComputedValuesMap;
use style::logical_geometry::WritingMode;
use style::properties::{CascadePropertyFn, ServoComputedValues, ComputedValues};
use style::properties::longhands;
use style::properties::style_struct_traits::*;

#[derive(Clone)]
pub struct GeckoComputedValues {
    % for style_struct in STYLE_STRUCTS:
    ${style_struct.ident}: Arc<Gecko${style_struct.name}>,
    % endfor

    custom_properties: Option<Arc<ComputedValuesMap>>,
    shareable: bool,
    pub writing_mode: WritingMode,
    pub root_font_size: Au,
}

impl ComputedValues for GeckoComputedValues {
% for style_struct in STYLE_STRUCTS:
    type Concrete${style_struct.name} = Gecko${style_struct.name};
% endfor

    // These will go away, and we will never implement them.
    fn as_servo<'a>(&'a self) -> &'a ServoComputedValues { unimplemented!() }
    fn as_servo_mut<'a>(&'a mut self) -> &'a mut ServoComputedValues { unimplemented!() }

    fn new(custom_properties: Option<Arc<ComputedValuesMap>>,
           shareable: bool,
           writing_mode: WritingMode,
           root_font_size: Au,
            % for style_struct in STYLE_STRUCTS:
           ${style_struct.ident}: Arc<Gecko${style_struct.name}>,
            % endfor
    ) -> Self {
        GeckoComputedValues {
            custom_properties: custom_properties,
            shareable: shareable,
            writing_mode: writing_mode,
            root_font_size: root_font_size,
            % for style_struct in STYLE_STRUCTS:
            ${style_struct.ident}: ${style_struct.ident},
            % endfor
        }
    }

    fn initial_values() -> &'static Self { unimplemented!() }

    fn do_cascade_property<F: FnOnce(&Vec<Option<CascadePropertyFn<Self>>>)>(_: F) {
        unimplemented!()
    }

    % for style_struct in STYLE_STRUCTS:
    #[inline]
    fn clone_${style_struct.name.lower()}(&self) -> Arc<Self::Concrete${style_struct.name}> {
        self.${style_struct.ident}.clone()
    }
    #[inline]
    fn get_${style_struct.name.lower()}<'a>(&'a self) -> &'a Self::Concrete${style_struct.name} {
        &self.${style_struct.ident}
    }
    #[inline]
    fn mutate_${style_struct.name.lower()}<'a>(&'a mut self) -> &'a mut Self::Concrete${style_struct.name} {
        Arc::make_mut(&mut self.${style_struct.ident})
    }
    % endfor

    fn custom_properties(&self) -> Option<Arc<ComputedValuesMap>> { self.custom_properties.as_ref().map(|x| x.clone())}
    fn root_font_size(&self) -> Au { self.root_font_size }
    fn set_root_font_size(&mut self, s: Au) { self.root_font_size = s; }
    fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; }

    #[inline]
    fn is_multicol(&self) -> bool { unimplemented!() }
}

<%def name="declare_style_struct(style_struct)">
#[derive(Clone, HeapSizeOf, Debug)]
% if style_struct.gecko_name:
pub struct Gecko${style_struct.name} {
    gecko: ${style_struct.gecko_name},
}
% else:
pub struct Gecko${style_struct.name};
% endif
</%def>

<%def name="impl_style_struct(style_struct)">
impl Gecko${style_struct.name} {
    #[allow(dead_code, unused_variables)]
    fn initial() -> Self {
% if style_struct.gecko_name:
        let result = Gecko${style_struct.name} { gecko: unsafe { zeroed() } };
        panic!("Need to invoke Gecko placement new");
% else:
        Gecko${style_struct.name}
% endif
    }
}
%if style_struct.gecko_name:
impl Drop for Gecko${style_struct.name} {
    fn drop(&mut self) {
        panic!("Need to invoke Gecko destructor");
    }
}
impl Clone for ${style_struct.gecko_name} {
    fn clone(&self) -> Self {
        panic!("Need to invoke Gecko copy constructor");
    }
}
unsafe impl Send for ${style_struct.gecko_name} {}
unsafe impl Sync for ${style_struct.gecko_name} {}
impl HeapSizeOf for ${style_struct.gecko_name} {
    // Not entirely accurate, but good enough for now.
    fn heap_size_of_children(&self) -> usize { 0 }
}
impl Debug for ${style_struct.gecko_name} {
    // FIXME(bholley): Generate this.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "GECKO STYLE STRUCT")
    }
}
%endif
</%def>

% for style_struct in STYLE_STRUCTS:
${declare_style_struct(style_struct)}
${impl_style_struct(style_struct)}
impl T${style_struct.name} for Gecko${style_struct.name} {
    % for longhand in style_struct.longhands:
    fn set_${longhand.ident}(&mut self, _: longhands::${longhand.ident}::computed_value::T) {
        unimplemented!()
    }
    fn copy_${longhand.ident}_from(&mut self, _: &Self) {
        unimplemented!()
    }
    % endfor
    % for additional in style_struct.additional_methods:
    ${additional.stub()}
    % endfor
}

% endfor
<commit_msg>Use templates to implement the traits in geckolib.<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/. */

use app_units::Au;
% for style_struct in STYLE_STRUCTS:
%if style_struct.gecko_name:
use gecko_style_structs::${style_struct.gecko_name};
% endif
% endfor
use heapsize::HeapSizeOf;
use std::fmt::{self, Debug};
use std::mem::zeroed;
use std::sync::Arc;
use style::custom_properties::ComputedValuesMap;
use style::logical_geometry::WritingMode;
use style::properties::{CascadePropertyFn, ServoComputedValues, ComputedValues};
use style::properties::longhands;
use style::properties::style_struct_traits::*;

#[derive(Clone)]
pub struct GeckoComputedValues {
    % for style_struct in STYLE_STRUCTS:
    ${style_struct.ident}: Arc<Gecko${style_struct.name}>,
    % endfor

    custom_properties: Option<Arc<ComputedValuesMap>>,
    shareable: bool,
    pub writing_mode: WritingMode,
    pub root_font_size: Au,
}

impl ComputedValues for GeckoComputedValues {
% for style_struct in STYLE_STRUCTS:
    type Concrete${style_struct.name} = Gecko${style_struct.name};
% endfor

    // These will go away, and we will never implement them.
    fn as_servo<'a>(&'a self) -> &'a ServoComputedValues { unimplemented!() }
    fn as_servo_mut<'a>(&'a mut self) -> &'a mut ServoComputedValues { unimplemented!() }

    fn new(custom_properties: Option<Arc<ComputedValuesMap>>,
           shareable: bool,
           writing_mode: WritingMode,
           root_font_size: Au,
            % for style_struct in STYLE_STRUCTS:
           ${style_struct.ident}: Arc<Gecko${style_struct.name}>,
            % endfor
    ) -> Self {
        GeckoComputedValues {
            custom_properties: custom_properties,
            shareable: shareable,
            writing_mode: writing_mode,
            root_font_size: root_font_size,
            % for style_struct in STYLE_STRUCTS:
            ${style_struct.ident}: ${style_struct.ident},
            % endfor
        }
    }

    fn initial_values() -> &'static Self { unimplemented!() }

    fn do_cascade_property<F: FnOnce(&Vec<Option<CascadePropertyFn<Self>>>)>(_: F) {
        unimplemented!()
    }

    % for style_struct in STYLE_STRUCTS:
    #[inline]
    fn clone_${style_struct.name.lower()}(&self) -> Arc<Self::Concrete${style_struct.name}> {
        self.${style_struct.ident}.clone()
    }
    #[inline]
    fn get_${style_struct.name.lower()}<'a>(&'a self) -> &'a Self::Concrete${style_struct.name} {
        &self.${style_struct.ident}
    }
    #[inline]
    fn mutate_${style_struct.name.lower()}<'a>(&'a mut self) -> &'a mut Self::Concrete${style_struct.name} {
        Arc::make_mut(&mut self.${style_struct.ident})
    }
    % endfor

    fn custom_properties(&self) -> Option<Arc<ComputedValuesMap>> { self.custom_properties.as_ref().map(|x| x.clone())}
    fn root_font_size(&self) -> Au { self.root_font_size }
    fn set_root_font_size(&mut self, s: Au) { self.root_font_size = s; }
    fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; }

    #[inline]
    fn is_multicol(&self) -> bool { unimplemented!() }
}

<%def name="declare_style_struct(style_struct)">
#[derive(Clone, HeapSizeOf, Debug)]
% if style_struct.gecko_name:
pub struct Gecko${style_struct.name} {
    gecko: ${style_struct.gecko_name},
}
% else:
pub struct Gecko${style_struct.name};
% endif
</%def>

<%def name="impl_style_struct(style_struct)">
impl Gecko${style_struct.name} {
    #[allow(dead_code, unused_variables)]
    fn initial() -> Self {
% if style_struct.gecko_name:
        let result = Gecko${style_struct.name} { gecko: unsafe { zeroed() } };
        panic!("Need to invoke Gecko placement new");
% else:
        Gecko${style_struct.name}
% endif
    }
}
%if style_struct.gecko_name:
impl Drop for Gecko${style_struct.name} {
    fn drop(&mut self) {
        panic!("Need to invoke Gecko destructor");
    }
}
impl Clone for ${style_struct.gecko_name} {
    fn clone(&self) -> Self {
        panic!("Need to invoke Gecko copy constructor");
    }
}
unsafe impl Send for ${style_struct.gecko_name} {}
unsafe impl Sync for ${style_struct.gecko_name} {}
impl HeapSizeOf for ${style_struct.gecko_name} {
    // Not entirely accurate, but good enough for now.
    fn heap_size_of_children(&self) -> usize { 0 }
}
impl Debug for ${style_struct.gecko_name} {
    // FIXME(bholley): Generate this.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "GECKO STYLE STRUCT")
    }
}
%endif
</%def>

<%def name="raw_impl_trait(style_struct, skip_longhands=None, skip_additionals=None)">
impl T${style_struct.name} for Gecko${style_struct.name} {
    /*
     * Manually-Implemented Methods.
     */
    ${caller.body().strip()}

    /*
     * Auto-Generated Methods.
     */
    <% longhands = [x for x in style_struct.longhands
                    if not (skip_longhands and x.name in skip_longhands)] %>
    % for longhand in longhands:
    fn set_${longhand.ident}(&mut self, _: longhands::${longhand.ident}::computed_value::T) {
        unimplemented!()
    }
    fn copy_${longhand.ident}_from(&mut self, _: &Self) {
        unimplemented!()
    }
    % endfor
    <% additionals = [x for x in style_struct.additional_methods
                      if not (skip_additionals and x.name in skip_additionals)] %>
    % for additional in additionals:
    ${additional.stub()}
    % endfor
}
</%def>

<%! MANUAL_STYLE_STRUCTS = [] %>
<%def name="impl_trait(style_struct_name, skip_longhands=None, skip_additionals=None)">
<%self:raw_impl_trait style_struct="${next(x for x in STYLE_STRUCTS if x.name == style_struct_name)}"
                       skip_longhands="${skip_longhands}" skip_additionals="${skip_additionals}">
${caller.body()}
</%self:raw_impl_trait>
<% MANUAL_STYLE_STRUCTS.append(style_struct_name) %>
</%def>

// Proof-of-concept for a style struct with some manually-implemented methods. We add
// the manually-implemented methods to skip_longhands and skip_additionals, and the
// infrastructure auto-generates everything not in those lists. This allows us to
// iteratively implement more and more methods.
<%self:impl_trait style_struct_name="Border"
                  skip_longhands="${['border-left-color', 'border-left-style']}"
                  skip_additionals="${['border_bottom_is_none_or_hidden_and_has_nonzero_width']}">
    fn set_border_left_color(&mut self, _: longhands::border_left_color::computed_value::T) {
        unimplemented!()
    }
    fn copy_border_left_color_from(&mut self, _: &Self) {
        unimplemented!()
    }
    fn set_border_left_style(&mut self, _: longhands::border_left_style::computed_value::T) {
        unimplemented!()
    }
    fn copy_border_left_style_from(&mut self, _: &Self) {
        unimplemented!()
    }
    fn border_bottom_is_none_or_hidden_and_has_nonzero_width(&self) -> bool {
        unimplemented!()
    }
</%self:impl_trait>

% for style_struct in STYLE_STRUCTS:
${declare_style_struct(style_struct)}
${impl_style_struct(style_struct)}
% if not style_struct.name in MANUAL_STYLE_STRUCTS:
<%self:raw_impl_trait style_struct="${style_struct}"></%self:raw_impl_trait>
% endif
% endfor
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::iter::FromIterator;
use std::slice::{Iter, IterMut};
use std::vec::IntoIter;

use crate::stable_hasher::{HashStable, StableHasher};

#[derive(Clone, Encodable, Decodable, Debug)]
pub struct VecMap<K, V>(Vec<(K, V)>);

impl<K, V> VecMap<K, V>
where
    K: PartialEq,
{
    pub fn new() -> Self {
        VecMap(Default::default())
    }

    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
        if let Some(elem) = self.0.iter_mut().find(|(key, _)| *key == k) {
            Some(std::mem::replace(&mut elem.1, v))
        } else {
            self.0.push((k, v));
            None
        }
    }

    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
    where
        K: Borrow<Q>,
        Q: Eq,
    {
        self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1)
    }

    pub fn get_by<P>(&self, predicate: P) -> Option<&V>
    where
        for<'b> P: FnMut(&'b &(K, V)) -> bool,
    {
        self.0.iter().find(predicate).map(|elem| &elem.1)
    }

    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
    where
        K: Borrow<Q>,
        Q: Eq,
    {
        self.get(k).is_some()
    }

    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    pub fn iter(&self) -> Iter<'_, (K, V)> {
        self.into_iter()
    }

    pub fn iter_mut(&mut self) -> IterMut<'_, (K, V)> {
        self.into_iter()
    }
}

impl<K, V> Default for VecMap<K, V> {
    #[inline]
    fn default() -> Self {
        Self(Default::default())
    }
}

impl<K, V> From<Vec<(K, V)>> for VecMap<K, V> {
    fn from(vec: Vec<(K, V)>) -> Self {
        Self(vec)
    }
}

impl<K, V> Into<Vec<(K, V)>> for VecMap<K, V> {
    fn into(self) -> Vec<(K, V)> {
        self.0
    }
}

impl<K, V> FromIterator<(K, V)> for VecMap<K, V> {
    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
        Self(iter.into_iter().collect())
    }
}

impl<'a, K, V> IntoIterator for &'a VecMap<K, V> {
    type Item = &'a (K, V);
    type IntoIter = Iter<'a, (K, V)>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.0.iter()
    }
}

impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> {
    type Item = &'a mut (K, V);
    type IntoIter = IterMut<'a, (K, V)>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.0.iter_mut()
    }
}

impl<K, V> IntoIterator for VecMap<K, V> {
    type Item = (K, V);
    type IntoIter = IntoIter<(K, V)>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl<K, V> Extend<(K, V)> for VecMap<K, V> {
    fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
        self.0.extend(iter);
    }

    fn extend_one(&mut self, item: (K, V)) {
        self.0.extend_one(item);
    }

    fn extend_reserve(&mut self, additional: usize) {
        self.0.extend_reserve(additional);
    }
}

impl<K, V, CTX> HashStable<CTX> for VecMap<K, V>
where
    K: HashStable<CTX> + Eq,
    V: HashStable<CTX>,
{
    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
        self.0.hash_stable(hcx, hasher)
    }
}

#[cfg(test)]
mod tests;
<commit_msg>Explicitly pass find arguments down the predicate so coercions can apply<commit_after>use std::borrow::Borrow;
use std::iter::FromIterator;
use std::slice::{Iter, IterMut};
use std::vec::IntoIter;

use crate::stable_hasher::{HashStable, StableHasher};

#[derive(Clone, Encodable, Decodable, Debug)]
pub struct VecMap<K, V>(Vec<(K, V)>);

impl<K, V> VecMap<K, V>
where
    K: PartialEq,
{
    pub fn new() -> Self {
        VecMap(Default::default())
    }

    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
        if let Some(elem) = self.0.iter_mut().find(|(key, _)| *key == k) {
            Some(std::mem::replace(&mut elem.1, v))
        } else {
            self.0.push((k, v));
            None
        }
    }

    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
    where
        K: Borrow<Q>,
        Q: Eq,
    {
        self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1)
    }

    pub fn get_by<P>(&self, mut predicate: P) -> Option<&V>
    where
        for<'b> P: FnMut(&'b &(K, V)) -> bool,
    {
        self.0.iter().find(|kv| predicate(kv)).map(|elem| &elem.1)
    }

    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
    where
        K: Borrow<Q>,
        Q: Eq,
    {
        self.get(k).is_some()
    }

    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    pub fn iter(&self) -> Iter<'_, (K, V)> {
        self.into_iter()
    }

    pub fn iter_mut(&mut self) -> IterMut<'_, (K, V)> {
        self.into_iter()
    }
}

impl<K, V> Default for VecMap<K, V> {
    #[inline]
    fn default() -> Self {
        Self(Default::default())
    }
}

impl<K, V> From<Vec<(K, V)>> for VecMap<K, V> {
    fn from(vec: Vec<(K, V)>) -> Self {
        Self(vec)
    }
}

impl<K, V> Into<Vec<(K, V)>> for VecMap<K, V> {
    fn into(self) -> Vec<(K, V)> {
        self.0
    }
}

impl<K, V> FromIterator<(K, V)> for VecMap<K, V> {
    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
        Self(iter.into_iter().collect())
    }
}

impl<'a, K, V> IntoIterator for &'a VecMap<K, V> {
    type Item = &'a (K, V);
    type IntoIter = Iter<'a, (K, V)>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.0.iter()
    }
}

impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> {
    type Item = &'a mut (K, V);
    type IntoIter = IterMut<'a, (K, V)>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.0.iter_mut()
    }
}

impl<K, V> IntoIterator for VecMap<K, V> {
    type Item = (K, V);
    type IntoIter = IntoIter<(K, V)>;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl<K, V> Extend<(K, V)> for VecMap<K, V> {
    fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
        self.0.extend(iter);
    }

    fn extend_one(&mut self, item: (K, V)) {
        self.0.extend_one(item);
    }

    fn extend_reserve(&mut self, additional: usize) {
        self.0.extend_reserve(additional);
    }
}

impl<K, V, CTX> HashStable<CTX> for VecMap<K, V>
where
    K: HashStable<CTX> + Eq,
    V: HashStable<CTX>,
{
    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
        self.0.hash_stable(hcx, hasher)
    }
}

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>pub fn verse(index: usize) -> String {
    match index {
        2 => {
            "2 bottles of beer on the wall, 2 bottles of beer.\n\
             Take one down and pass it around, 1 bottle of beer \
             on the wall.\n"
                .to_string()
        }
        1 => {
            "1 bottle of beer on the wall, 1 bottle of beer.\n\
             Take it down and pass it around, no more bottles of beer \
             on the wall.\n"
                .to_string()
        }
        0 => {
            "No more bottles of beer on the wall, no more bottles of beer.\n\
             Go to the store and buy some more, 99 bottles of beer \
             on the wall.\n"
                .to_string()
        }
        _ => {
            format!(
                "{} bottles of beer on the wall, {} bottles of beer.\n\
                 Take one down and pass it around, {} bottles of beer \
                 on the wall.\n",
                index,
                index,
                index - 1
            )
        }
    }
}

pub fn sing(upper: usize, lower: usize) -> String {
    (lower..upper + 1)
        .rev()
        .map(verse)
        .collect::<Vec<_>>()
        .join("\n")
}
<commit_msg>Use {0} and {1} in format<commit_after>pub fn verse(index: usize) -> String {
    match index {
        2 => {
            "2 bottles of beer on the wall, 2 bottles of beer.\n\
             Take one down and pass it around, 1 bottle of beer \
             on the wall.\n"
                .to_string()
        }
        1 => {
            "1 bottle of beer on the wall, 1 bottle of beer.\n\
             Take it down and pass it around, no more bottles of beer \
             on the wall.\n"
                .to_string()
        }
        0 => {
            "No more bottles of beer on the wall, no more bottles of beer.\n\
             Go to the store and buy some more, 99 bottles of beer \
             on the wall.\n"
                .to_string()
        }
        _ => {
            format!(
                "{0} bottles of beer on the wall, {0} bottles of beer.\n\
                 Take one down and pass it around, {1} bottles of beer \
                 on the wall.\n",
                index,
                index - 1
            )
        }
    }
}

pub fn sing(upper: usize, lower: usize) -> String {
    (lower..upper + 1)
        .rev()
        .map(verse)
        .collect::<Vec<_>>()
        .join("\n")
}
<|endoftext|>


<commit_before>// Copyright 2014 Rich Lane.

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

extern mod extra;
extern mod cgmath;
extern mod noise;

use std;
use std::num::clamp;

use extra::time::precise_time_ns;

use cgmath::vector::Vec3;

use noise::Perlin;

use CHUNK_SIZE;
use chunk::Block;
use chunk::{BlockAir,BlockDirt,BlockStone,BlockWater,BlockGrass};

pub struct Terrain {
    blocks: [[[Block, ..CHUNK_SIZE], ..CHUNK_SIZE], ..CHUNK_SIZE],
}

impl Terrain {
    pub fn gen(seed: u32, p: Vec3<f64>) -> ~Terrain {
        let def_block = Block { blocktype: BlockAir };
        let mut t = ~Terrain {
            blocks: [[[def_block, ..CHUNK_SIZE], ..CHUNK_SIZE], ..CHUNK_SIZE],
        };

        let start_time = precise_time_ns();

        let perlin1 = Perlin::from_seed([seed as uint]);
        let perlin2 = Perlin::from_seed([seed as uint * 7]);
        let perlin3 = Perlin::from_seed([seed as uint * 13]);
        let perlin4 = Perlin::from_seed([seed as uint * 17]);

        for block_x in std::iter::range(0, CHUNK_SIZE) {
            for block_z in std::iter::range(0, CHUNK_SIZE) {
                let noise1 = perlin1.gen([
                    (p.x + block_x as f64) * 0.07,
                    (p.z + block_z as f64) * 0.04
                ]);
                let noise2 = perlin2.gen([
                    (p.x + block_x as f64) * 0.05,
                    (p.z + block_z as f64) * 0.05
                ]);
                let noise3 = perlin3.gen([
                    (p.x + block_x as f64) * 0.005,
                    (p.z + block_z as f64) * 0.005
                ]);
                let noise4 = perlin4.gen([
                    (p.x + block_x as f64) * 0.001,
                    (p.z + block_z as f64) * 0.001
                ]);

                let base_height = 15.0;
                let base_variance = 10.0;
                let height = clamp(
                    (
                        base_height +
                        noise4 * 10.0 +
                        base_variance *
                            std::num::pow(noise3 + 1.0, 2.5) *
                            noise1
                    ) as int,
                    1, CHUNK_SIZE as int - 1) as uint;

                for y in range(0, height) {
                    let mut blocktype = BlockStone;

                    let dirt_height = (4.0 + noise2 * 8.0) as uint;
                    if (height <= 20) && (y + dirt_height >= height) {
                        if y < height - 2 {
                            blocktype = BlockDirt;
                        } else {
                            blocktype = BlockGrass;
                        }
                    }

                    t.blocks[block_x][y][block_z] = Block { blocktype: blocktype };
                }

                let water_height = 10;
                for y in range(height, water_height) {
                    t.blocks[block_x][y][block_z] = Block { blocktype: BlockWater };
                }
            }
        }

        let end_time = precise_time_ns();

        println!("terrain gen : {}us",
                (end_time - start_time)/1000);

        return t;
    }

    pub fn index<'a>(&'a self, x: int, y: int, z: int) -> Option<&'a Block> {
        if x < 0 || x >= CHUNK_SIZE as int || y < 0 || y >= CHUNK_SIZE as int || z < 0 || z >= CHUNK_SIZE as int {
            None
        } else {
            Some(&self.blocks[x][y][z])
        }
    }
}
<commit_msg>terrain: generate caves<commit_after>// Copyright 2014 Rich Lane.

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

extern mod extra;
extern mod cgmath;
extern mod noise;

use std;
use std::num::clamp;

use extra::time::precise_time_ns;

use cgmath::vector::Vec3;

use noise::Perlin;

use CHUNK_SIZE;
use chunk::Block;
use chunk::{BlockAir,BlockDirt,BlockStone,BlockWater,BlockGrass};

pub struct Terrain {
    blocks: [[[Block, ..CHUNK_SIZE], ..CHUNK_SIZE], ..CHUNK_SIZE],
}

impl Terrain {
    pub fn gen(seed: u32, p: Vec3<f64>) -> ~Terrain {
        let def_block = Block { blocktype: BlockAir };
        let mut t = ~Terrain {
            blocks: [[[def_block, ..CHUNK_SIZE], ..CHUNK_SIZE], ..CHUNK_SIZE],
        };

        let start_time = precise_time_ns();

        let perlin1 = Perlin::from_seed([seed as uint]);
        let perlin2 = Perlin::from_seed([seed as uint * 7]);
        let perlin3 = Perlin::from_seed([seed as uint * 13]);
        let perlin4 = Perlin::from_seed([seed as uint * 17]);

        for block_x in std::iter::range(0, CHUNK_SIZE) {
            for block_z in std::iter::range(0, CHUNK_SIZE) {
                let noise1 = perlin1.gen([
                    (p.x + block_x as f64) * 0.07,
                    (p.z + block_z as f64) * 0.04
                ]);
                let noise2 = perlin2.gen([
                    (p.x + block_x as f64) * 0.05,
                    (p.z + block_z as f64) * 0.05
                ]);
                let noise3 = perlin3.gen([
                    (p.x + block_x as f64) * 0.005,
                    (p.z + block_z as f64) * 0.005
                ]);
                let noise4 = perlin4.gen([
                    (p.x + block_x as f64) * 0.001,
                    (p.z + block_z as f64) * 0.001
                ]);

                let base_height = 15.0;
                let base_variance = 10.0;
                let height = clamp(
                    (
                        base_height +
                        noise4 * 10.0 +
                        base_variance *
                            std::num::pow(noise3 + 1.0, 2.5) *
                            noise1
                    ) as int,
                    1, CHUNK_SIZE as int - 1) as uint;

                for y in range(0, height) {
                    let mut blocktype = BlockStone;

                    let dirt_height = (4.0 + noise2 * 8.0) as uint;
                    if (height <= 20) && (y + dirt_height >= height) {
                        if y < height - 2 {
                            blocktype = BlockDirt;
                        } else {
                            blocktype = BlockGrass;
                        }
                    }

                    t.blocks[block_x][y][block_z] = Block { blocktype: blocktype };
                }

                let water_height = 10;
                for y in range(height, water_height) {
                    t.blocks[block_x][y][block_z] = Block { blocktype: BlockWater };
                }

                for block_y in std::iter::range(0, CHUNK_SIZE) {
                    let block = &mut t.blocks[block_x][block_y][block_z];

                    if (p.y + block_y as f64) <= 1.0 ||
                       block.blocktype == BlockAir {
                        continue;
                    }

                    let cave = perlin1.gen([
                        (p.x + block_x as f64) * 0.05,
                        (p.y + block_y as f64) * 0.1,
                        (p.z + block_z as f64) * 0.05]);

                    if cave > 0.5 {
                        block.blocktype = BlockAir;
                    }
                }

            }
        }

        let end_time = precise_time_ns();

        println!("terrain gen : {}us",
                (end_time - start_time)/1000);

        return t;
    }

    pub fn index<'a>(&'a self, x: int, y: int, z: int) -> Option<&'a Block> {
        if x < 0 || x >= CHUNK_SIZE as int || y < 0 || y >= CHUNK_SIZE as int || z < 0 || z >= CHUNK_SIZE as int {
            None
        } else {
            Some(&self.blocks[x][y][z])
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Rich Lane.

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

extern mod extra;
extern mod cgmath;
extern mod noise;

use std;
use std::num::clamp;

use extra::time::precise_time_ns;

use cgmath::vector::Vector;
use cgmath::vector::Vec3;

use noise::Perlin;

use CHUNK_SIZE;
use WORLD_HEIGHT;

#[repr(u8)]
#[deriving(Eq)]
pub enum BlockType {
    BlockAir = 0,
    BlockGrass = 1,
    BlockStone = 2,
    BlockDirt = 3,
    BlockWater = 4,
}

pub struct Block {
    blocktype: BlockType,
}

impl Block {
    pub fn is_opaque(&self) -> bool {
        self.blocktype != BlockAir
    }
}

pub struct Terrain {
    priv blocks: [[[Block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
}

impl Terrain {
    pub fn gen(seed: u32, p: Vec3<f64>) -> ~Terrain {
        let def_block = Block { blocktype: BlockAir };
        let mut t = ~Terrain {
            blocks: [[[def_block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
        };

        let water_height = 52.0;
        let base_height = 64.0;
        let base_variance = 10.0;

        let start_time = precise_time_ns();

        let perlin1 = Perlin::from_seed([seed as uint]);
        let perlin2 = Perlin::from_seed([seed as uint * 7]);
        let perlin3 = Perlin::from_seed([seed as uint * 13]);
        let perlin4 = Perlin::from_seed([seed as uint * 17]);

        for block_x in std::iter::range(-1, CHUNK_SIZE+1) {
            for block_z in std::iter::range(-1, CHUNK_SIZE+1) {
                let noise1 = perlin1.gen([
                    (p.x + block_x as f64) * 0.07,
                    (p.z + block_z as f64) * 0.04
                ]);
                let noise2 = perlin2.gen([
                    (p.x + block_x as f64) * 0.05,
                    (p.z + block_z as f64) * 0.05
                ]);
                let noise3 = perlin3.gen([
                    (p.x + block_x as f64) * 0.005,
                    (p.z + block_z as f64) * 0.005
                ]);
                let noise4 = perlin4.gen([
                    (p.x + block_x as f64) * 0.001,
                    (p.z + block_z as f64) * 0.001
                ]);

                let height = clamp(
                    (
                        base_height +
                        noise4 * 10.0 +
                        base_variance *
                            std::num::pow(noise3 + 1.0, 2.5) *
                            noise1
                    ),
                    1.0, (CHUNK_SIZE * (WORLD_HEIGHT as int) - 1) as f64);

                let dirt_height = 4.0 + noise2 * 8.0;

                for block_y in range(-1, CHUNK_SIZE+1) {
                    let mut blocktype = BlockAir;
                    let v = p.add_v(&Vec3::new(block_x as f64, block_y as f64, block_z as f64));

                    if v.y < height {
                        if v.y > height - dirt_height {
                            if v.y > height - 2.0 {
                                blocktype = BlockGrass;
                            } else {
                                blocktype = BlockDirt;
                            }
                        } else {
                            blocktype = BlockStone;
                        }
                    }

                    if blocktype == BlockAir && v.y < water_height {
                        blocktype = BlockWater;
                    }

                    if blocktype != BlockAir && blocktype != BlockWater && v.y > 1.0 {
                        let caviness = (0.3 * (1.0 - v.y/256.0)).clamp(&0.0, &1.0);
                        let cave = perlin1.gen([
                            (p.x + block_x as f64) * 0.05,
                            (p.y + block_y as f64) * 0.1,
                            (p.z + block_z as f64) * 0.05]) * 0.5 + 0.5;

                        if cave < caviness {
                            blocktype = BlockAir;
                        }
                    }

                    if blocktype != BlockAir {
                        let block = t.get_mut(block_x, block_y, block_z);
                        block.blocktype = blocktype;
                    }
                }
            }
        }

        let end_time = precise_time_ns();

        println!("terrain gen : {}us",
                (end_time - start_time)/1000);

        return t;
    }

    pub fn get<'a>(&'a self, x: int, y: int, z: int) -> &'a Block {
        &self.blocks[x+1][y+1][z+1]
    }

    pub fn get_mut<'a>(&'a mut self, x: int, y: int, z: int) -> &'a mut Block {
        &mut self.blocks[x+1][y+1][z+1]
    }

}
<commit_msg>terrain: warp cave domain<commit_after>// Copyright 2014 Rich Lane.

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

extern mod extra;
extern mod cgmath;
extern mod noise;

use std;
use std::num::clamp;

use extra::time::precise_time_ns;

use cgmath::array::Array;
use cgmath::vector::Vector;
use cgmath::vector::Vec3;

use noise::Perlin;

use CHUNK_SIZE;
use WORLD_HEIGHT;

#[repr(u8)]
#[deriving(Eq)]
pub enum BlockType {
    BlockAir = 0,
    BlockGrass = 1,
    BlockStone = 2,
    BlockDirt = 3,
    BlockWater = 4,
}

pub struct Block {
    blocktype: BlockType,
}

impl Block {
    pub fn is_opaque(&self) -> bool {
        self.blocktype != BlockAir
    }
}

pub struct Terrain {
    priv blocks: [[[Block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
}

impl Terrain {
    pub fn gen(seed: u32, p: Vec3<f64>) -> ~Terrain {
        let def_block = Block { blocktype: BlockAir };
        let mut t = ~Terrain {
            blocks: [[[def_block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
        };

        let water_height = 52.0;
        let base_height = 64.0;
        let base_variance = 10.0;

        let start_time = precise_time_ns();

        let perlin1 = Perlin::from_seed([seed as uint]);
        let perlin2 = Perlin::from_seed([seed as uint * 7]);
        let perlin3 = Perlin::from_seed([seed as uint * 13]);
        let perlin4 = Perlin::from_seed([seed as uint * 17]);

        for block_x in std::iter::range(-1, CHUNK_SIZE+1) {
            for block_z in std::iter::range(-1, CHUNK_SIZE+1) {
                let noise1 = perlin1.gen([
                    (p.x + block_x as f64) * 0.07,
                    (p.z + block_z as f64) * 0.04
                ]);
                let noise2 = perlin2.gen([
                    (p.x + block_x as f64) * 0.05,
                    (p.z + block_z as f64) * 0.05
                ]);
                let noise3 = perlin3.gen([
                    (p.x + block_x as f64) * 0.005,
                    (p.z + block_z as f64) * 0.005
                ]);
                let noise4 = perlin4.gen([
                    (p.x + block_x as f64) * 0.001,
                    (p.z + block_z as f64) * 0.001
                ]);

                let height = clamp(
                    (
                        base_height +
                        noise4 * 10.0 +
                        base_variance *
                            std::num::pow(noise3 + 1.0, 2.5) *
                            noise1
                    ),
                    1.0, (CHUNK_SIZE * (WORLD_HEIGHT as int) - 1) as f64);

                let dirt_height = 4.0 + noise2 * 8.0;

                for block_y in range(-1, CHUNK_SIZE+1) {
                    let mut blocktype = BlockAir;
                    let v = p.add_v(&Vec3::new(block_x as f64, block_y as f64, block_z as f64));

                    if v.y < height {
                        if v.y > height - dirt_height {
                            if v.y > height - 2.0 {
                                blocktype = BlockGrass;
                            } else {
                                blocktype = BlockDirt;
                            }
                        } else {
                            blocktype = BlockStone;
                        }
                    }

                    if blocktype == BlockAir && v.y < water_height {
                        blocktype = BlockWater;
                    }

                    if blocktype != BlockAir && blocktype != BlockWater && v.y > 1.0 {
                        let caviness = (0.5 - v.y.clamp(&30.0, &128.0) * 0.005);
                        let warp_v = Vec3::new(v.x * 0.01, v.y * 0.01, v.z * 0.01);
                        let warp = Vec3::new(
                            perlin2.gen(warp_v.as_slice()),
                            perlin3.gen(warp_v.as_slice()),
                            perlin4.gen(warp_v.as_slice())).mul_s(2.0);
                        let cave_v = v.mul_v(&Vec3::new(0.05, 0.08, 0.05)).add_v(&warp);
                        let cave = perlin1.gen(cave_v.as_slice()) * 0.5 + 0.5;

                        if cave < caviness {
                            blocktype = BlockAir;
                        }
                    }

                    if blocktype != BlockAir {
                        let block = t.get_mut(block_x, block_y, block_z);
                        block.blocktype = blocktype;
                    }
                }
            }
        }

        let end_time = precise_time_ns();

        println!("terrain gen : {}us",
                (end_time - start_time)/1000);

        return t;
    }

    pub fn get<'a>(&'a self, x: int, y: int, z: int) -> &'a Block {
        &self.blocks[x+1][y+1][z+1]
    }

    pub fn get_mut<'a>(&'a mut self, x: int, y: int, z: int) -> &'a mut Block {
        &mut self.blocks[x+1][y+1][z+1]
    }

}
<|endoftext|>


<commit_before>
macro_rules! return_if {
  ($e:expr, $r:expr) => {
    if $e {
      return $r;
    }
  }
}

pub struct Square {
  a: usize,
  data: Vec<usize>
}

enum Diagonal {
  First,
  Second
}

enum SquareLine {
  Row(usize),
  Col(usize),
  Diag(Diagonal)
}

impl Square {
  pub fn new(data: Vec<usize>) -> Square {
    let len = data.len();
    let a_candidate = (len as f64).sqrt().floor() as usize;

    assert_eq!(a_candidate * a_candidate, len);

    Square {
      a: a_candidate,
      data: data
    }
  }

  pub fn is_magic(&self) -> bool {
    let first_sum = self.row_sum(0);

    for i in 1..self.a {
      let sum = self.row_sum(i);
      return_if!(sum != first_sum, false);
    }

    for i in 0..self.a {
      let sum = self.col_sum(i);
      return_if!(sum != first_sum, false);
    }

    {
      let sum = self.diag_sum(&Diagonal::First);
      return_if!(sum != first_sum, false);
    }

    {
      let sum = self.diag_sum(&Diagonal::Second);
      return_if!(sum != first_sum, false);
    }

    return true;
  }

  fn sum_of(&self, line: &SquareLine) -> usize {
    match line {
      &SquareLine::Row(r) => self.row_sum(r),
      &SquareLine::Col(c) => self.col_sum(c),
      &SquareLine::Diag(ref d) => self.diag_sum(d)
    }
  }

  fn row_sum(&self, r: usize) -> usize {
    let mut sum = 0;

    let start = r * self.a;

    for i in 0..self.a {
      sum = sum + self.data[start + i];
    }

    sum
  }

  fn col_sum(&self, u: usize) -> usize {
    let mut sum = 0;

    for i in 0..self.a {
      sum = sum + self.data[u + self.a * i];
    }

    sum
  }

  fn diag_sum(&self, d: &Diagonal) -> usize {
    match d {
      &Diagonal::First => self.diag_sum_first(),
      &Diagonal::Second => self.diag_sum_second()
    }
  }

  fn diag_sum_first(&self) -> usize {
    let mut sum = 0;

    let jump = self.a + 1;

    for i in 0..self.a {
      sum = sum + self.data[i * jump];
    }

    sum
  }

  fn diag_sum_second(&self) -> usize {
    let mut sum = 0;

    let start = self.a - 1;

    for i in 0..self.a {
      let index = start + i * start;
      println!("diag2: i: {} index: {} data: {}", i, index, self.data[index]);
      sum = sum + self.data[index]
    }

    sum
  }

}

#[cfg(test)]
mod test {

  use super::*;

  #[test]
  #[should_panic]
  fn test_non_square() {
    Square::new(vec![1, 2]);
  }

  #[test]
  fn test_first_example() {
    let square = Square::new(vec![8, 1, 6, 3, 5, 7, 4, 9, 2]);

    assert_eq!(true, square.is_magic());
  }

  #[test]
  fn test_second_example() {
    let square = Square::new(vec![2, 7, 6, 9, 5, 1, 4, 3, 8]);

    assert_eq!(true, square.is_magic());
  }

  #[test]
  fn test_third_example() {
    let square = Square::new(vec![3, 5, 7, 8, 1, 6, 4, 9, 2]);

    assert_eq!(false, square.is_magic());
  }

  #[test]
  fn test_fourth_example() {
    let square = Square::new(vec![8, 1, 6, 7, 5, 3, 4, 9, 2]);

    assert_eq!(false, square.is_magic());
  }
}
<commit_msg>iterators<commit_after>
macro_rules! return_if {
  ($e:expr, $r:expr) => {
    if $e {
      return $r;
    }
  }
}

pub struct Square {
  a: usize,
  data: Vec<usize>
}

pub enum Diagonal {
  First,
  Second
}

pub enum SquareLine {
  Row(usize),
  Col(usize),
  Diag(Diagonal)
}

pub struct SquareIter<'a> {
  square: &'a Square,
  start: usize,
  jump: usize,
  i: usize
}

impl<'a> Iterator for SquareIter<'a> {
  type Item = &'a usize;

  fn next(&mut self) -> Option<&'a usize> {

    if self.i >= self.square.a {
      return None;
    }

    let value = &self.square.data[self.start + self.i * self.jump];
    self.i = self.i + 1;

    Some(value)

  }
}

impl Square {
  pub fn new(data: Vec<usize>) -> Square {
    let len = data.len();
    let a_candidate = (len as f64).sqrt().floor() as usize;

    assert_eq!(a_candidate * a_candidate, len);

    Square {
      a: a_candidate,
      data: data
    }
  }

  pub fn is_magic(&self) -> bool {
    for i in 0..self.a {
      let row_sum = self.row_sum(i);
      let col_sum = self.col_sum(i);
      return_if!(row_sum != 15, false);
      return_if!(col_sum != 15, false);
    }

    {
      let sum = self.diag_sum(&Diagonal::First);
      return_if!(sum != 15, false);
    }

    {
      let sum = self.diag_sum(&Diagonal::Second);
      return_if!(sum != 15, false);
    }

    return true;
  }

  pub fn sum_of(&self, line: &SquareLine) -> usize {
    self.get_iter(line).fold(0, |acc, &x| acc + x)
  }

  pub fn get_iter<'a, 'b>(&'a self, line: &'b SquareLine) -> SquareIter<'a> {
    match line {
      &SquareLine::Row(r) => self.row(r),
      &SquareLine::Col(c) => self.col(c),
      &SquareLine::Diag(ref d) => self.diag(d)
    }
  }

  pub fn row<'a>(&'a self, r: usize) -> SquareIter<'a> {
    SquareIter {
      square: self,
      start: r * self.a,
      jump: 1,
      i: 0
    }
  }

  pub fn col<'a>(&'a self, c: usize) -> SquareIter<'a> {
    SquareIter {
      square: self,
      start: c,
      jump: self.a,
      i: 0
    }
  }

  pub fn diag<'a>(&'a self, d: &Diagonal) -> SquareIter<'a> {
    match d {
      &Diagonal::First => SquareIter {
        square: self,
        start: 0,
        jump: self.a + 1,
        i: 0
      },

      &Diagonal::Second => SquareIter {
        square: self,
        start: self.a - 1,
        jump: self.a - 1,
        i: 0
      }
    }
  }

  fn row_sum(&self, r: usize) -> usize {
    self.row(r).fold(0, |acc, &x| acc + x)
  }

  fn col_sum(&self, c: usize) -> usize {
    self.col(c).fold(0, |acc, &x| acc + x)
  }

  fn diag_sum(&self, d: &Diagonal) -> usize {
    self.diag(d).fold(0, |acc, &x| acc + x)
  }

}

#[cfg(test)]
mod test {

  use super::*;

  fn test_square() -> Square {
    Square::new(vec![8, 1, 6, 3, 5, 7, 4, 9, 2])
  }

  #[test]
  #[should_panic]
  fn test_non_square() {
    Square::new(vec![1, 2]);
  }

  #[test]
  fn test_row_iterator() {
    let square = test_square();

    assert_eq!(vec![8, 1, 6], square.row(0).map(|v| v.clone()).collect::<Vec<usize>>());
  }

  #[test]
  fn test_col_iterator() {
    let square = test_square();

    assert_eq!(vec![8, 3, 4], square.col(0).map(|v| v.clone()).collect::<Vec<usize>>());
  }

  #[test]
  fn test_diag_iterator() {
    let square = test_square();

    assert_eq!(vec![8, 5, 2], square.diag(&Diagonal::First).map(|v| v.clone()).collect::<Vec<usize>>());
    assert_eq!(vec![6, 5, 4], square.diag(&Diagonal::Second).map(|v| v.clone()).collect::<Vec<usize>>());
  }

  #[test]
  fn test_first_example() {
    let square = Square::new(vec![8, 1, 6, 3, 5, 7, 4, 9, 2]);

    assert_eq!(true, square.is_magic());
  }

  #[test]
  fn test_second_example() {
    let square = Square::new(vec![2, 7, 6, 9, 5, 1, 4, 3, 8]);

    assert_eq!(true, square.is_magic());
  }

  #[test]
  fn test_third_example() {
    let square = Square::new(vec![3, 5, 7, 8, 1, 6, 4, 9, 2]);

    assert_eq!(false, square.is_magic());
  }

  #[test]
  fn test_fourth_example() {
    let square = Square::new(vec![8, 1, 6, 7, 5, 3, 4, 9, 2]);

    assert_eq!(false, square.is_magic());
  }
}
<|endoftext|>


<commit_before>use yaml_rust as yaml;
use source::Source;
use std::error::Error;
use std::fmt;
use std::collections::{BTreeMap, HashMap};
use std::mem;
use value::{Value, ValueKind};

pub fn parse(uri: Option<&String>, text: &str) -> Result<HashMap<String, Value>, Box<Error>> {
    // Parse a YAML object from file
    let mut docs = yaml::YamlLoader::load_from_str(text)?;
    let root = match docs.len() {
        0 => yaml::Yaml::Hash(BTreeMap::new()),
        1 => mem::replace(&mut docs[0], yaml::Yaml::Null),
        n => {
            return Err(Box::new(MultipleDocumentsError(n)));
        }
    };

    // TODO: Have a proper error fire if the root of a file is ever not a Table
    let value = from_yaml_value(uri, &root);
    match value.kind {
        ValueKind::Table(map) => Ok(map),

        _ => Ok(HashMap::new()),
    }
}

fn from_yaml_value(uri: Option<&String>, value: &yaml::Yaml) -> Value {
    match *value {
        yaml::Yaml::String(ref value) => Value::new(uri, ValueKind::String(value.clone())),
        yaml::Yaml::Real(ref value) => {
            Value::new(uri, ValueKind::Float(value.parse::<f64>().unwrap()))
        }
        yaml::Yaml::Integer(value) => Value::new(uri, ValueKind::Integer(value)),
        yaml::Yaml::Boolean(value) => Value::new(uri, ValueKind::Boolean(value)),
        yaml::Yaml::Hash(ref table) => {
            let mut m = HashMap::new();
            for (key, value) in table {
                if let Some(k) = key.as_str() {
                    m.insert(k.to_lowercase().to_owned(), from_yaml_value(uri, value));
                }
                // TODO: should we do anything for non-string keys?
            }
            Value::new(uri, ValueKind::Table(m))
        }
        yaml::Yaml::Array(ref array) => {
            let mut l = Vec::new();

            for value in array {
                l.push(from_yaml_value(uri, value));
            }

            Value::new(uri, ValueKind::Array(l))
        }

        yaml::Yaml::Null => Value::new(uri, ValueKind::Nil),

        // TODO: how should we BadValue?
        _ => {
            unimplemented!();
        }

    }
}

#[derive(Debug, Copy, Clone)]
struct MultipleDocumentsError(usize);

impl fmt::Display for MultipleDocumentsError {
    fn fmt(&self, format: &mut fmt::Formatter) -> fmt::Result {
        write!(format, "Got {} YAML documents, expected 1", self.0)
    }
}

impl Error for MultipleDocumentsError {
    fn description(&self) -> &str {
        "More than one YAML document provided"
    }
}
<commit_msg>Remove last unimplemented!<commit_after>use yaml_rust as yaml;
use source::Source;
use std::error::Error;
use std::fmt;
use std::collections::{BTreeMap, HashMap};
use std::mem;
use value::{Value, ValueKind};

pub fn parse(uri: Option<&String>, text: &str) -> Result<HashMap<String, Value>, Box<Error>> {
    // Parse a YAML object from file
    let mut docs = yaml::YamlLoader::load_from_str(text)?;
    let root = match docs.len() {
        0 => yaml::Yaml::Hash(BTreeMap::new()),
        1 => mem::replace(&mut docs[0], yaml::Yaml::Null),
        n => {
            return Err(Box::new(MultipleDocumentsError(n)));
        }
    };

    // TODO: Have a proper error fire if the root of a file is ever not a Table
    let value = from_yaml_value(uri, &root);
    match value.kind {
        ValueKind::Table(map) => Ok(map),

        _ => Ok(HashMap::new()),
    }
}

fn from_yaml_value(uri: Option<&String>, value: &yaml::Yaml) -> Value {
    match *value {
        yaml::Yaml::String(ref value) => Value::new(uri, ValueKind::String(value.clone())),
        yaml::Yaml::Real(ref value) => {
            Value::new(uri, ValueKind::Float(value.parse::<f64>().unwrap()))
        }
        yaml::Yaml::Integer(value) => Value::new(uri, ValueKind::Integer(value)),
        yaml::Yaml::Boolean(value) => Value::new(uri, ValueKind::Boolean(value)),
        yaml::Yaml::Hash(ref table) => {
            let mut m = HashMap::new();
            for (key, value) in table {
                if let Some(k) = key.as_str() {
                    m.insert(k.to_lowercase().to_owned(), from_yaml_value(uri, value));
                }
                // TODO: should we do anything for non-string keys?
            }
            Value::new(uri, ValueKind::Table(m))
        }
        yaml::Yaml::Array(ref array) => {
            let mut l = Vec::new();

            for value in array {
                l.push(from_yaml_value(uri, value));
            }

            Value::new(uri, ValueKind::Array(l))
        }

        // 1. Yaml NULL
        // 2. BadValue – It shouldn't be possible to hit BadValue as this only happens when
        //               using the index trait badly or on a type error but we send back nil.
        // 3. Alias – No idea what to do with this and there is a note in the lib that its
        //            not fully supported yet anyway
        _ => Value::new(uri, ValueKind::Nil),
    }
}

#[derive(Debug, Copy, Clone)]
struct MultipleDocumentsError(usize);

impl fmt::Display for MultipleDocumentsError {
    fn fmt(&self, format: &mut fmt::Formatter) -> fmt::Result {
        write!(format, "Got {} YAML documents, expected 1", self.0)
    }
}

impl Error for MultipleDocumentsError {
    fn description(&self) -> &str {
        "More than one YAML document provided"
    }
}
<|endoftext|>


<commit_before>use crate::Stream;

use core::future::Future;
use core::marker::PhantomPinned;
use core::mem;
use core::pin::Pin;
use core::task::{Context, Poll};
use pin_project_lite::pin_project;

// Do not export this struct until `FromStream` can be unsealed.
pin_project! {
    /// Future returned by the [`collect`](super::StreamExt::collect) method.
    #[must_use = "futures do nothing unless you `.await` or poll them"]
    #[derive(Debug)]
    pub struct Collect<T, U>
    where
        T: Stream,
        U: FromStream<T::Item>,
    {
        #[pin]
        stream: T,
        collection: U::InternalCollection,
        // Make this future `!Unpin` for compatibility with async trait methods.
        #[pin]
        _pin: PhantomPinned,
    }
}

/// Convert from a [`Stream`](crate::Stream).
///
/// This trait is not intended to be used directly. Instead, call
/// [`StreamExt::collect()`](super::StreamExt::collect).
///
/// # Implementing
///
/// Currently, this trait may not be implemented by third parties. The trait is
/// sealed in order to make changes in the future. Stabilization is pending
/// enhancements to the Rust language.
pub trait FromStream<T>: sealed::FromStreamPriv<T> {}

impl<T, U> Collect<T, U>
where
    T: Stream,
    U: FromStream<T::Item>,
{
    pub(super) fn new(stream: T) -> Collect<T, U> {
        let (lower, upper) = stream.size_hint();
        let collection = U::initialize(sealed::Internal, lower, upper);

        Collect {
            stream,
            collection,
            _pin: PhantomPinned,
        }
    }
}

impl<T, U> Future for Collect<T, U>
where
    T: Stream,
    U: FromStream<T::Item>,
{
    type Output = U;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<U> {
        use Poll::Ready;

        loop {
            let mut me = self.as_mut().project();

            let item = match ready!(me.stream.poll_next(cx)) {
                Some(item) => item,
                None => {
                    return Ready(U::finalize(sealed::Internal, &mut me.collection));
                }
            };

            if !U::extend(sealed::Internal, &mut me.collection, item) {
                return Ready(U::finalize(sealed::Internal, &mut me.collection));
            }
        }
    }
}

// ===== FromStream implementations

impl FromStream<()> for () {}

impl sealed::FromStreamPriv<()> for () {
    type InternalCollection = ();

    fn initialize(_: sealed::Internal, _lower: usize, _upper: Option<usize>) {}

    fn extend(_: sealed::Internal, _collection: &mut (), _item: ()) -> bool {
        true
    }

    fn finalize(_: sealed::Internal, _collection: &mut ()) {}
}

impl<T: AsRef<str>> FromStream<T> for String {}

impl<T: AsRef<str>> sealed::FromStreamPriv<T> for String {
    type InternalCollection = String;

    fn initialize(_: sealed::Internal, _lower: usize, _upper: Option<usize>) -> String {
        String::new()
    }

    fn extend(_: sealed::Internal, collection: &mut String, item: T) -> bool {
        collection.push_str(item.as_ref());
        true
    }

    fn finalize(_: sealed::Internal, collection: &mut String) -> String {
        mem::replace(collection, String::new())
    }
}

impl<T> FromStream<T> for Vec<T> {}

impl<T> sealed::FromStreamPriv<T> for Vec<T> {
    type InternalCollection = Vec<T>;

    fn initialize(_: sealed::Internal, lower: usize, _upper: Option<usize>) -> Vec<T> {
        Vec::with_capacity(lower)
    }

    fn extend(_: sealed::Internal, collection: &mut Vec<T>, item: T) -> bool {
        collection.push(item);
        true
    }

    fn finalize(_: sealed::Internal, collection: &mut Vec<T>) -> Vec<T> {
        mem::replace(collection, vec![])
    }
}

impl<T> FromStream<T> for Box<[T]> {}

impl<T> sealed::FromStreamPriv<T> for Box<[T]> {
    type InternalCollection = Vec<T>;

    fn initialize(_: sealed::Internal, lower: usize, upper: Option<usize>) -> Vec<T> {
        <Vec<T> as sealed::FromStreamPriv<T>>::initialize(sealed::Internal, lower, upper)
    }

    fn extend(_: sealed::Internal, collection: &mut Vec<T>, item: T) -> bool {
        <Vec<T> as sealed::FromStreamPriv<T>>::extend(sealed::Internal, collection, item)
    }

    fn finalize(_: sealed::Internal, collection: &mut Vec<T>) -> Box<[T]> {
        <Vec<T> as sealed::FromStreamPriv<T>>::finalize(sealed::Internal, collection)
            .into_boxed_slice()
    }
}

impl<T, U, E> FromStream<Result<T, E>> for Result<U, E> where U: FromStream<T> {}

impl<T, U, E> sealed::FromStreamPriv<Result<T, E>> for Result<U, E>
where
    U: FromStream<T>,
{
    type InternalCollection = Result<U::InternalCollection, E>;

    fn initialize(
        _: sealed::Internal,
        lower: usize,
        upper: Option<usize>,
    ) -> Result<U::InternalCollection, E> {
        Ok(U::initialize(sealed::Internal, lower, upper))
    }

    fn extend(
        _: sealed::Internal,
        collection: &mut Self::InternalCollection,
        item: Result<T, E>,
    ) -> bool {
        assert!(collection.is_ok());
        match item {
            Ok(item) => {
                let collection = collection.as_mut().ok().expect("invalid state");
                U::extend(sealed::Internal, collection, item)
            }
            Err(err) => {
                *collection = Err(err);
                false
            }
        }
    }

    fn finalize(_: sealed::Internal, collection: &mut Self::InternalCollection) -> Result<U, E> {
        if let Ok(collection) = collection.as_mut() {
            Ok(U::finalize(sealed::Internal, collection))
        } else {
            let res = mem::replace(collection, Ok(U::initialize(sealed::Internal, 0, Some(0))));

            if let Err(err) = res {
                Err(err)
            } else {
                unreachable!();
            }
        }
    }
}

pub(crate) mod sealed {
    #[doc(hidden)]
    pub trait FromStreamPriv<T> {
        /// Intermediate type used during collection process
        ///
        /// The name of this type is internal and cannot be relied upon.
        type InternalCollection;

        /// Initialize the collection
        fn initialize(
            internal: Internal,
            lower: usize,
            upper: Option<usize>,
        ) -> Self::InternalCollection;

        /// Extend the collection with the received item
        ///
        /// Return `true` to continue streaming, `false` complete collection.
        fn extend(internal: Internal, collection: &mut Self::InternalCollection, item: T) -> bool;

        /// Finalize collection into target type.
        fn finalize(internal: Internal, collection: &mut Self::InternalCollection) -> Self;
    }

    #[allow(missing_debug_implementations)]
    pub struct Internal;
}
<commit_msg>chore: fix new clippy complaint (#3915)<commit_after>use crate::Stream;

use core::future::Future;
use core::marker::PhantomPinned;
use core::mem;
use core::pin::Pin;
use core::task::{Context, Poll};
use pin_project_lite::pin_project;

// Do not export this struct until `FromStream` can be unsealed.
pin_project! {
    /// Future returned by the [`collect`](super::StreamExt::collect) method.
    #[must_use = "futures do nothing unless you `.await` or poll them"]
    #[derive(Debug)]
    pub struct Collect<T, U>
    where
        T: Stream,
        U: FromStream<T::Item>,
    {
        #[pin]
        stream: T,
        collection: U::InternalCollection,
        // Make this future `!Unpin` for compatibility with async trait methods.
        #[pin]
        _pin: PhantomPinned,
    }
}

/// Convert from a [`Stream`](crate::Stream).
///
/// This trait is not intended to be used directly. Instead, call
/// [`StreamExt::collect()`](super::StreamExt::collect).
///
/// # Implementing
///
/// Currently, this trait may not be implemented by third parties. The trait is
/// sealed in order to make changes in the future. Stabilization is pending
/// enhancements to the Rust language.
pub trait FromStream<T>: sealed::FromStreamPriv<T> {}

impl<T, U> Collect<T, U>
where
    T: Stream,
    U: FromStream<T::Item>,
{
    pub(super) fn new(stream: T) -> Collect<T, U> {
        let (lower, upper) = stream.size_hint();
        let collection = U::initialize(sealed::Internal, lower, upper);

        Collect {
            stream,
            collection,
            _pin: PhantomPinned,
        }
    }
}

impl<T, U> Future for Collect<T, U>
where
    T: Stream,
    U: FromStream<T::Item>,
{
    type Output = U;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<U> {
        use Poll::Ready;

        loop {
            let mut me = self.as_mut().project();

            let item = match ready!(me.stream.poll_next(cx)) {
                Some(item) => item,
                None => {
                    return Ready(U::finalize(sealed::Internal, &mut me.collection));
                }
            };

            if !U::extend(sealed::Internal, &mut me.collection, item) {
                return Ready(U::finalize(sealed::Internal, &mut me.collection));
            }
        }
    }
}

// ===== FromStream implementations

impl FromStream<()> for () {}

impl sealed::FromStreamPriv<()> for () {
    type InternalCollection = ();

    fn initialize(_: sealed::Internal, _lower: usize, _upper: Option<usize>) {}

    fn extend(_: sealed::Internal, _collection: &mut (), _item: ()) -> bool {
        true
    }

    fn finalize(_: sealed::Internal, _collection: &mut ()) {}
}

impl<T: AsRef<str>> FromStream<T> for String {}

impl<T: AsRef<str>> sealed::FromStreamPriv<T> for String {
    type InternalCollection = String;

    fn initialize(_: sealed::Internal, _lower: usize, _upper: Option<usize>) -> String {
        String::new()
    }

    fn extend(_: sealed::Internal, collection: &mut String, item: T) -> bool {
        collection.push_str(item.as_ref());
        true
    }

    fn finalize(_: sealed::Internal, collection: &mut String) -> String {
        mem::take(collection)
    }
}

impl<T> FromStream<T> for Vec<T> {}

impl<T> sealed::FromStreamPriv<T> for Vec<T> {
    type InternalCollection = Vec<T>;

    fn initialize(_: sealed::Internal, lower: usize, _upper: Option<usize>) -> Vec<T> {
        Vec::with_capacity(lower)
    }

    fn extend(_: sealed::Internal, collection: &mut Vec<T>, item: T) -> bool {
        collection.push(item);
        true
    }

    fn finalize(_: sealed::Internal, collection: &mut Vec<T>) -> Vec<T> {
        mem::take(collection)
    }
}

impl<T> FromStream<T> for Box<[T]> {}

impl<T> sealed::FromStreamPriv<T> for Box<[T]> {
    type InternalCollection = Vec<T>;

    fn initialize(_: sealed::Internal, lower: usize, upper: Option<usize>) -> Vec<T> {
        <Vec<T> as sealed::FromStreamPriv<T>>::initialize(sealed::Internal, lower, upper)
    }

    fn extend(_: sealed::Internal, collection: &mut Vec<T>, item: T) -> bool {
        <Vec<T> as sealed::FromStreamPriv<T>>::extend(sealed::Internal, collection, item)
    }

    fn finalize(_: sealed::Internal, collection: &mut Vec<T>) -> Box<[T]> {
        <Vec<T> as sealed::FromStreamPriv<T>>::finalize(sealed::Internal, collection)
            .into_boxed_slice()
    }
}

impl<T, U, E> FromStream<Result<T, E>> for Result<U, E> where U: FromStream<T> {}

impl<T, U, E> sealed::FromStreamPriv<Result<T, E>> for Result<U, E>
where
    U: FromStream<T>,
{
    type InternalCollection = Result<U::InternalCollection, E>;

    fn initialize(
        _: sealed::Internal,
        lower: usize,
        upper: Option<usize>,
    ) -> Result<U::InternalCollection, E> {
        Ok(U::initialize(sealed::Internal, lower, upper))
    }

    fn extend(
        _: sealed::Internal,
        collection: &mut Self::InternalCollection,
        item: Result<T, E>,
    ) -> bool {
        assert!(collection.is_ok());
        match item {
            Ok(item) => {
                let collection = collection.as_mut().ok().expect("invalid state");
                U::extend(sealed::Internal, collection, item)
            }
            Err(err) => {
                *collection = Err(err);
                false
            }
        }
    }

    fn finalize(_: sealed::Internal, collection: &mut Self::InternalCollection) -> Result<U, E> {
        if let Ok(collection) = collection.as_mut() {
            Ok(U::finalize(sealed::Internal, collection))
        } else {
            let res = mem::replace(collection, Ok(U::initialize(sealed::Internal, 0, Some(0))));

            if let Err(err) = res {
                Err(err)
            } else {
                unreachable!();
            }
        }
    }
}

pub(crate) mod sealed {
    #[doc(hidden)]
    pub trait FromStreamPriv<T> {
        /// Intermediate type used during collection process
        ///
        /// The name of this type is internal and cannot be relied upon.
        type InternalCollection;

        /// Initialize the collection
        fn initialize(
            internal: Internal,
            lower: usize,
            upper: Option<usize>,
        ) -> Self::InternalCollection;

        /// Extend the collection with the received item
        ///
        /// Return `true` to continue streaming, `false` complete collection.
        fn extend(internal: Internal, collection: &mut Self::InternalCollection, item: T) -> bool;

        /// Finalize collection into target type.
        fn finalize(internal: Internal, collection: &mut Self::InternalCollection) -> Self;
    }

    #[allow(missing_debug_implementations)]
    pub struct Internal;
}
<|endoftext|>