<commit_before>//! Utilities for building HTTP endpoints in a library-agnostic manner

use serde::ser;
use serde::ser::SerializeMap;

use {GraphQLError, GraphQLType, RootNode, Value, Variables};
use ast::InputValue;
use executor::ExecutionError;

/// The expected structure of the decoded JSON document for either POST or GET requests.
///
/// For POST, you can use Serde to deserialize the incoming JSON data directly
/// into this struct - it derives Deserialize for exactly this reason.
///
/// For GET, you will need to parse the query string and exctract "query",
/// "operationName", and "variables" manually.
#[derive(Deserialize, Clone)]
pub struct GraphQLRequest {
    query: String,
    #[serde(rename = "operationName")]
    operation_name: Option<String>,
    variables: Option<InputValue>,
}

impl GraphQLRequest {
    fn operation_name(&self) -> Option<&str> {
        self.operation_name.as_ref().map(|oper_name| &**oper_name)
    }

    fn variables(&self) -> Variables {
        self.variables
            .as_ref()
            .and_then(|iv| {
                iv.to_object_value().map(|o| {
                    o.into_iter()
                        .map(|(k, v)| (k.to_owned(), v.clone()))
                        .collect()
                })
            })
            .unwrap_or_default()
    }

    /// Construct a new GraphQL request from parts
    pub fn new(
        query: String,
        operation_name: Option<String>,
        variables: Option<InputValue>,
    ) -> GraphQLRequest {
        GraphQLRequest {
            query: query,
            operation_name: operation_name,
            variables: variables,
        }
    }

    /// Execute a GraphQL request using the specified schema and context
    ///
    /// This is a simple wrapper around the `execute` function exposed at the
    /// top level of this crate.
    pub fn execute<'a, CtxT, QueryT, MutationT>(
        &'a self,
        root_node: &RootNode<QueryT, MutationT>,
        context: &CtxT,
    ) -> GraphQLResponse<'a>
    where
        QueryT: GraphQLType<Context = CtxT>,
        MutationT: GraphQLType<Context = CtxT>,
    {
        GraphQLResponse(::execute(
            &self.query,
            self.operation_name(),
            root_node,
            &self.variables(),
            context,
        ))
    }
}

/// Simple wrapper around the result from executing a GraphQL query
///
/// This struct implements Serialize, so you can simply serialize this
/// to JSON and send it over the wire. Use the `is_ok` method to determine
/// whether to send a 200 or 400 HTTP status code.
pub struct GraphQLResponse<'a>(Result<(Value, Vec<ExecutionError>), GraphQLError<'a>>);

impl<'a> GraphQLResponse<'a> {
    /// Was the request successful or not?
    ///
    /// Note that there still might be errors in the response even though it's
    /// considered OK. This is by design in GraphQL.
    pub fn is_ok(&self) -> bool {
        self.0.is_ok()
    }
}

impl<'a> ser::Serialize for GraphQLResponse<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        match self.0 {
            Ok((ref res, ref err)) => {
                let mut map = try!(serializer.serialize_map(None));

                try!(map.serialize_key("data"));
                try!(map.serialize_value(res));

                if !err.is_empty() {
                    try!(map.serialize_key("errors"));
                    try!(map.serialize_value(err));
                }

                map.end()
            }
            Err(ref err) => {
                let mut map = try!(serializer.serialize_map(Some(1)));
                try!(map.serialize_key("errors"));
                try!(map.serialize_value(err));
                map.end()
            }
        }
    }
}

#[cfg(any(test, feature = "expose-test-schema"))]
pub mod tests {
    use serde_json::Value as Json;
    use serde_json;

    pub struct TestResponse {
        pub status_code: i32,
        pub body: Option<String>,
        pub content_type: String,
    }

    pub trait HTTPIntegration {
        fn get(&self, url: &str) -> TestResponse;
        fn post(&self, url: &str, body: &str) -> TestResponse;
    }

    pub fn run_http_test_suite<T: HTTPIntegration>(integration: &T) {
        println!("Running HTTP Test suite for integration");

        println!("  - test_simple_get");
        test_simple_get(integration);

        println!("  - test_encoded_get");
        test_encoded_get(integration);

        println!("  - test_get_with_variables");
        test_get_with_variables(integration);

        println!("  - test_simple_post");
        test_simple_post(integration);
    }

    fn unwrap_json_response(response: &TestResponse) -> Json {
        serde_json::from_str::<Json>(
            response
                .body
                .as_ref()
                .expect("No data returned from request"),
        ).expect("Could not parse JSON object")
    }

    fn test_simple_get<T: HTTPIntegration>(integration: &T) {
        let response = integration.get("/?query={hero{name}}");

        assert_eq!(response.status_code, 200);
        assert_eq!(response.content_type.as_str(), "application/json");

        assert_eq!(
            unwrap_json_response(&response),
            serde_json::from_str::<Json>(r#"{"data": {"hero": {"name": "R2-D2"}}}"#)
                .expect("Invalid JSON constant in test")
        );
    }

    fn test_encoded_get<T: HTTPIntegration>(integration: &T) {
        let response = integration.get(
            "/?query=query%20{%20%20%20human(id:%20\"1000\")%20{%20%20%20%20%20id,%20%20%20%20%20name,%20%20%20%20%20appearsIn,%20%20%20%20%20homePlanet%20%20%20}%20}");

        assert_eq!(response.status_code, 200);
        assert_eq!(response.content_type.as_str(), "application/json");

        assert_eq!(
            unwrap_json_response(&response),
            serde_json::from_str::<Json>(
                r#"{
                    "data": {
                        "human": {
                            "appearsIn": [
                                "NEW_HOPE",
                                "EMPIRE",
                                "JEDI"
                                ],
                                "homePlanet": "Tatooine",
                                "name": "Luke Skywalker",
                                "id": "1000"
                            }
                        }
                    }"#
            ).expect("Invalid JSON constant in test")
        );
    }

    fn test_get_with_variables<T: HTTPIntegration>(integration: &T) {
        let response = integration.get(
            "/?query=query($id:%20String!)%20{%20%20%20human(id:%20$id)%20{%20%20%20%20%20id,%20%20%20%20%20name,%20%20%20%20%20appearsIn,%20%20%20%20%20homePlanet%20%20%20}%20}&variables={%20%20%20\"id\":%20%20\"1000\"%20}");

        assert_eq!(response.status_code, 200);
        assert_eq!(response.content_type, "application/json");

        assert_eq!(
            unwrap_json_response(&response),
            serde_json::from_str::<Json>(
                r#"{
                    "data": {
                        "human": {
                            "appearsIn": [
                                "NEW_HOPE",
                                "EMPIRE",
                                "JEDI"
                                ],
                                "homePlanet": "Tatooine",
                                "name": "Luke Skywalker",
                                "id": "1000"
                            }
                        }
                    }"#
            ).expect("Invalid JSON constant in test")
        );
    }

    fn test_simple_post<T: HTTPIntegration>(integration: &T) {
        let response = integration.post("/", r#"{"query": "{hero{name}}"}"#);

        assert_eq!(response.status_code, 200);
        assert_eq!(response.content_type, "application/json");

        assert_eq!(
            unwrap_json_response(&response),
            serde_json::from_str::<Json>(r#"{"data": {"hero": {"name": "R2-D2"}}}"#)
                .expect("Invalid JSON constant in test")
        );
    }
}
<commit_msg>Serialize on GraphQLRequest<commit_after>//! Utilities for building HTTP endpoints in a library-agnostic manner

use serde::ser;
use serde::ser::SerializeMap;

use {GraphQLError, GraphQLType, RootNode, Value, Variables};
use ast::InputValue;
use executor::ExecutionError;

/// The expected structure of the decoded JSON document for either POST or GET requests.
///
/// For POST, you can use Serde to deserialize the incoming JSON data directly
/// into this struct - it derives Deserialize for exactly this reason.
///
/// For GET, you will need to parse the query string and exctract "query",
/// "operationName", and "variables" manually.
#[derive(Deserialize, Clone, Serialize)]
pub struct GraphQLRequest {
    query: String,
    #[serde(rename = "operationName")]
    operation_name: Option<String>,
    variables: Option<InputValue>,
}

impl GraphQLRequest {
    fn operation_name(&self) -> Option<&str> {
        self.operation_name.as_ref().map(|oper_name| &**oper_name)
    }

    fn variables(&self) -> Variables {
        self.variables
            .as_ref()
            .and_then(|iv| {
                iv.to_object_value().map(|o| {
                    o.into_iter()
                        .map(|(k, v)| (k.to_owned(), v.clone()))
                        .collect()
                })
            })
            .unwrap_or_default()
    }

    /// Construct a new GraphQL request from parts
    pub fn new(
        query: String,
        operation_name: Option<String>,
        variables: Option<InputValue>,
    ) -> GraphQLRequest {
        GraphQLRequest {
            query: query,
            operation_name: operation_name,
            variables: variables,
        }
    }

    /// Execute a GraphQL request using the specified schema and context
    ///
    /// This is a simple wrapper around the `execute` function exposed at the
    /// top level of this crate.
    pub fn execute<'a, CtxT, QueryT, MutationT>(
        &'a self,
        root_node: &RootNode<QueryT, MutationT>,
        context: &CtxT,
    ) -> GraphQLResponse<'a>
    where
        QueryT: GraphQLType<Context = CtxT>,
        MutationT: GraphQLType<Context = CtxT>,
    {
        GraphQLResponse(::execute(
            &self.query,
            self.operation_name(),
            root_node,
            &self.variables(),
            context,
        ))
    }
}

/// Simple wrapper around the result from executing a GraphQL query
///
/// This struct implements Serialize, so you can simply serialize this
/// to JSON and send it over the wire. Use the `is_ok` method to determine
/// whether to send a 200 or 400 HTTP status code.
pub struct GraphQLResponse<'a>(Result<(Value, Vec<ExecutionError>), GraphQLError<'a>>);

impl<'a> GraphQLResponse<'a> {
    /// Was the request successful or not?
    ///
    /// Note that there still might be errors in the response even though it's
    /// considered OK. This is by design in GraphQL.
    pub fn is_ok(&self) -> bool {
        self.0.is_ok()
    }
}

impl<'a> ser::Serialize for GraphQLResponse<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        match self.0 {
            Ok((ref res, ref err)) => {
                let mut map = try!(serializer.serialize_map(None));

                try!(map.serialize_key("data"));
                try!(map.serialize_value(res));

                if !err.is_empty() {
                    try!(map.serialize_key("errors"));
                    try!(map.serialize_value(err));
                }

                map.end()
            }
            Err(ref err) => {
                let mut map = try!(serializer.serialize_map(Some(1)));
                try!(map.serialize_key("errors"));
                try!(map.serialize_value(err));
                map.end()
            }
        }
    }
}

#[cfg(any(test, feature = "expose-test-schema"))]
pub mod tests {
    use serde_json::Value as Json;
    use serde_json;

    pub struct TestResponse {
        pub status_code: i32,
        pub body: Option<String>,
        pub content_type: String,
    }

    pub trait HTTPIntegration {
        fn get(&self, url: &str) -> TestResponse;
        fn post(&self, url: &str, body: &str) -> TestResponse;
    }

    pub fn run_http_test_suite<T: HTTPIntegration>(integration: &T) {
        println!("Running HTTP Test suite for integration");

        println!("  - test_simple_get");
        test_simple_get(integration);

        println!("  - test_encoded_get");
        test_encoded_get(integration);

        println!("  - test_get_with_variables");
        test_get_with_variables(integration);

        println!("  - test_simple_post");
        test_simple_post(integration);
    }

    fn unwrap_json_response(response: &TestResponse) -> Json {
        serde_json::from_str::<Json>(
            response
                .body
                .as_ref()
                .expect("No data returned from request"),
        ).expect("Could not parse JSON object")
    }

    fn test_simple_get<T: HTTPIntegration>(integration: &T) {
        let response = integration.get("/?query={hero{name}}");

        assert_eq!(response.status_code, 200);
        assert_eq!(response.content_type.as_str(), "application/json");

        assert_eq!(
            unwrap_json_response(&response),
            serde_json::from_str::<Json>(r#"{"data": {"hero": {"name": "R2-D2"}}}"#)
                .expect("Invalid JSON constant in test")
        );
    }

    fn test_encoded_get<T: HTTPIntegration>(integration: &T) {
        let response = integration.get(
            "/?query=query%20{%20%20%20human(id:%20\"1000\")%20{%20%20%20%20%20id,%20%20%20%20%20name,%20%20%20%20%20appearsIn,%20%20%20%20%20homePlanet%20%20%20}%20}");

        assert_eq!(response.status_code, 200);
        assert_eq!(response.content_type.as_str(), "application/json");

        assert_eq!(
            unwrap_json_response(&response),
            serde_json::from_str::<Json>(
                r#"{
                    "data": {
                        "human": {
                            "appearsIn": [
                                "NEW_HOPE",
                                "EMPIRE",
                                "JEDI"
                                ],
                                "homePlanet": "Tatooine",
                                "name": "Luke Skywalker",
                                "id": "1000"
                            }
                        }
                    }"#
            ).expect("Invalid JSON constant in test")
        );
    }

    fn test_get_with_variables<T: HTTPIntegration>(integration: &T) {
        let response = integration.get(
            "/?query=query($id:%20String!)%20{%20%20%20human(id:%20$id)%20{%20%20%20%20%20id,%20%20%20%20%20name,%20%20%20%20%20appearsIn,%20%20%20%20%20homePlanet%20%20%20}%20}&variables={%20%20%20\"id\":%20%20\"1000\"%20}");

        assert_eq!(response.status_code, 200);
        assert_eq!(response.content_type, "application/json");

        assert_eq!(
            unwrap_json_response(&response),
            serde_json::from_str::<Json>(
                r#"{
                    "data": {
                        "human": {
                            "appearsIn": [
                                "NEW_HOPE",
                                "EMPIRE",
                                "JEDI"
                                ],
                                "homePlanet": "Tatooine",
                                "name": "Luke Skywalker",
                                "id": "1000"
                            }
                        }
                    }"#
            ).expect("Invalid JSON constant in test")
        );
    }

    fn test_simple_post<T: HTTPIntegration>(integration: &T) {
        let response = integration.post("/", r#"{"query": "{hero{name}}"}"#);

        assert_eq!(response.status_code, 200);
        assert_eq!(response.content_type, "application/json");

        assert_eq!(
            unwrap_json_response(&response),
            serde_json::from_str::<Json>(r#"{"data": {"hero": {"name": "R2-D2"}}}"#)
                .expect("Invalid JSON constant in test")
        );
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins) within
//! a Cargo build. You still need the `capnp` binary (implemented in C++).
//! (If you use a package manager, try looking for a package called
//! `capnproto`.)
//!
//! In your Cargo.toml:
//!
//! ```ignore
//! [package]
//! build = "build.rs"
//!
//! [build-dependencies]
//! capnpc = "0.10"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     capnpc::CompilerCommand::new()
//!         .src_prefix("schema")
//!         .file("schema/foo.capnp")
//!         .file("schema/bar.capnp")
//!         .run().expect("schema compiler command");
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/capnproto/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
mod pointer_constants;
pub mod schema;

use std::path::{Path, PathBuf};

#[derive(Copy, Clone)]
pub enum RustEdition {
    Rust2015,
    Rust2018,
}

fn run_command(
    mut command: ::std::process::Command,
    path: &PathBuf,
) -> ::capnp::Result<()> {
    let mut p = command.spawn()?;
    crate::codegen::generate_code(p.stdout.take().unwrap(), path.as_path())?;
    let exit_status = p.wait()?;
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!(
            "Non-success exit status: {}",
            exit_status
        )))
    } else {
        Ok(())
    }
}

/// A builder object for schema compiler commands.
pub struct CompilerCommand {
    files: Vec<PathBuf>,
    src_prefixes: Vec<PathBuf>,
    import_paths: Vec<PathBuf>,
    no_standard_import: bool,
    output_path: PathBuf,
}

impl CompilerCommand {
    /// Creates a new, empty command.
    pub fn new() -> CompilerCommand {
        CompilerCommand {
            files: Vec::new(),
            src_prefixes: Vec::new(),
            import_paths: Vec::new(),
            no_standard_import: false,
            output_path: PathBuf::from(&::std::env::var("OUT_DIR").unwrap()),
        }
    }

    /// Adds a file to be compiled.
    pub fn file<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.files.push(path.as_ref().to_path_buf());
        self
    }

    /// Adds a --src-prefix flag. For all files specified for compilation that start
    /// with `prefix`, removes the prefix when computing output filenames.
    pub fn src_prefix<'a, P>(&'a mut self, prefix: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.src_prefixes.push(prefix.as_ref().to_path_buf());
        self
    }

    /// Adds an --import_path flag. Adds `dir` to the list of directories searched
    /// for absolute imports.
    pub fn import_path<'a, P>(&'a mut self, dir: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.import_paths.push(dir.as_ref().to_path_buf());
        self
    }

    /// Adds the --no-standard-import flag, indicating that the default import paths of
    /// /usr/include and /usr/local/include should not bet included.
    pub fn no_standard_import<'a>(&'a mut self) -> &'a mut CompilerCommand {
        self.no_standard_import = true;
        self
    }

    /// Sets the Rust edition of the generated code.
    #[deprecated(since = "0.10.0", note = "no longer need to specify rust edition")]
    pub fn edition(&mut self, _rust_edition: RustEdition) -> &mut Self {
        self
    }

    ///Sets the output directory of generated code. Default is OUT_DIR
    pub fn output_path<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.output_path = path.as_ref().to_path_buf();
        self
    }

    /// Runs the command.
    pub fn run(&mut self) -> ::capnp::Result<()> {
        let mut command = ::std::process::Command::new("capnp");
        command.arg("compile").arg("-o").arg("-");

        if self.no_standard_import {
            command.arg("--no-standard-import");
        }

        for import_path in &self.import_paths {
            command.arg(&format!("--import-path={}", import_path.display()));
        }

        for src_prefix in &self.src_prefixes {
            command.arg(&format!("--src-prefix={}", src_prefix.display()));
        }

        for file in &self.files {
            command.arg(&format!("{}", file.display()));
        }

        command.stdout(::std::process::Stdio::piped());
        command.stderr(::std::process::Stdio::inherit());

        run_command(command, &self.output_path).map_err(|error| {
            ::capnp::Error::failed(format!(
                "Error while trying to execute `capnp compile`: {}.  \
                 Please verify that version 0.5.2 or higher of the capnp executable \
                 is installed on your system. See https://capnproto.org/install.html",
                error
            ))
        })
    }
}
<commit_msg>CompilerCommand will not panic on OUT_DIR not set + nice error + unittest<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do [Cap'n Proto code generation]
//! (https://capnproto.org/otherlang.html#how-to-write-compiler-plugins) within
//! a Cargo build. You still need the `capnp` binary (implemented in C++).
//! (If you use a package manager, try looking for a package called
//! `capnproto`.)
//!
//! In your Cargo.toml:
//!
//! ```ignore
//! [package]
//! build = "build.rs"
//!
//! [build-dependencies]
//! capnpc = "0.10"
//! ```
//!
//! In your build.rs:
//!
//! ```ignore
//! extern crate capnpc;
//!
//! fn main() {
//!     capnpc::CompilerCommand::new()
//!         .src_prefix("schema")
//!         .file("schema/foo.capnp")
//!         .file("schema/bar.capnp")
//!         .run().expect("schema compiler command");
//! }
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

extern crate capnp;

/// Code generated from [schema.capnp]
/// (https://github.com/capnproto/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp).
pub mod schema_capnp;

pub mod codegen;
pub mod codegen_types;
mod pointer_constants;
pub mod schema;

use std::path::{Path, PathBuf};

#[derive(Copy, Clone)]
pub enum RustEdition {
    Rust2015,
    Rust2018,
}

fn run_command(mut command: ::std::process::Command, path: &PathBuf) -> ::capnp::Result<()> {
    let mut p = command.spawn()?;
    crate::codegen::generate_code(p.stdout.take().unwrap(), path.as_path())?;
    let exit_status = p.wait()?;
    if !exit_status.success() {
        Err(::capnp::Error::failed(format!(
            "Non-success exit status: {}",
            exit_status
        )))
    } else {
        Ok(())
    }
}

/// A builder object for schema compiler commands.
pub struct CompilerCommand {
    files: Vec<PathBuf>,
    src_prefixes: Vec<PathBuf>,
    import_paths: Vec<PathBuf>,
    no_standard_import: bool,
    output_path: Option<PathBuf>,
}

impl CompilerCommand {
    /// Creates a new, empty command.
    pub fn new() -> CompilerCommand {
        CompilerCommand {
            files: Vec::new(),
            src_prefixes: Vec::new(),
            import_paths: Vec::new(),
            no_standard_import: false,
            output_path: None,
        }
    }

    /// Adds a file to be compiled.
    pub fn file<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.files.push(path.as_ref().to_path_buf());
        self
    }

    /// Adds a --src-prefix flag. For all files specified for compilation that start
    /// with `prefix`, removes the prefix when computing output filenames.
    pub fn src_prefix<'a, P>(&'a mut self, prefix: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.src_prefixes.push(prefix.as_ref().to_path_buf());
        self
    }

    /// Adds an --import_path flag. Adds `dir` to the list of directories searched
    /// for absolute imports.
    pub fn import_path<'a, P>(&'a mut self, dir: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.import_paths.push(dir.as_ref().to_path_buf());
        self
    }

    /// Adds the --no-standard-import flag, indicating that the default import paths of
    /// /usr/include and /usr/local/include should not bet included.
    pub fn no_standard_import<'a>(&'a mut self) -> &'a mut CompilerCommand {
        self.no_standard_import = true;
        self
    }

    /// Sets the Rust edition of the generated code.
    #[deprecated(since = "0.10.0", note = "no longer need to specify rust edition")]
    pub fn edition(&mut self, _rust_edition: RustEdition) -> &mut Self {
        self
    }

    ///Sets the output directory of generated code. Default is OUT_DIR
    pub fn output_path<'a, P>(&'a mut self, path: P) -> &'a mut CompilerCommand
    where
        P: AsRef<Path>,
    {
        self.output_path = Some(path.as_ref().to_path_buf());
        self
    }

    /// Runs the command. Returns an error if `OUT_DIR` or a custom output directory was not set
    /// or if `capnp compile` fails.
    pub fn run(&mut self) -> ::capnp::Result<()> {
        let mut command = ::std::process::Command::new("capnp");
        command.arg("compile").arg("-o").arg("-");

        if self.no_standard_import {
            command.arg("--no-standard-import");
        }

        for import_path in &self.import_paths {
            command.arg(&format!("--import-path={}", import_path.display()));
        }

        for src_prefix in &self.src_prefixes {
            command.arg(&format!("--src-prefix={}", src_prefix.display()));
        }

        for file in &self.files {
            command.arg(&format!("{}", file.display()));
        }

        let output_path = if let Some(output_path) = &self.output_path {
            output_path.clone()
        } else {
            // Try `OUT_DIR` by default
            PathBuf::from(::std::env::var("OUT_DIR").map_err(|error| {
                ::capnp::Error::failed(format!(
                    "Could not access `OUT_DIR` environment variable: {}. \
                     You might need to set it up or instead create you own output \
                     structure using `CompilerCommand::output_path`",
                    error
                ))
            })?)
        };

        command.stdout(::std::process::Stdio::piped());
        command.stderr(::std::process::Stdio::inherit());

        run_command(command, &output_path).map_err(|error| {
            ::capnp::Error::failed(format!(
                "Error while trying to execute `capnp compile`: {}.  \
                 Please verify that version 0.5.2 or higher of the capnp executable \
                 is installed on your system. See https://capnproto.org/install.html",
                error
            ))
        })
    }
}

#[test]
fn compiler_command_new_no_out_dir() {
    let error = CompilerCommand::new().run().unwrap_err().description;
    assert!(error.starts_with("Could not access `OUT_DIR` environment variable"));
}

#[test]
fn compiler_command_with_output_path_no_out_dir() {
    let error = CompilerCommand::new().output_path("foo").run().unwrap_err().description;
    assert!(error.starts_with("Error while trying to execute `capnp compile`"));
}
<|endoftext|>


<commit_before>use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub,
               SubAssign};
use std::convert::From;
use std::fmt::{Display, Error, Formatter};

use {Normal3, Point3};
use num::{Num, Zero};

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vector2<T> {
    pub x: T,
    pub y: T,
}

impl<T> Vector2<T> {
    pub fn new(x: T, y: T) -> Vector2<T> {
        Vector2 { x, y }
    }
}

impl Vector2<f32> {
    pub fn has_nan(&self) -> bool {
        self.x.is_nan() || self.y.is_nan()
    }

    pub fn length_squared(&self) -> f32 {
        self.x * self.x + self.y * self.y
    }

    pub fn length(&self) -> f32 {
        f32::sqrt(self.length_squared())
    }
}

// Operators
impl<T> Add<Vector2<T>> for Vector2<T>
where
    T: Add<Output = T> + Copy,
{
    type Output = Vector2<T>;

    fn add(self, rhs: Vector2<T>) -> Vector2<T> {
        Vector2 {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
        }
    }
}

impl<T> AddAssign<Vector2<T>> for Vector2<T>
where
    T: AddAssign + Copy,
{
    fn add_assign(&mut self, other: Vector2<T>) {
        self.x += other.x;
        self.y += other.y;
    }
}

impl<T> Sub<Vector2<T>> for Vector2<T>
where
    T: Sub<Output = T> + Copy,
{
    type Output = Vector2<T>;

    fn sub(self, rhs: Vector2<T>) -> Vector2<T> {
        Vector2 {
            x: self.x - rhs.x,
            y: self.y - rhs.y,
        }
    }
}

impl<T> SubAssign<Vector2<T>> for Vector2<T>
where
    T: SubAssign + Copy,
{
    fn sub_assign(&mut self, other: Vector2<T>) {
        self.x -= other.x;
        self.y -= other.y;
    }
}

impl<T> Div<T> for Vector2<T>
where
    T: Div<Output = T> + Copy,
{
    type Output = Vector2<T>;

    fn div(self, v: T) -> Vector2<T> {
        Vector2 {
            x: self.x / v,
            y: self.y / v,
        }
    }
}

impl<T> DivAssign<T> for Vector2<T>
where
    T: DivAssign + Copy,
{
    fn div_assign(&mut self, v: T) {
        self.x /= v;
        self.y /= v;
    }
}

impl<T> Mul<T> for Vector2<T>
where
    T: Mul<Output = T> + Copy,
{
    type Output = Vector2<T>;

    fn mul(self, v: T) -> Vector2<T> {
        Vector2 {
            x: self.x * v,
            y: self.y * v,
        }
    }
}

impl<T> MulAssign<T> for Vector2<T>
where
    T: MulAssign + Copy,
{
    fn mul_assign(&mut self, v: T) {
        self.x *= v;
        self.y *= v;
    }
}

impl<T> Neg for Vector2<T>
where
    T: Neg<Output = T>,
{
    type Output = Vector2<T>;

    fn neg(self) -> Vector2<T> {
        Vector2 {
            x: -self.x,
            y: -self.y,
        }
    }
}

impl<T> Index<usize> for Vector2<T> {
    type Output = T;

    fn index(&self, i: usize) -> &T {
        match i {
            0 => &self.x,
            1 => &self.y,
            _ => panic!("Invalid index into vector"),
        }
    }
}

impl<T> IndexMut<usize> for Vector2<T> {
    fn index_mut(&mut self, i: usize) -> &mut T {
        match i {
            0 => &mut self.x,
            1 => &mut self.y,
            _ => panic!("Invalid index into vector"),
        }
    }
}

impl<T> Default for Vector2<T>
where
    T: Default,
{
    fn default() -> Self {
        Vector2 {
            x: T::default(),
            y: T::default(),
        }
    }
}

impl<T> Zero for Vector2<T>
where
    T: Num + Copy,
{
    fn zero() -> Vector2<T> {
        Vector2::new(T::zero(), T::zero())
    }

    fn is_zero(&self) -> bool {
        self.x == T::zero() && self.y == T::zero()
    }
}

impl<T> Display for Vector2<T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "[{}, {}]", self.x, self.y)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vector3<T> {
    pub x: T,
    pub y: T,
    pub z: T,
}

impl<T> Vector3<T>
where
    T: Num + Copy,
{
    pub fn new(x: T, y: T, z: T) -> Vector3<T> {
        Vector3 { x, y, z }
    }

    pub fn dot(&self, v: &Vector3<T>) -> T {
        self.x * v.x + self.y * v.y + self.z * v.z
    }

    pub fn dotn(&self, v: &Normal3<T>) -> T {
        self.x * v.x + self.y * v.y + self.z * v.z
    }

    pub fn x() -> Vector3<T> {
        Vector3::new(T::one(), T::zero(), T::zero())
    }

    pub fn y() -> Vector3<T> {
        Vector3::new(T::zero(), T::one(), T::zero())
    }

    pub fn z() -> Vector3<T> {
        Vector3::new(T::zero(), T::zero(), T::one())
    }
}

impl Vector3<f32> {
    pub fn has_nan(&self) -> bool {
        self.x.is_nan() || self.y.is_nan() || self.z.is_nan()
    }

    pub fn length_squared(&self) -> f32 {
        self.x * self.x + self.y * self.y + self.z * self.z
    }

    pub fn length(&self) -> f32 {
        f32::sqrt(self.length_squared())
    }

    pub fn normalize(&self) -> Vector3<f32> {
        *self / self.length()
    }

    pub fn cross(&self, v: &Vector3<f32>) -> Vector3<f32> {
        Vector3::new(
            (self.y * v.z) - (self.z * v.y),
            (self.z * v.x) - (self.x * v.z),
            (self.x * v.y) - (self.y * v.x),
        )
    }

    pub fn abs(&self) -> Vector3<f32> {
        Vector3::new(f32::abs(self.x), f32::abs(self.y), f32::abs(self.z))
    }

    // TODO cross_normal()
}

// Operators
impl<T> Add<Vector3<T>> for Vector3<T>
where
    T: Add<Output = T> + Copy,
{
    type Output = Vector3<T>;

    fn add(self, rhs: Vector3<T>) -> Vector3<T> {
        Vector3 {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
            z: self.z + rhs.z,
        }
    }
}

impl<T> AddAssign<Vector3<T>> for Vector3<T>
where
    T: AddAssign + Copy,
{
    fn add_assign(&mut self, other: Vector3<T>) {
        self.x += other.x;
        self.y += other.y;
        self.z += other.z;
    }
}

impl<T> Sub<Vector3<T>> for Vector3<T>
where
    T: Sub<Output = T> + Copy,
{
    type Output = Vector3<T>;

    fn sub(self, rhs: Vector3<T>) -> Vector3<T> {
        Vector3 {
            x: self.x - rhs.x,
            y: self.y - rhs.y,
            z: self.z - rhs.z,
        }
    }
}

impl<T> SubAssign<Vector3<T>> for Vector3<T>
where
    T: SubAssign + Copy,
{
    fn sub_assign(&mut self, other: Vector3<T>) {
        self.x -= other.x;
        self.y -= other.y;
        self.z -= other.z;
    }
}

impl<T> Div<T> for Vector3<T>
where
    T: Div<Output = T> + Copy,
{
    type Output = Vector3<T>;

    fn div(self, v: T) -> Vector3<T> {
        Vector3 {
            x: self.x / v,
            y: self.y / v,
            z: self.z / v,
        }
    }
}

impl<T> DivAssign<T> for Vector3<T>
where
    T: DivAssign + Copy,
{
    fn div_assign(&mut self, v: T) {
        self.x /= v;
        self.y /= v;
        self.z /= v;
    }
}

impl<T> Mul<T> for Vector3<T>
where
    T: Mul<Output = T> + Copy,
{
    type Output = Vector3<T>;

    fn mul(self, v: T) -> Vector3<T> {
        Vector3 {
            x: self.x * v,
            y: self.y * v,
            z: self.z * v,
        }
    }
}

impl Mul<Vector3<f32>> for f32 {
    type Output = Vector3<f32>;

    fn mul(self, v: Vector3<f32>) -> Vector3<f32> {
        Vector3 {
            x: self * v.x,
            y: self * v.y,
            z: self * v.z,
        }
    }
}

impl<T> MulAssign<T> for Vector3<T>
where
    T: MulAssign + Copy,
{
    fn mul_assign(&mut self, v: T) {
        self.x *= v;
        self.y *= v;
        self.z *= v;
    }
}

impl<'a, T> Neg for &'a Vector3<T>
where
    T: Neg<Output = T>,
    T: Copy,
{
    type Output = Vector3<T>;

    fn neg(self) -> Vector3<T> {
        Vector3 {
            x: -self.x,
            y: -self.y,
            z: -self.z,
        }
    }
}

impl<T> Neg for Vector3<T>
where
    T: Neg<Output = T>,
{
    type Output = Vector3<T>;

    fn neg(self) -> Vector3<T> {
        Vector3 {
            x: -self.x,
            y: -self.y,
            z: -self.z,
        }
    }
}

impl<T> Index<usize> for Vector3<T> {
    type Output = T;

    fn index(&self, i: usize) -> &T {
        match i {
            0 => &self.x,
            1 => &self.y,
            2 => &self.z,
            _ => panic!("Invalid index into vector"),
        }
    }
}

impl<T> IndexMut<usize> for Vector3<T> {
    fn index_mut(&mut self, i: usize) -> &mut T {
        match i {
            0 => &mut self.x,
            1 => &mut self.y,
            2 => &mut self.z,
            _ => panic!("Invalid index into vector"),
        }
    }
}

impl<T> From<Point3<T>> for Vector3<T>
where
    T: Num + Copy,
{
    fn from(p: Point3<T>) -> Vector3<T> {
        Vector3::new(p.x, p.y, p.z)
    }
}

impl<T> From<Normal3<T>> for Vector3<T>
where
    T: Num + Copy,
{
    fn from(n: Normal3<T>) -> Vector3<T> {
        Vector3::new(n.x, n.y, n.z)
    }
}

impl<T> Default for Vector3<T>
where
    T: Default,
{
    fn default() -> Self {
        Vector3 {
            x: T::default(),
            y: T::default(),
            z: T::default(),
        }
    }
}

impl<T> Zero for Vector3<T>
where
    T: Num + Copy,
{
    fn zero() -> Vector3<T> {
        Vector3::new(T::zero(), T::zero(), T::zero())
    }

    fn is_zero(&self) -> bool {
        self.x == T::zero() && self.y == T::zero() && self.z == T::zero()
    }
}

impl<T> Display for Vector3<T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "[{}, {}, {}]", self.x, self.y, self.z)
    }
}

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

    #[test]
    fn test_add() {
        let v1 = Vector2::new(1.0, 2.0);
        let v2 = Vector2::new(3.0, 4.0);
        assert_eq!(v1 + v2, Vector2::new(4.0, 6.0));
    }
}
<commit_msg>Add Mul and MulAssign for &Vector2<commit_after>use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub,
               SubAssign};
use std::convert::From;
use std::fmt::{Display, Error, Formatter};

use {Normal3, Point3};
use num::{Num, Zero};

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vector2<T> {
    pub x: T,
    pub y: T,
}

impl<T> Vector2<T> {
    pub fn new(x: T, y: T) -> Vector2<T> {
        Vector2 { x, y }
    }
}

impl Vector2<f32> {
    pub fn has_nan(&self) -> bool {
        self.x.is_nan() || self.y.is_nan()
    }

    pub fn length_squared(&self) -> f32 {
        self.x * self.x + self.y * self.y
    }

    pub fn length(&self) -> f32 {
        f32::sqrt(self.length_squared())
    }
}

// Operators
impl<T> Add<Vector2<T>> for Vector2<T>
where
    T: Add<Output = T> + Copy,
{
    type Output = Vector2<T>;

    fn add(self, rhs: Vector2<T>) -> Vector2<T> {
        Vector2 {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
        }
    }
}

impl<T> AddAssign<Vector2<T>> for Vector2<T>
where
    T: AddAssign + Copy,
{
    fn add_assign(&mut self, other: Vector2<T>) {
        self.x += other.x;
        self.y += other.y;
    }
}

impl<T> Sub<Vector2<T>> for Vector2<T>
where
    T: Sub<Output = T> + Copy,
{
    type Output = Vector2<T>;

    fn sub(self, rhs: Vector2<T>) -> Vector2<T> {
        Vector2 {
            x: self.x - rhs.x,
            y: self.y - rhs.y,
        }
    }
}

impl<T> SubAssign<Vector2<T>> for Vector2<T>
where
    T: SubAssign + Copy,
{
    fn sub_assign(&mut self, other: Vector2<T>) {
        self.x -= other.x;
        self.y -= other.y;
    }
}

impl<T> Div<T> for Vector2<T>
where
    T: Div<Output = T> + Copy,
{
    type Output = Vector2<T>;

    fn div(self, v: T) -> Vector2<T> {
        Vector2 {
            x: self.x / v,
            y: self.y / v,
        }
    }
}

impl<T> DivAssign<T> for Vector2<T>
where
    T: DivAssign + Copy,
{
    fn div_assign(&mut self, v: T) {
        self.x /= v;
        self.y /= v;
    }
}

impl<'a, T> Mul<T> for &'a Vector2<T>
where
    T: Mul<Output = T> + Copy,
{
    type Output = Vector2<T>;

    fn mul(self, v: T) -> Vector2<T> {
        Vector2 {
            x: self.x * v,
            y: self.y * v,
        }
    }
}

impl<T> Mul<T> for Vector2<T>
where
    T: Mul<Output = T> + Copy,
{
    type Output = Vector2<T>;

    fn mul(self, v: T) -> Vector2<T> {
        Vector2 {
            x: self.x * v,
            y: self.y * v,
        }
    }
}

impl<'a, T> MulAssign<T> for &'a mut Vector2<T>
where
    T: MulAssign + Copy,
{
    fn mul_assign(&mut self, v: T) {
        self.x *= v;
        self.y *= v;
    }
}

impl<T> MulAssign<T> for Vector2<T>
where
    T: MulAssign + Copy,
{
    fn mul_assign(&mut self, v: T) {
        self.x *= v;
        self.y *= v;
    }
}

impl<T> Neg for Vector2<T>
where
    T: Neg<Output = T>,
{
    type Output = Vector2<T>;

    fn neg(self) -> Vector2<T> {
        Vector2 {
            x: -self.x,
            y: -self.y,
        }
    }
}

impl<T> Index<usize> for Vector2<T> {
    type Output = T;

    fn index(&self, i: usize) -> &T {
        match i {
            0 => &self.x,
            1 => &self.y,
            _ => panic!("Invalid index into vector"),
        }
    }
}

impl<T> IndexMut<usize> for Vector2<T> {
    fn index_mut(&mut self, i: usize) -> &mut T {
        match i {
            0 => &mut self.x,
            1 => &mut self.y,
            _ => panic!("Invalid index into vector"),
        }
    }
}

impl<T> Default for Vector2<T>
where
    T: Default,
{
    fn default() -> Self {
        Vector2 {
            x: T::default(),
            y: T::default(),
        }
    }
}

impl<T> Zero for Vector2<T>
where
    T: Num + Copy,
{
    fn zero() -> Vector2<T> {
        Vector2::new(T::zero(), T::zero())
    }

    fn is_zero(&self) -> bool {
        self.x == T::zero() && self.y == T::zero()
    }
}

impl<T> Display for Vector2<T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "[{}, {}]", self.x, self.y)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vector3<T> {
    pub x: T,
    pub y: T,
    pub z: T,
}

impl<T> Vector3<T>
where
    T: Num + Copy,
{
    pub fn new(x: T, y: T, z: T) -> Vector3<T> {
        Vector3 { x, y, z }
    }

    pub fn dot(&self, v: &Vector3<T>) -> T {
        self.x * v.x + self.y * v.y + self.z * v.z
    }

    pub fn dotn(&self, v: &Normal3<T>) -> T {
        self.x * v.x + self.y * v.y + self.z * v.z
    }

    pub fn x() -> Vector3<T> {
        Vector3::new(T::one(), T::zero(), T::zero())
    }

    pub fn y() -> Vector3<T> {
        Vector3::new(T::zero(), T::one(), T::zero())
    }

    pub fn z() -> Vector3<T> {
        Vector3::new(T::zero(), T::zero(), T::one())
    }
}

impl Vector3<f32> {
    pub fn has_nan(&self) -> bool {
        self.x.is_nan() || self.y.is_nan() || self.z.is_nan()
    }

    pub fn length_squared(&self) -> f32 {
        self.x * self.x + self.y * self.y + self.z * self.z
    }

    pub fn length(&self) -> f32 {
        f32::sqrt(self.length_squared())
    }

    pub fn normalize(&self) -> Vector3<f32> {
        *self / self.length()
    }

    pub fn cross(&self, v: &Vector3<f32>) -> Vector3<f32> {
        Vector3::new(
            (self.y * v.z) - (self.z * v.y),
            (self.z * v.x) - (self.x * v.z),
            (self.x * v.y) - (self.y * v.x),
        )
    }

    pub fn abs(&self) -> Vector3<f32> {
        Vector3::new(f32::abs(self.x), f32::abs(self.y), f32::abs(self.z))
    }

    // TODO cross_normal()
}

// Operators
impl<T> Add<Vector3<T>> for Vector3<T>
where
    T: Add<Output = T> + Copy,
{
    type Output = Vector3<T>;

    fn add(self, rhs: Vector3<T>) -> Vector3<T> {
        Vector3 {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
            z: self.z + rhs.z,
        }
    }
}

impl<T> AddAssign<Vector3<T>> for Vector3<T>
where
    T: AddAssign + Copy,
{
    fn add_assign(&mut self, other: Vector3<T>) {
        self.x += other.x;
        self.y += other.y;
        self.z += other.z;
    }
}

impl<T> Sub<Vector3<T>> for Vector3<T>
where
    T: Sub<Output = T> + Copy,
{
    type Output = Vector3<T>;

    fn sub(self, rhs: Vector3<T>) -> Vector3<T> {
        Vector3 {
            x: self.x - rhs.x,
            y: self.y - rhs.y,
            z: self.z - rhs.z,
        }
    }
}

impl<T> SubAssign<Vector3<T>> for Vector3<T>
where
    T: SubAssign + Copy,
{
    fn sub_assign(&mut self, other: Vector3<T>) {
        self.x -= other.x;
        self.y -= other.y;
        self.z -= other.z;
    }
}

impl<T> Div<T> for Vector3<T>
where
    T: Div<Output = T> + Copy,
{
    type Output = Vector3<T>;

    fn div(self, v: T) -> Vector3<T> {
        Vector3 {
            x: self.x / v,
            y: self.y / v,
            z: self.z / v,
        }
    }
}

impl<T> DivAssign<T> for Vector3<T>
where
    T: DivAssign + Copy,
{
    fn div_assign(&mut self, v: T) {
        self.x /= v;
        self.y /= v;
        self.z /= v;
    }
}

impl<T> Mul<T> for Vector3<T>
where
    T: Mul<Output = T> + Copy,
{
    type Output = Vector3<T>;

    fn mul(self, v: T) -> Vector3<T> {
        Vector3 {
            x: self.x * v,
            y: self.y * v,
            z: self.z * v,
        }
    }
}

impl Mul<Vector3<f32>> for f32 {
    type Output = Vector3<f32>;

    fn mul(self, v: Vector3<f32>) -> Vector3<f32> {
        Vector3 {
            x: self * v.x,
            y: self * v.y,
            z: self * v.z,
        }
    }
}

impl<T> MulAssign<T> for Vector3<T>
where
    T: MulAssign + Copy,
{
    fn mul_assign(&mut self, v: T) {
        self.x *= v;
        self.y *= v;
        self.z *= v;
    }
}

impl<'a, T> Neg for &'a Vector3<T>
where
    T: Neg<Output = T>,
    T: Copy,
{
    type Output = Vector3<T>;

    fn neg(self) -> Vector3<T> {
        Vector3 {
            x: -self.x,
            y: -self.y,
            z: -self.z,
        }
    }
}

impl<T> Neg for Vector3<T>
where
    T: Neg<Output = T>,
{
    type Output = Vector3<T>;

    fn neg(self) -> Vector3<T> {
        Vector3 {
            x: -self.x,
            y: -self.y,
            z: -self.z,
        }
    }
}

impl<T> Index<usize> for Vector3<T> {
    type Output = T;

    fn index(&self, i: usize) -> &T {
        match i {
            0 => &self.x,
            1 => &self.y,
            2 => &self.z,
            _ => panic!("Invalid index into vector"),
        }
    }
}

impl<T> IndexMut<usize> for Vector3<T> {
    fn index_mut(&mut self, i: usize) -> &mut T {
        match i {
            0 => &mut self.x,
            1 => &mut self.y,
            2 => &mut self.z,
            _ => panic!("Invalid index into vector"),
        }
    }
}

impl<T> From<Point3<T>> for Vector3<T>
where
    T: Num + Copy,
{
    fn from(p: Point3<T>) -> Vector3<T> {
        Vector3::new(p.x, p.y, p.z)
    }
}

impl<T> From<Normal3<T>> for Vector3<T>
where
    T: Num + Copy,
{
    fn from(n: Normal3<T>) -> Vector3<T> {
        Vector3::new(n.x, n.y, n.z)
    }
}

impl<T> Default for Vector3<T>
where
    T: Default,
{
    fn default() -> Self {
        Vector3 {
            x: T::default(),
            y: T::default(),
            z: T::default(),
        }
    }
}

impl<T> Zero for Vector3<T>
where
    T: Num + Copy,
{
    fn zero() -> Vector3<T> {
        Vector3::new(T::zero(), T::zero(), T::zero())
    }

    fn is_zero(&self) -> bool {
        self.x == T::zero() && self.y == T::zero() && self.z == T::zero()
    }
}

impl<T> Display for Vector3<T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "[{}, {}, {}]", self.x, self.y, self.z)
    }
}

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

    #[test]
    fn test_add() {
        let v1 = Vector2::new(1.0, 2.0);
        let v2 = Vector2::new(3.0, 4.0);
        assert_eq!(v1 + v2, Vector2::new(4.0, 6.0));
    }
}
<|endoftext|>


<commit_before>use clap::{App, Arg, ArgMatches};
use failure::Error;
use lucetc::{HeapSettings, OptLevel};
use std::path::PathBuf;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CodegenOutput {
    Clif,
    Obj,
    SharedObj,
}

fn parse_humansized(desc: &str) -> Result<u64, Error> {
    use human_size::{Byte, ParsingError, Size, SpecificSize};
    match desc.parse::<Size>() {
        Ok(s) => {
            let bytes: SpecificSize<Byte> = s.into();
            Ok(bytes.value() as u64)
        }
        Err(ParsingError::MissingMultiple) => Ok(desc.parse::<u64>()?),
        Err(e) => Err(e)?,
    }
}

fn humansized(bytes: u64) -> String {
    use human_size::{Byte, Mebibyte, SpecificSize};
    let bytes = SpecificSize::new(bytes as f64, Byte).expect("bytes");
    let mb: SpecificSize<Mebibyte> = bytes.into();
    mb.to_string()
}

#[derive(Debug)]
pub struct Options {
    pub output: PathBuf,
    pub input: Vec<PathBuf>,
    pub codegen: CodegenOutput,
    pub binding_files: Vec<PathBuf>,
    pub witx_specs: Vec<PathBuf>,
    pub wasi_exe: bool,
    pub builtins_path: Option<PathBuf>,
    pub min_reserved_size: Option<u64>,
    pub max_reserved_size: Option<u64>,
    pub reserved_size: Option<u64>,
    pub guard_size: Option<u64>,
    pub opt_level: OptLevel,
    pub keygen: bool,
    pub sign: bool,
    pub verify: bool,
    pub pk_path: Option<PathBuf>,
    pub sk_path: Option<PathBuf>,
    pub count_instructions: bool,
}

impl Options {
    pub fn from_args(m: &ArgMatches<'_>) -> Result<Self, Error> {
        let input: Vec<PathBuf> = m
            .values_of("input")
            .unwrap_or_default()
            .map(PathBuf::from)
            .collect();

        let output = PathBuf::from(m.value_of("output").unwrap_or("a.out"));

        let binding_files: Vec<PathBuf> = m
            .values_of("bindings")
            .unwrap_or_default()
            .map(PathBuf::from)
            .collect();

        let witx_specs: Vec<PathBuf> = m
            .values_of("witx_specs")
            .unwrap_or_default()
            .map(PathBuf::from)
            .collect();
        let wasi_exe = m.is_present("wasi_exe");

        let codegen = match m.value_of("emit") {
            None => CodegenOutput::SharedObj,
            Some("clif") => CodegenOutput::Clif,
            Some("obj") => CodegenOutput::Obj,
            Some("so") => CodegenOutput::SharedObj,
            Some(_) => panic!("unknown value for emit"),
        };

        let builtins_path = m.value_of("builtins").map(PathBuf::from);

        let min_reserved_size = if let Some(min_reserved_str) = m.value_of("min_reserved_size") {
            Some(parse_humansized(min_reserved_str)?)
        } else {
            None
        };

        let max_reserved_size = if let Some(max_reserved_str) = m.value_of("max_reserved_size") {
            Some(parse_humansized(max_reserved_str)?)
        } else {
            None
        };

        let reserved_size = if let Some(reserved_str) = m.value_of("reserved_size") {
            Some(parse_humansized(reserved_str)?)
        } else {
            None
        };

        let guard_size = if let Some(guard_str) = m.value_of("guard_size") {
            Some(parse_humansized(guard_str)?)
        } else {
            None
        };

        let opt_level = match m.value_of("opt_level") {
            None => OptLevel::SpeedAndSize,
            Some("0") => OptLevel::None,
            Some("1") => OptLevel::Speed,
            Some("2") => OptLevel::SpeedAndSize,
            Some(_) => panic!("unknown value for opt-level"),
        };

        let keygen = m.is_present("keygen");
        let sign = m.is_present("sign");
        let verify = m.is_present("verify");
        let sk_path = m.value_of("sk_path").map(PathBuf::from);
        let pk_path = m.value_of("pk_path").map(PathBuf::from);
        let count_instructions = m.is_present("count_instructions");

        Ok(Options {
            output,
            input,
            codegen,
            binding_files,
            witx_specs,
            wasi_exe,
            builtins_path,
            min_reserved_size,
            max_reserved_size,
            reserved_size,
            guard_size,
            opt_level,
            keygen,
            sign,
            verify,
            sk_path,
            pk_path,
            count_instructions,
        })
    }
    pub fn get() -> Result<Self, Error> {
        let m = App::new("lucetc")
            .arg(
                Arg::with_name("precious")
                    .long("--precious")
                    .takes_value(true)
                    .help("directory to keep intermediate build artifacts in"),
            )
            .arg(
                Arg::with_name("emit")
                    .long("emit")
                    .takes_value(true)
                    .possible_values(&["obj", "so", "clif"])
                    .help("type of code to generate (default: so)"),
            )
            .arg(
                Arg::with_name("output")
                    .short("o")
                    .long("output")
                    .takes_value(true)
                    .multiple(false)
                    .help("output destination, defaults to a.out if unspecified"),
            )
            .arg(
                Arg::with_name("bindings")
                    .long("--bindings")
                    .takes_value(true)
                    .multiple(true)
                    .number_of_values(1)
                    .help("path to bindings json file"),
            )
            .arg(
                Arg::with_name("witx_specs")
                    .long("--witx")
                    .takes_value(true)
                    .multiple(true)
                    .number_of_values(1)
                    .help("path to witx spec to validate against"),
            )
            .arg(
                Arg::with_name("wasi_exe")
                    .long("--wasi_exe")
                    .takes_value(false)
                    .multiple(false)
                    .help("validate as a wasi executable"),
            )
            .arg(
                Arg::with_name("min_reserved_size")
                    .long("--min-reserved-size")
                    .takes_value(true)
                    .multiple(false)
                    .help(&format!(
                        "minimum size of usable linear memory region. must be multiple of 4k. default: {}",
                        humansized(HeapSettings::default().min_reserved_size)
                    )),
            )
            .arg(
                Arg::with_name("max_reserved_size")
                    .long("--max-reserved-size")
                    .takes_value(true)
                    .multiple(false)
                    .help("maximum size of usable linear memory region. must be multiple of 4k. default: 4 GiB"),
            )
            .arg(
                Arg::with_name("reserved_size")
                    .long("--reserved-size")
                    .takes_value(true)
                    .multiple(false)
                    .help("exact size of usable linear memory region, overriding --{min,max}-reserved-size. must be multiple of 4k"),
            )
            .arg(
                Arg::with_name("guard_size")
                    .long("--guard-size")
                    .takes_value(true)
                    .multiple(false)
                    .help(&format!(
                        "size of linear memory guard. must be multiple of 4k. default: {}",
                        humansized(HeapSettings::default().guard_size)
                    )),
            )
            .arg(
                Arg::with_name("builtins")
                    .long("--builtins")
                    .takes_value(true)
                    .help("builtins file"),
            )
            .arg(
                Arg::with_name("input")
                    .multiple(false)
                    .required(false)
                    .help("input file"),
            )
            .arg(
                Arg::with_name("opt_level")
                    .long("--opt-level")
                    .takes_value(true)
                    .possible_values(&["0", "1", "2", "none", "speed", "speed_and_size"])
                    .help("optimization level (default: 'speed_and_size'). 0 is alias to 'none', 1 to 'speed', 2 to 'speed_and_size'"),
            )
            .arg(
                Arg::with_name("keygen")
                    .long("--signature-keygen")
                    .takes_value(false)
                    .help("Create a new key pair")
            )
            .arg(
                Arg::with_name("verify")
                     .long("--signature-verify")
                     .takes_value(false)
                     .help("Verify the signature of the source file")
            )
            .arg(
                Arg::with_name("sign")
                     .long("--signature-create")
                     .takes_value(false)
                     .help("Sign the object file")
            )
            .arg(
                Arg::with_name("pk_path")
                     .long("--signature-pk")
                     .takes_value(true)
                     .help("Path to the public key to verify the source code signature")
            )
            .arg(
                Arg::with_name("sk_path")
                     .long("--signature-sk")
                     .takes_value(true)
                     .help("Path to the secret key to sign the object file. The file can be prefixed with \"raw:\" in order to store a raw, unencrypted secret key")
            )
            .arg(
                Arg::with_name("count_instructions")
                    .long("--count-instructions")
                    .takes_value(false)
                    .help("Instrument the produced binary to count the number of wasm operations the translated program executes")
            )
            .get_matches();

        Self::from_args(&m)
    }
}
<commit_msg>lucetc: fix --opt-level {none, speed, speed_and_size} (#328)<commit_after>use clap::{App, Arg, ArgMatches};
use failure::Error;
use lucetc::{HeapSettings, OptLevel};
use std::path::PathBuf;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CodegenOutput {
    Clif,
    Obj,
    SharedObj,
}

fn parse_humansized(desc: &str) -> Result<u64, Error> {
    use human_size::{Byte, ParsingError, Size, SpecificSize};
    match desc.parse::<Size>() {
        Ok(s) => {
            let bytes: SpecificSize<Byte> = s.into();
            Ok(bytes.value() as u64)
        }
        Err(ParsingError::MissingMultiple) => Ok(desc.parse::<u64>()?),
        Err(e) => Err(e)?,
    }
}

fn humansized(bytes: u64) -> String {
    use human_size::{Byte, Mebibyte, SpecificSize};
    let bytes = SpecificSize::new(bytes as f64, Byte).expect("bytes");
    let mb: SpecificSize<Mebibyte> = bytes.into();
    mb.to_string()
}

#[derive(Debug)]
pub struct Options {
    pub output: PathBuf,
    pub input: Vec<PathBuf>,
    pub codegen: CodegenOutput,
    pub binding_files: Vec<PathBuf>,
    pub witx_specs: Vec<PathBuf>,
    pub wasi_exe: bool,
    pub builtins_path: Option<PathBuf>,
    pub min_reserved_size: Option<u64>,
    pub max_reserved_size: Option<u64>,
    pub reserved_size: Option<u64>,
    pub guard_size: Option<u64>,
    pub opt_level: OptLevel,
    pub keygen: bool,
    pub sign: bool,
    pub verify: bool,
    pub pk_path: Option<PathBuf>,
    pub sk_path: Option<PathBuf>,
    pub count_instructions: bool,
}

impl Options {
    pub fn from_args(m: &ArgMatches<'_>) -> Result<Self, Error> {
        let input: Vec<PathBuf> = m
            .values_of("input")
            .unwrap_or_default()
            .map(PathBuf::from)
            .collect();

        let output = PathBuf::from(m.value_of("output").unwrap_or("a.out"));

        let binding_files: Vec<PathBuf> = m
            .values_of("bindings")
            .unwrap_or_default()
            .map(PathBuf::from)
            .collect();

        let witx_specs: Vec<PathBuf> = m
            .values_of("witx_specs")
            .unwrap_or_default()
            .map(PathBuf::from)
            .collect();
        let wasi_exe = m.is_present("wasi_exe");

        let codegen = match m.value_of("emit") {
            None => CodegenOutput::SharedObj,
            Some("clif") => CodegenOutput::Clif,
            Some("obj") => CodegenOutput::Obj,
            Some("so") => CodegenOutput::SharedObj,
            Some(_) => panic!("unknown value for emit"),
        };

        let builtins_path = m.value_of("builtins").map(PathBuf::from);

        let min_reserved_size = if let Some(min_reserved_str) = m.value_of("min_reserved_size") {
            Some(parse_humansized(min_reserved_str)?)
        } else {
            None
        };

        let max_reserved_size = if let Some(max_reserved_str) = m.value_of("max_reserved_size") {
            Some(parse_humansized(max_reserved_str)?)
        } else {
            None
        };

        let reserved_size = if let Some(reserved_str) = m.value_of("reserved_size") {
            Some(parse_humansized(reserved_str)?)
        } else {
            None
        };

        let guard_size = if let Some(guard_str) = m.value_of("guard_size") {
            Some(parse_humansized(guard_str)?)
        } else {
            None
        };

        let opt_level = match m.value_of("opt_level") {
            None => OptLevel::SpeedAndSize,
            Some("0") | Some("none") => OptLevel::None,
            Some("1") | Some("speed") => OptLevel::Speed,
            Some("2") | Some("speed_and_size") => OptLevel::SpeedAndSize,
            Some(_) => panic!("unknown value for opt-level"),
        };

        let keygen = m.is_present("keygen");
        let sign = m.is_present("sign");
        let verify = m.is_present("verify");
        let sk_path = m.value_of("sk_path").map(PathBuf::from);
        let pk_path = m.value_of("pk_path").map(PathBuf::from);
        let count_instructions = m.is_present("count_instructions");

        Ok(Options {
            output,
            input,
            codegen,
            binding_files,
            witx_specs,
            wasi_exe,
            builtins_path,
            min_reserved_size,
            max_reserved_size,
            reserved_size,
            guard_size,
            opt_level,
            keygen,
            sign,
            verify,
            sk_path,
            pk_path,
            count_instructions,
        })
    }
    pub fn get() -> Result<Self, Error> {
        let m = App::new("lucetc")
            .arg(
                Arg::with_name("precious")
                    .long("--precious")
                    .takes_value(true)
                    .help("directory to keep intermediate build artifacts in"),
            )
            .arg(
                Arg::with_name("emit")
                    .long("emit")
                    .takes_value(true)
                    .possible_values(&["obj", "so", "clif"])
                    .help("type of code to generate (default: so)"),
            )
            .arg(
                Arg::with_name("output")
                    .short("o")
                    .long("output")
                    .takes_value(true)
                    .multiple(false)
                    .help("output destination, defaults to a.out if unspecified"),
            )
            .arg(
                Arg::with_name("bindings")
                    .long("--bindings")
                    .takes_value(true)
                    .multiple(true)
                    .number_of_values(1)
                    .help("path to bindings json file"),
            )
            .arg(
                Arg::with_name("witx_specs")
                    .long("--witx")
                    .takes_value(true)
                    .multiple(true)
                    .number_of_values(1)
                    .help("path to witx spec to validate against"),
            )
            .arg(
                Arg::with_name("wasi_exe")
                    .long("--wasi_exe")
                    .takes_value(false)
                    .multiple(false)
                    .help("validate as a wasi executable"),
            )
            .arg(
                Arg::with_name("min_reserved_size")
                    .long("--min-reserved-size")
                    .takes_value(true)
                    .multiple(false)
                    .help(&format!(
                        "minimum size of usable linear memory region. must be multiple of 4k. default: {}",
                        humansized(HeapSettings::default().min_reserved_size)
                    )),
            )
            .arg(
                Arg::with_name("max_reserved_size")
                    .long("--max-reserved-size")
                    .takes_value(true)
                    .multiple(false)
                    .help("maximum size of usable linear memory region. must be multiple of 4k. default: 4 GiB"),
            )
            .arg(
                Arg::with_name("reserved_size")
                    .long("--reserved-size")
                    .takes_value(true)
                    .multiple(false)
                    .help("exact size of usable linear memory region, overriding --{min,max}-reserved-size. must be multiple of 4k"),
            )
            .arg(
                Arg::with_name("guard_size")
                    .long("--guard-size")
                    .takes_value(true)
                    .multiple(false)
                    .help(&format!(
                        "size of linear memory guard. must be multiple of 4k. default: {}",
                        humansized(HeapSettings::default().guard_size)
                    )),
            )
            .arg(
                Arg::with_name("builtins")
                    .long("--builtins")
                    .takes_value(true)
                    .help("builtins file"),
            )
            .arg(
                Arg::with_name("input")
                    .multiple(false)
                    .required(false)
                    .help("input file"),
            )
            .arg(
                Arg::with_name("opt_level")
                    .long("--opt-level")
                    .takes_value(true)
                    .possible_values(&["0", "1", "2", "none", "speed", "speed_and_size"])
                    .help("optimization level (default: 'speed_and_size'). 0 is alias to 'none', 1 to 'speed', 2 to 'speed_and_size'"),
            )
            .arg(
                Arg::with_name("keygen")
                    .long("--signature-keygen")
                    .takes_value(false)
                    .help("Create a new key pair")
            )
            .arg(
                Arg::with_name("verify")
                     .long("--signature-verify")
                     .takes_value(false)
                     .help("Verify the signature of the source file")
            )
            .arg(
                Arg::with_name("sign")
                     .long("--signature-create")
                     .takes_value(false)
                     .help("Sign the object file")
            )
            .arg(
                Arg::with_name("pk_path")
                     .long("--signature-pk")
                     .takes_value(true)
                     .help("Path to the public key to verify the source code signature")
            )
            .arg(
                Arg::with_name("sk_path")
                     .long("--signature-sk")
                     .takes_value(true)
                     .help("Path to the secret key to sign the object file. The file can be prefixed with \"raw:\" in order to store a raw, unencrypted secret key")
            )
            .arg(
                Arg::with_name("count_instructions")
                    .long("--count-instructions")
                    .takes_value(false)
                    .help("Instrument the produced binary to count the number of wasm operations the translated program executes")
            )
            .get_matches();

        Self::from_args(&m)
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagutil;

use std::process::exit;

use clap::ArgMatches;

use libimagrt::runtime::Runtime;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Result as StoreResult;
use libimagstore::storeid::StoreId;
use libimagutil::trace::trace_error;

mod ui;
mod viewer;

use ui::build_ui;
use viewer::Viewer;
use viewer::ViewInformation;
use viewer::stdout::StdoutViewer;

fn main() {
    let name = "imag-view";
    let version = &version!()[..];
    let about = "View entries (readonly)";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));
    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.err().unwrap());
            exit(1);
        }
    };

    rt.init_logger();

    debug!("Hello. Logging was just enabled");
    debug!("I already set up the Runtime object and build the commandline interface parser.");
    debug!("Lets get rollin' ...");

    info!("No implementation yet");

    let entry_id = rt.cli().value_of("id").unwrap(); // enforced by clap

    if rt.cli().is_present("versions") {
        view_versions_of(entry_id, &rt);
    } else {
        let entry_version   = rt.cli().value_of("version");
        let view_header     = rt.cli().is_present("view-header");
        let view_content    = rt.cli().is_present("view-content");
        let view_copy       = rt.cli().is_present("view-copy");
        let keep_copy       = rt.cli().is_present("keep-copy");

        let scmd = rt.cli().subcommand_matches("view-in");
        if scmd.is_none() {
            debug!("No commandline call");
            exit(1);
        }
        let scmd = scmd.unwrap();

        let viewer = build_viewer(scmd);
        let entry = load_entry(entry_id, entry_version, &rt);
        if entry.is_err() {
            trace_error(&entry.err().unwrap());
            exit(1);
        }
        let entry = entry.unwrap();

        let view_info = ViewInformation {
            entry:          entry,
            view_header:    view_header,
            view_content:   view_content,
            view_copy:      view_copy,
            keep_copy:      keep_copy,
        };

        let viewer = StdoutViewer::new();
        viewer.view(view_info);
    }
}

// TODO: This is a shameless adaption of imag-store/src/util.rs
fn load_entry<'a>(id: &str,
                  version: Option<&str>,
                  rt: &'a Runtime)
    -> StoreResult<FileLockEntry<'a>>
{
    use std::ops::Deref;

    debug!("Checking path element for version");

    let version = {
        version.unwrap_or_else(|| {
            id.split("~").last().unwrap_or_else(|| {
                warn!("No version");
                exit(1);
            })
        })
    };

    debug!("Building path from {:?} and {:?}", id, version);
    let mut path = rt.store().path().clone();

    if id.chars().next() == Some('/') {
        path.push(format!("{}~{}", &id[1..id.len()], version));
    } else {
        path.push(format!("{}~{}", id, version));
    }

    // the above is the adaption...

    rt.store().retrieve(path)
}

fn view_versions_of(id: &str, rt: &Runtime) {
    use glob::glob;

    let mut path = rt.store().path().clone();

    if id.chars().next() == Some('/') {
        path.push(format!("{}~*", &id[1..id.len()]));
    } else {
        path.push(format!("{}~*", id));
    }

    if let Some(path) = path.to_str() {
        match glob(path) {
            Ok(paths) =>
                for entry in paths {
                    match entry {
                        Ok(path) => println!("{}", path.file_name().and_then(|s| s.to_str()).unwrap()),
                        Err(e)   => trace_error(e.error()),
                    }
                },
            Err(e) => {
                warn!("{}", e); // trace_error(&e); // error seems not to be implemented
                debug!("Error in pattern");
                exit(1);
            },
        }
    } else {
        warn!("Could not build glob() argument!");
    }
}

<commit_msg>Remove unused imports<commit_after>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagutil;

use std::process::exit;

use libimagrt::runtime::Runtime;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Result as StoreResult;
use libimagutil::trace::trace_error;

mod ui;
mod viewer;

use ui::build_ui;
use viewer::Viewer;
use viewer::ViewInformation;
use viewer::stdout::StdoutViewer;

fn main() {
    let name = "imag-view";
    let version = &version!()[..];
    let about = "View entries (readonly)";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));
    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.err().unwrap());
            exit(1);
        }
    };

    rt.init_logger();

    debug!("Hello. Logging was just enabled");
    debug!("I already set up the Runtime object and build the commandline interface parser.");
    debug!("Lets get rollin' ...");

    info!("No implementation yet");

    let entry_id = rt.cli().value_of("id").unwrap(); // enforced by clap

    if rt.cli().is_present("versions") {
        view_versions_of(entry_id, &rt);
    } else {
        let entry_version   = rt.cli().value_of("version");
        let view_header     = rt.cli().is_present("view-header");
        let view_content    = rt.cli().is_present("view-content");
        let view_copy       = rt.cli().is_present("view-copy");
        let keep_copy       = rt.cli().is_present("keep-copy");

        let scmd = rt.cli().subcommand_matches("view-in");
        if scmd.is_none() {
            debug!("No commandline call");
            exit(1);
        }
        let scmd = scmd.unwrap();

        let viewer = build_viewer(scmd);
        let entry = load_entry(entry_id, entry_version, &rt);
        if entry.is_err() {
            trace_error(&entry.err().unwrap());
            exit(1);
        }
        let entry = entry.unwrap();

        let view_info = ViewInformation {
            entry:          entry,
            view_header:    view_header,
            view_content:   view_content,
            view_copy:      view_copy,
            keep_copy:      keep_copy,
        };

        let viewer = StdoutViewer::new();
        viewer.view(view_info);
    }
}

// TODO: This is a shameless adaption of imag-store/src/util.rs
fn load_entry<'a>(id: &str,
                  version: Option<&str>,
                  rt: &'a Runtime)
    -> StoreResult<FileLockEntry<'a>>
{
    debug!("Checking path element for version");

    let version = {
        version.unwrap_or_else(|| {
            id.split("~").last().unwrap_or_else(|| {
                warn!("No version");
                exit(1);
            })
        })
    };

    debug!("Building path from {:?} and {:?}", id, version);
    let mut path = rt.store().path().clone();

    if id.chars().next() == Some('/') {
        path.push(format!("{}~{}", &id[1..id.len()], version));
    } else {
        path.push(format!("{}~{}", id, version));
    }

    // the above is the adaption...

    rt.store().retrieve(path)
}

fn view_versions_of(id: &str, rt: &Runtime) {
    use glob::glob;

    let mut path = rt.store().path().clone();

    if id.chars().next() == Some('/') {
        path.push(format!("{}~*", &id[1..id.len()]));
    } else {
        path.push(format!("{}~*", id));
    }

    if let Some(path) = path.to_str() {
        match glob(path) {
            Ok(paths) =>
                for entry in paths {
                    match entry {
                        Ok(path) => println!("{}", path.file_name().and_then(|s| s.to_str()).unwrap()),
                        Err(e)   => trace_error(e.error()),
                    }
                },
            Err(e) => {
                warn!("{}", e); // trace_error(&e); // error seems not to be implemented
                debug!("Error in pattern");
                exit(1);
            },
        }
    } else {
        warn!("Could not build glob() argument!");
    }
}

<|endoftext|>


<commit_before>
struct median_filter_t<'a> {
    window: &'a mut Vec<u8>,
    input: &'a mut Vec<u8>,
    hole: i64,
    max: i64,
}

fn median_init(f: &mut median_filter_t, w_size: usize){
    f.max = 0;
    f.hole = 0;

    *f.window = Vec::with_capacity(w_size);
    *f.input = Vec::with_capacity(w_size/2);
}

fn median_close_hole(f: &mut median_filter_t) {
    while f.hole < f.max - 1 {
        let i: usize = f.hole as usize;
        f.window[i] = f.window[i + 1];
        f.hole += 1;
    }

    if f.hole == f.max - 1 {
        f.max = f.max - 1;
    }
}

fn media_remove(f: &mut median_filter_t, v: u8) {
    median_close_hole(f);

    let mut lo: i64 = 0;
    let mut hi: i64 = f.max - 1;

    f.hole = (hi / 2) as i64;

    while lo <= hi {
        let i: usize = f.hole as usize;
        if v > f.window[i] {
            lo = f.hole + 1;
        } else if v < f.window[i] {
            hi = f.hole - 1;
        } else {
            break;
        }
        f.hole = (lo + hi) / 2;
    }
}

fn median_add(f: &mut median_filter_t, v: u8) {
    if f.hole == f.max {
        f.max += 1;
    }

    let mut i: usize = f.hole as usize;
    while (f.hole > 0) && (f.window[i] > v) {
        f.window[i] = f.window[i-1];
        f.hole -= 1;
        i = f.hole as usize;
    }

    i = f.hole as usize;

    while (f.hole < f.max - 1) && (f.window[i+1] < v) {
        f.window[i] = f.window[i+1];
        f.hole += 1;
        i = f.hole as usize;
    }

    f.window[i] = v;
    f.hole = f.max;
}

fn main() {
    println!("Hello, world!");
}
<commit_msg>add median_get function<commit_after>
struct median_filter_t<'a> {
    window: &'a mut Vec<u8>,
    input: &'a mut Vec<u8>,
    hole: i64,
    max: i64,
}

fn median_init(f: &mut median_filter_t, w_size: usize){
    f.max = 0;
    f.hole = 0;

    *f.window = Vec::with_capacity(w_size);
    *f.input = Vec::with_capacity(w_size/2);
}

fn median_close_hole(f: &mut median_filter_t) {
    while f.hole < f.max - 1 {
        let i: usize = f.hole as usize;
        f.window[i] = f.window[i + 1];
        f.hole += 1;
    }

    if f.hole == f.max - 1 {
        f.max = f.max - 1;
    }
}

fn media_remove(f: &mut median_filter_t, v: u8) {
    median_close_hole(f);

    let mut lo: i64 = 0;
    let mut hi: i64 = f.max - 1;

    f.hole = (hi / 2) as i64;

    while lo <= hi {
        let i: usize = f.hole as usize;
        if v > f.window[i] {
            lo = f.hole + 1;
        } else if v < f.window[i] {
            hi = f.hole - 1;
        } else {
            break;
        }
        f.hole = (lo + hi) / 2;
    }
}

fn median_add(f: &mut median_filter_t, v: u8) {
    if f.hole == f.max {
        f.max += 1;
    }

    let mut i: usize = f.hole as usize;
    while (f.hole > 0) && (f.window[i] > v) {
        f.window[i] = f.window[i-1];
        f.hole -= 1;
        i = f.hole as usize;
    }

    i = f.hole as usize;

    while (f.hole < f.max - 1) && (f.window[i+1] < v) {
        f.window[i] = f.window[i+1];
        f.hole += 1;
        i = f.hole as usize;
    }

    f.window[i] = v;
    f.hole = f.max;
}

fn median_get(f: &mut median_filter_t) -> u8 {
    median_close_hole(f);

    if f.max == 0 {
        return 0;
    }

    if (f.max & 1i64) == 1 {
        let i: usize = f.max as usize;
        return f.window[(i-1)/2];
    } else {
        let i: usize = f.max as usize;
        return (f.window[(i-1)/2] + f.window[i/2]) / 2;
    }
}

fn main() {
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::default::Default;
use std::io::stdout;
use std::io::Write;

use toml::Value;

use libimagentrylist::lister::Lister;
use libimagentrylist::result::Result;
use libimagerror::trace::trace_error;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagerror::into::IntoError;
use libimagentrylist::error::ListErrorKind as LEK;

use reference::Ref;
use error::MapErrInto;
use error::RefErrorKind as REK;

pub struct RefLister {
    check_dead: bool,
    check_changed: bool,
    check_changed_content: bool,
    check_changed_permiss: bool,
}

impl RefLister {

    pub fn new() -> RefLister {
        RefLister::default()
    }

    pub fn check_dead(mut self, b: bool) -> RefLister {
        self.check_dead = b;
        self
    }

    pub fn check_changed(mut self, b: bool) -> RefLister {
        self.check_changed = b;
        self
    }

    pub fn check_changed_content(mut self, b: bool) -> RefLister {
        self.check_changed_content = b;
        self
    }

    pub fn check_changed_permiss(mut self, b: bool) -> RefLister {
        self.check_changed_permiss = b;
        self
    }

}

impl Default for RefLister {

    fn default() -> RefLister {
        RefLister {
            check_dead: false,
            check_changed: false,
            check_changed_content: false,
            check_changed_permiss: false,
        }
    }
}

impl Lister for RefLister {

    fn list<'b, I: Iterator<Item = FileLockEntry<'b>>>(&self, entries: I) -> Result<()> {

        debug!("Called list()");
        let (r, n) = entries.fold((Ok(()), 0), |(accu, i), entry| {
            debug!("fold({:?}, {:?})", accu, entry);
            let r = accu.and_then(|_| {
                    debug!("Listing Entry: {:?}", entry);
                    lister_fn(entry,
                              self.check_dead,
                              self.check_changed,
                              self.check_changed_content,
                              self.check_changed_permiss)
                        .and_then(|s| {
                            write!(stdout(), "{}\n", s)
                                .map_err(Box::new)
                                .map_err(|e| LEK::FormatError.into_error_with_cause(e))
                        })
                        .map_err_into(REK::RefToDisplayError)
                })
                .map(|_| ());
            (r, i + 1)
        });
        debug!("Iterated over {} entries", n);
        r.map_err(|e| LEK::FormatError.into_error_with_cause(Box::new(e)))
    }

}

fn lister_fn(fle: FileLockEntry,
             do_check_dead: bool,
             do_check_changed: bool,
             do_check_changed_content: bool,
             do_check_changed_permiss: bool) -> Result<String>
{
    Ref::from_filelockentry(fle)
        .map(|r| {
            let is_dead = if do_check_dead {
                if check_dead(&r) { "dead" } else { "alive" }
            } else {
                "not checked"
            };

            let is_changed = if do_check_changed {
                if check_changed(&r) { "changed" } else { "unchanged" }
            } else {
                "not checked"
            };

            let is_changed_content = if do_check_changed_content {
                if check_changed_content(&r) { "changed" } else { "unchanged" }
            } else {
                "not checked"
            };

            let is_changed_permiss = if do_check_changed_permiss {
                if check_changed_permiss(&r) { "changed" } else { "unchanged" }
            } else {
                "not checked"
            };

            format!("{} | {} | {} | {} | {} | {}",
                    is_dead,
                    is_changed,
                    is_changed_content,
                    is_changed_permiss,
                    r.get_path_hash().unwrap_or_else(|| String::from("Cannot get hash")),
                    r.get_location())
        })
        .map_err(|e| LEK::FormatError.into_error_with_cause(Box::new(e)))
}

fn check_dead(r: &Ref) -> bool {
    match r.fs_link_exists() {
        Ok(b)  => b,
        Err(e) => {
            warn!("Could not check whether the ref {} exists on the FS:", r);
            trace_error(&e);

            // We continue here and tell the callee that this reference is dead, what is kind of
            // true actually, as we might not have access to it right now
            true
        },
    }
}

fn check_changed(r: &Ref) -> bool {
    check_changed_content(r) && check_changed_permiss(r)
}

fn check_changed_content(r: &Ref) -> bool {
    let eq = r.get_current_hash()
        .and_then(|hash| r.get_stored_hash().map(|stored| (hash, stored)))
        .map(|(hash, stored)| hash == stored);

    match eq {
        Ok(eq) => eq,
        Err(e) => {
            warn!("Could not check whether the ref {} changed on the FS:", r);
            trace_error(&e);

            // We continue here and tell the callee that this reference is unchanged
            false
        },
    }
}

fn check_changed_permiss(_: &Ref) -> bool {
    warn!("Permission changes tracking not supported yet.");
    false
}

<commit_msg>Remove unused imports<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::default::Default;
use std::io::stdout;
use std::io::Write;

use libimagentrylist::lister::Lister;
use libimagentrylist::result::Result;
use libimagerror::trace::trace_error;
use libimagstore::store::FileLockEntry;
use libimagerror::into::IntoError;
use libimagentrylist::error::ListErrorKind as LEK;

use reference::Ref;
use error::MapErrInto;
use error::RefErrorKind as REK;

pub struct RefLister {
    check_dead: bool,
    check_changed: bool,
    check_changed_content: bool,
    check_changed_permiss: bool,
}

impl RefLister {

    pub fn new() -> RefLister {
        RefLister::default()
    }

    pub fn check_dead(mut self, b: bool) -> RefLister {
        self.check_dead = b;
        self
    }

    pub fn check_changed(mut self, b: bool) -> RefLister {
        self.check_changed = b;
        self
    }

    pub fn check_changed_content(mut self, b: bool) -> RefLister {
        self.check_changed_content = b;
        self
    }

    pub fn check_changed_permiss(mut self, b: bool) -> RefLister {
        self.check_changed_permiss = b;
        self
    }

}

impl Default for RefLister {

    fn default() -> RefLister {
        RefLister {
            check_dead: false,
            check_changed: false,
            check_changed_content: false,
            check_changed_permiss: false,
        }
    }
}

impl Lister for RefLister {

    fn list<'b, I: Iterator<Item = FileLockEntry<'b>>>(&self, entries: I) -> Result<()> {

        debug!("Called list()");
        let (r, n) = entries.fold((Ok(()), 0), |(accu, i), entry| {
            debug!("fold({:?}, {:?})", accu, entry);
            let r = accu.and_then(|_| {
                    debug!("Listing Entry: {:?}", entry);
                    lister_fn(entry,
                              self.check_dead,
                              self.check_changed,
                              self.check_changed_content,
                              self.check_changed_permiss)
                        .and_then(|s| {
                            write!(stdout(), "{}\n", s)
                                .map_err(Box::new)
                                .map_err(|e| LEK::FormatError.into_error_with_cause(e))
                        })
                        .map_err_into(REK::RefToDisplayError)
                })
                .map(|_| ());
            (r, i + 1)
        });
        debug!("Iterated over {} entries", n);
        r.map_err(|e| LEK::FormatError.into_error_with_cause(Box::new(e)))
    }

}

fn lister_fn(fle: FileLockEntry,
             do_check_dead: bool,
             do_check_changed: bool,
             do_check_changed_content: bool,
             do_check_changed_permiss: bool) -> Result<String>
{
    Ref::from_filelockentry(fle)
        .map(|r| {
            let is_dead = if do_check_dead {
                if check_dead(&r) { "dead" } else { "alive" }
            } else {
                "not checked"
            };

            let is_changed = if do_check_changed {
                if check_changed(&r) { "changed" } else { "unchanged" }
            } else {
                "not checked"
            };

            let is_changed_content = if do_check_changed_content {
                if check_changed_content(&r) { "changed" } else { "unchanged" }
            } else {
                "not checked"
            };

            let is_changed_permiss = if do_check_changed_permiss {
                if check_changed_permiss(&r) { "changed" } else { "unchanged" }
            } else {
                "not checked"
            };

            format!("{} | {} | {} | {} | {} | {}",
                    is_dead,
                    is_changed,
                    is_changed_content,
                    is_changed_permiss,
                    r.get_path_hash().unwrap_or_else(|| String::from("Cannot get hash")),
                    r.get_location())
        })
        .map_err(|e| LEK::FormatError.into_error_with_cause(Box::new(e)))
}

fn check_dead(r: &Ref) -> bool {
    match r.fs_link_exists() {
        Ok(b)  => b,
        Err(e) => {
            warn!("Could not check whether the ref {} exists on the FS:", r);
            trace_error(&e);

            // We continue here and tell the callee that this reference is dead, what is kind of
            // true actually, as we might not have access to it right now
            true
        },
    }
}

fn check_changed(r: &Ref) -> bool {
    check_changed_content(r) && check_changed_permiss(r)
}

fn check_changed_content(r: &Ref) -> bool {
    let eq = r.get_current_hash()
        .and_then(|hash| r.get_stored_hash().map(|stored| (hash, stored)))
        .map(|(hash, stored)| hash == stored);

    match eq {
        Ok(eq) => eq,
        Err(e) => {
            warn!("Could not check whether the ref {} changed on the FS:", r);
            trace_error(&e);

            // We continue here and tell the callee that this reference is unchanged
            false
        },
    }
}

fn check_changed_permiss(_: &Ref) -> bool {
    warn!("Permission changes tracking not supported yet.");
    false
}

<|endoftext|>