<commit_before>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::{self, File};
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
use std::process;

use regex::Regex;

use super::{Error, Result};

const CONTROLLER_CPU: &str = "cpu";

const CONTROLLER_CPUSET: &str = "cpuset";
const CPUSET_CPUS: &str = "cpuset.cpus";
const CPUSET_MEMS: &str = "cpuset.mems";

const CONTROLLER_PIDS: &str = "pids";

// The list of cgroup controllers we're interested in.
const CONTROLLERS: [&'static str; 3] = [CONTROLLER_CPU, CONTROLLER_CPUSET, CONTROLLER_PIDS];
const PROC_MOUNTS: &str = "/proc/mounts";
const NODE_TO_CPULIST: &str = "/sys/devices/system/node/node";

pub struct Cgroup {
    tasks_files: Vec<PathBuf>,
}

// It's called writeln_special because we have to use this rather convoluted way of writing
// to special cgroup files, to avoid getting errors. It would be nice to know why that happens :-s
fn writeln_special<T, V>(file_path: &T, value: V) -> Result<()>
where
    T: AsRef<Path>,
    V: ::std::fmt::Display,
{
    fs::write(file_path, format!("{}\n", value))
        .map_err(|e| Error::Write(PathBuf::from(file_path.as_ref()), e))
}

fn readln_special<T: AsRef<Path>>(file_path: &T) -> Result<String> {
    let mut line = fs::read_to_string(file_path)
        .map_err(|e| Error::ReadToString(PathBuf::from(file_path.as_ref()), e))?;

    // Remove the newline character at the end (if any).
    line.pop();

    Ok(line)
}

// If we call inherit_from_parent_aux(.../A/B/C, file, condition), the following will happen:
// 1) If .../A/B/C/file does not exist, or if .../A/B/file does not exist, return an error.
// 2) If .../A/B/file is not empty, write the first line of .../A/B/file into .../A/B/C/file
// and return.
// 3) If ../A/B/file exists but it is empty, call inherit_from_parent_aux(.../A/B, file, false).
// 4) If .../A/B/file is no longer empty, write the first line of .../A/B/file into
// .../A/B/C/file, and return.
// 5) Otherwise, return an error.

// How is this helpful? When creating cgroup folders for the jailer Firecracker instance, the jailer
// will create a hierarchy that looks like <cgroup_base>/firecracker/<id>. Depending on each
// particular cgroup controller, <cgroup_base> contains a number of configuration files. These are
// not actually present on a disk; they are special files exposed by the controller, and they
// usually contain a single line with some configuration value(s). When the "firecracker" and <id>
// subfolders are created, configuration files with the same name appear automatically in the new
// folders, but their contents are not always automatically populated. Moreover,
// if <cgroup_base>/firecracker/some_file is empty, then we cannot have a non-empty file with
// at <cgroup_base>/firecracker/<id>/some_file. The inherit_from_parent function (which is based
// on the following helper function) helps with propagating the values.

// There is also a potential race condition mentioned below. Here is what it refers to: let's say we
// start multiple jailer processes, and one of them calls
// inherit_from_parent_aux(/A/firecracker/id1, file, true), and hits case number 3) from the list
// above, thus recursively calling inherit_from_parent_aux(/A/firecracker, file, false). It's
// entirely possible there was another process in the exact same situations, and that process
// gets to write something to /A/firecracker/file first. In this case, the recursive call made by
// the first process to inherit_from_parent_aux(/A/firecracker, file, false) may fail when writing
// to /A/firecracker/file, but we can still continue, because step 4) only cares about the file
// no longer being empty, regardless of who actually got to populated its contents.

fn inherit_from_parent_aux(
    path: &mut PathBuf,
    file_name: &str,
    retry_one_level_up: bool,
) -> Result<()> {
    // The function with_file_name() replaces the last component of a path with the given name.
    let parent_file = path.with_file_name(file_name);

    let mut line = readln_special(&parent_file)?;
    if line.is_empty() {
        if retry_one_level_up {
            // We have to borrow "parent" from "parent_file" as opposed to "path", because then
            // we wouldn't be able to mutably borrow path at the end of this function (at least not
            // according to how the Rust borrow checker operates right now :-s)
            let parent = parent_file
                .parent()
                .ok_or_else(|| Error::MissingParent(parent_file.clone()))?;

            // Trying to avoid the race condition described above. We don't care about the result,
            // because we check once more if line.is_empty() after the end of this block.
            let _ = inherit_from_parent_aux(&mut parent.to_path_buf(), file_name, false);
            line = readln_special(&parent_file)?;
        }

        if line.is_empty() {
            return Err(Error::CgroupInheritFromParent(
                path.to_path_buf(),
                file_name.to_string(),
            ));
        }
    }

    path.push(file_name);
    writeln_special(&path, &line)?;
    path.pop();

    Ok(())
}

// The path reference is &mut here because we do a push to get the destination file name. However,
// a pop follows shortly after (see fn inherit_from_parent_aux), reverting to the original value.
fn inherit_from_parent(path: &mut PathBuf, file_name: &str) -> Result<()> {
    inherit_from_parent_aux(path, file_name, true)
}

impl Cgroup {
    pub fn new(id: &str, numa_node: u32, exec_file_name: &OsStr) -> Result<Self> {
        let f =
            File::open(PROC_MOUNTS).map_err(|e| Error::FileOpen(PathBuf::from(PROC_MOUNTS), e))?;

        let mut found_controllers: HashMap<&'static str, PathBuf> =
            HashMap::with_capacity(CONTROLLERS.len());

        // Regex courtesy of Filippo.
        let re = Regex::new(
            r"^cgroup[[:space:]](?P<dir>.*)[[:space:]]cgroup[[:space:]](?P<options>.*)[[:space:]]0[[:space:]]0$",
        ).map_err(Error::RegEx)?;
        for l in BufReader::new(f).lines() {
            let l = l.map_err(|e| Error::ReadLine(PathBuf::from(PROC_MOUNTS), e))?;
            if let Some(capture) = re.captures(&l) {
                // We could do the search in a more efficient manner but eh.
                let v: Vec<&str> = capture["options"].split(',').collect();

                for controller in CONTROLLERS.into_iter() {
                    if v.contains(controller) {
                        if let Some(_) =
                            found_controllers.insert(controller, PathBuf::from(&capture["dir"]))
                        {
                            return Err(Error::CgroupLineNotUnique(
                                PROC_MOUNTS.to_string(),
                                controller.to_string(),
                            ));
                        }
                    }
                }
            }
        }

        let keys_len = found_controllers.keys().len();

        if keys_len < CONTROLLERS.len() {
            // We return an error about the first one we didn't find.
            for controller in CONTROLLERS.into_iter() {
                if !found_controllers.contains_key(controller) {
                    return Err(Error::CgroupLineNotFound(
                        PROC_MOUNTS.to_string(),
                        controller.to_string(),
                    ));
                }
            }
        }

        // This is just a sanity check.
        assert_eq!(keys_len, CONTROLLERS.len());

        // We now both create the cgroup subfolders, and fill the tasks_files vector.
        let mut tasks_files = Vec::with_capacity(keys_len);

        for (controller, mut path_buf) in found_controllers.drain() {
            path_buf.push(exec_file_name);
            path_buf.push(id);

            fs::create_dir_all(&path_buf).map_err(|e| Error::CreateDir(path_buf.clone(), e))?;

            // For now, the jailer is only populating configuration values for the cpuset
            // controller, related to the cpu cores we are allowed to run on, and the numa node we
            // want to restrict to. The jailer only creates the folder hierarchy for other cgroups,
            // and the customer has to provide any desired configuration explicitly (if any).

            if controller == CONTROLLER_CPUSET {
                inherit_from_parent(&mut path_buf, CPUSET_CPUS)?;

                // TODO: this does make an unnecessary write, as we change the value of the
                // "cpuset.mems" file again at the end of the for block. Maybe fix this sometime.
                inherit_from_parent(&mut path_buf, CPUSET_MEMS)?;

                // Enforce NUMA node restriction.
                // The cpuset subsystem assigns individual CPUs and memory nodes to cgroups.
                // CPUSET_MEMS specifies the memory nodes that tasks in this cgroup are permitted to
                // access.
                path_buf.push(CPUSET_MEMS);
                writeln_special(&path_buf, numa_node)?;
                path_buf.pop();
                // Similar to how numactl library does, we are copying the contents of
                // /sys/devices/system/node/nodeX/cpulist to the cpuset.cpus file for ensuring
                // correct numa cpu assignment.
                let line = readln_special(&PathBuf::from(format!(
                    "{}{}/cpulist",
                    NODE_TO_CPULIST, numa_node
                )))?;
                path_buf.push(CPUSET_CPUS);
                writeln_special(&path_buf, line)?;
                path_buf.pop();
            }

            // And now add "tasks" to get the path of the corresponding tasks file.
            path_buf.push("tasks");
            if !tasks_files.contains(&path_buf) {
                tasks_files.push(path_buf);
            }
        }

        Ok(Cgroup { tasks_files })
    }

    // This writes the pid of the current process to each tasks file. These are special files that,
    // when written to, will assign the process associated with the pid to the respective cgroup.
    pub fn attach_pid(&self) -> Result<()> {
        let pid = process::id();
        for tasks_file in &self.tasks_files {
            writeln_special(tasks_file, pid)?;
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    extern crate tempfile;

    use self::tempfile::{tempdir, tempdir_in, NamedTempFile};
    use super::*;
    use std::io::Write;
    use std::path::PathBuf;

    #[test]
    fn test_inherit_from_parent() {
        // 1. If parent file does not exist, return an error.

        // This is /A/B/ .
        let dir = tempdir().expect("Cannot create temporary directory.");
        // This is /A/B/C .
        let dir2 = tempdir_in(dir.path()).expect("Cannot create temporary directory.");
        let path2 = PathBuf::from(dir2.path());
        let result = inherit_from_parent(&mut PathBuf::from(&path2), "inexistent");
        assert!(result.is_err());
        assert!(format!("{:?}", result).contains("ReadToString"));

        // 2. If parent file exists and is empty, will go one level up, and return error because
        // the grandparent file does not exist.
        let mut named_file = NamedTempFile::new_in(dir.path()).expect("Cannot create named file.");
        let result = inherit_from_parent(
            &mut PathBuf::from(path2.clone()),
            named_file.path().file_name().unwrap().to_str().unwrap(),
        );
        assert!(result.is_err());
        assert!(format!("{:?}", result).contains("CgroupInheritFromParent"));

        let child_file = dir2
            .path()
            .join(named_file.path().file_name().unwrap().to_str().unwrap());

        // 3. If parent file exists and is not empty, will return ok and child file will have its
        // contents.
        let some_line = "Parent line";
        writeln!(named_file, "{}", some_line).expect("Cannot write to file.");
        let result = inherit_from_parent(
            &mut PathBuf::from(path2),
            named_file.path().file_name().unwrap().to_str().unwrap(),
        );
        assert!(result.is_ok());
        let res = readln_special(&child_file).expect("Cannot read from file.");
        assert!(res == some_line);
    }
}
<commit_msg>Jailer: Allow 'none' device for cgroups<commit_after>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::{self, File};
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
use std::process;

use regex::Regex;

use super::{Error, Result};

const CONTROLLER_CPU: &str = "cpu";

const CONTROLLER_CPUSET: &str = "cpuset";
const CPUSET_CPUS: &str = "cpuset.cpus";
const CPUSET_MEMS: &str = "cpuset.mems";

const CONTROLLER_PIDS: &str = "pids";

// The list of cgroup controllers we're interested in.
const CONTROLLERS: [&'static str; 3] = [CONTROLLER_CPU, CONTROLLER_CPUSET, CONTROLLER_PIDS];
const PROC_MOUNTS: &str = "/proc/mounts";
const NODE_TO_CPULIST: &str = "/sys/devices/system/node/node";

pub struct Cgroup {
    tasks_files: Vec<PathBuf>,
}

// It's called writeln_special because we have to use this rather convoluted way of writing
// to special cgroup files, to avoid getting errors. It would be nice to know why that happens :-s
fn writeln_special<T, V>(file_path: &T, value: V) -> Result<()>
where
    T: AsRef<Path>,
    V: ::std::fmt::Display,
{
    fs::write(file_path, format!("{}\n", value))
        .map_err(|e| Error::Write(PathBuf::from(file_path.as_ref()), e))
}

fn readln_special<T: AsRef<Path>>(file_path: &T) -> Result<String> {
    let mut line = fs::read_to_string(file_path)
        .map_err(|e| Error::ReadToString(PathBuf::from(file_path.as_ref()), e))?;

    // Remove the newline character at the end (if any).
    line.pop();

    Ok(line)
}

// If we call inherit_from_parent_aux(.../A/B/C, file, condition), the following will happen:
// 1) If .../A/B/C/file does not exist, or if .../A/B/file does not exist, return an error.
// 2) If .../A/B/file is not empty, write the first line of .../A/B/file into .../A/B/C/file
// and return.
// 3) If ../A/B/file exists but it is empty, call inherit_from_parent_aux(.../A/B, file, false).
// 4) If .../A/B/file is no longer empty, write the first line of .../A/B/file into
// .../A/B/C/file, and return.
// 5) Otherwise, return an error.

// How is this helpful? When creating cgroup folders for the jailer Firecracker instance, the jailer
// will create a hierarchy that looks like <cgroup_base>/firecracker/<id>. Depending on each
// particular cgroup controller, <cgroup_base> contains a number of configuration files. These are
// not actually present on a disk; they are special files exposed by the controller, and they
// usually contain a single line with some configuration value(s). When the "firecracker" and <id>
// subfolders are created, configuration files with the same name appear automatically in the new
// folders, but their contents are not always automatically populated. Moreover,
// if <cgroup_base>/firecracker/some_file is empty, then we cannot have a non-empty file with
// at <cgroup_base>/firecracker/<id>/some_file. The inherit_from_parent function (which is based
// on the following helper function) helps with propagating the values.

// There is also a potential race condition mentioned below. Here is what it refers to: let's say we
// start multiple jailer processes, and one of them calls
// inherit_from_parent_aux(/A/firecracker/id1, file, true), and hits case number 3) from the list
// above, thus recursively calling inherit_from_parent_aux(/A/firecracker, file, false). It's
// entirely possible there was another process in the exact same situations, and that process
// gets to write something to /A/firecracker/file first. In this case, the recursive call made by
// the first process to inherit_from_parent_aux(/A/firecracker, file, false) may fail when writing
// to /A/firecracker/file, but we can still continue, because step 4) only cares about the file
// no longer being empty, regardless of who actually got to populated its contents.

fn inherit_from_parent_aux(
    path: &mut PathBuf,
    file_name: &str,
    retry_one_level_up: bool,
) -> Result<()> {
    // The function with_file_name() replaces the last component of a path with the given name.
    let parent_file = path.with_file_name(file_name);

    let mut line = readln_special(&parent_file)?;
    if line.is_empty() {
        if retry_one_level_up {
            // We have to borrow "parent" from "parent_file" as opposed to "path", because then
            // we wouldn't be able to mutably borrow path at the end of this function (at least not
            // according to how the Rust borrow checker operates right now :-s)
            let parent = parent_file
                .parent()
                .ok_or_else(|| Error::MissingParent(parent_file.clone()))?;

            // Trying to avoid the race condition described above. We don't care about the result,
            // because we check once more if line.is_empty() after the end of this block.
            let _ = inherit_from_parent_aux(&mut parent.to_path_buf(), file_name, false);
            line = readln_special(&parent_file)?;
        }

        if line.is_empty() {
            return Err(Error::CgroupInheritFromParent(
                path.to_path_buf(),
                file_name.to_string(),
            ));
        }
    }

    path.push(file_name);
    writeln_special(&path, &line)?;
    path.pop();

    Ok(())
}

// The path reference is &mut here because we do a push to get the destination file name. However,
// a pop follows shortly after (see fn inherit_from_parent_aux), reverting to the original value.
fn inherit_from_parent(path: &mut PathBuf, file_name: &str) -> Result<()> {
    inherit_from_parent_aux(path, file_name, true)
}

impl Cgroup {
    pub fn new(id: &str, numa_node: u32, exec_file_name: &OsStr) -> Result<Self> {
        let f =
            File::open(PROC_MOUNTS).map_err(|e| Error::FileOpen(PathBuf::from(PROC_MOUNTS), e))?;

        let mut found_controllers: HashMap<&'static str, PathBuf> =
            HashMap::with_capacity(CONTROLLERS.len());

        // Regex courtesy of Filippo.
        let re = Regex::new(
            r"^(cgroup|none)[[:space:]](?P<dir>.*)[[:space:]]cgroup[[:space:]](?P<options>.*)[[:space:]]0[[:space:]]0$",
        ).map_err(Error::RegEx)?;
        for l in BufReader::new(f).lines() {
            let l = l.map_err(|e| Error::ReadLine(PathBuf::from(PROC_MOUNTS), e))?;
            if let Some(capture) = re.captures(&l) {
                // We could do the search in a more efficient manner but eh.
                let v: Vec<&str> = capture["options"].split(',').collect();

                for controller in CONTROLLERS.into_iter() {
                    if v.contains(controller) {
                        if let Some(_) =
                            found_controllers.insert(controller, PathBuf::from(&capture["dir"]))
                        {
                            return Err(Error::CgroupLineNotUnique(
                                PROC_MOUNTS.to_string(),
                                controller.to_string(),
                            ));
                        }
                    }
                }
            }
        }

        let keys_len = found_controllers.keys().len();

        if keys_len < CONTROLLERS.len() {
            // We return an error about the first one we didn't find.
            for controller in CONTROLLERS.into_iter() {
                if !found_controllers.contains_key(controller) {
                    return Err(Error::CgroupLineNotFound(
                        PROC_MOUNTS.to_string(),
                        controller.to_string(),
                    ));
                }
            }
        }

        // This is just a sanity check.
        assert_eq!(keys_len, CONTROLLERS.len());

        // We now both create the cgroup subfolders, and fill the tasks_files vector.
        let mut tasks_files = Vec::with_capacity(keys_len);

        for (controller, mut path_buf) in found_controllers.drain() {
            path_buf.push(exec_file_name);
            path_buf.push(id);

            fs::create_dir_all(&path_buf).map_err(|e| Error::CreateDir(path_buf.clone(), e))?;

            // For now, the jailer is only populating configuration values for the cpuset
            // controller, related to the cpu cores we are allowed to run on, and the numa node we
            // want to restrict to. The jailer only creates the folder hierarchy for other cgroups,
            // and the customer has to provide any desired configuration explicitly (if any).

            if controller == CONTROLLER_CPUSET {
                inherit_from_parent(&mut path_buf, CPUSET_CPUS)?;

                // TODO: this does make an unnecessary write, as we change the value of the
                // "cpuset.mems" file again at the end of the for block. Maybe fix this sometime.
                inherit_from_parent(&mut path_buf, CPUSET_MEMS)?;

                // Enforce NUMA node restriction.
                // The cpuset subsystem assigns individual CPUs and memory nodes to cgroups.
                // CPUSET_MEMS specifies the memory nodes that tasks in this cgroup are permitted to
                // access.
                path_buf.push(CPUSET_MEMS);
                writeln_special(&path_buf, numa_node)?;
                path_buf.pop();
                // Similar to how numactl library does, we are copying the contents of
                // /sys/devices/system/node/nodeX/cpulist to the cpuset.cpus file for ensuring
                // correct numa cpu assignment.
                let line = readln_special(&PathBuf::from(format!(
                    "{}{}/cpulist",
                    NODE_TO_CPULIST, numa_node
                )))?;
                path_buf.push(CPUSET_CPUS);
                writeln_special(&path_buf, line)?;
                path_buf.pop();
            }

            // And now add "tasks" to get the path of the corresponding tasks file.
            path_buf.push("tasks");
            if !tasks_files.contains(&path_buf) {
                tasks_files.push(path_buf);
            }
        }

        Ok(Cgroup { tasks_files })
    }

    // This writes the pid of the current process to each tasks file. These are special files that,
    // when written to, will assign the process associated with the pid to the respective cgroup.
    pub fn attach_pid(&self) -> Result<()> {
        let pid = process::id();
        for tasks_file in &self.tasks_files {
            writeln_special(tasks_file, pid)?;
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    extern crate tempfile;

    use self::tempfile::{tempdir, tempdir_in, NamedTempFile};
    use super::*;
    use std::io::Write;
    use std::path::PathBuf;

    #[test]
    fn test_inherit_from_parent() {
        // 1. If parent file does not exist, return an error.

        // This is /A/B/ .
        let dir = tempdir().expect("Cannot create temporary directory.");
        // This is /A/B/C .
        let dir2 = tempdir_in(dir.path()).expect("Cannot create temporary directory.");
        let path2 = PathBuf::from(dir2.path());
        let result = inherit_from_parent(&mut PathBuf::from(&path2), "inexistent");
        assert!(result.is_err());
        assert!(format!("{:?}", result).contains("ReadToString"));

        // 2. If parent file exists and is empty, will go one level up, and return error because
        // the grandparent file does not exist.
        let mut named_file = NamedTempFile::new_in(dir.path()).expect("Cannot create named file.");
        let result = inherit_from_parent(
            &mut PathBuf::from(path2.clone()),
            named_file.path().file_name().unwrap().to_str().unwrap(),
        );
        assert!(result.is_err());
        assert!(format!("{:?}", result).contains("CgroupInheritFromParent"));

        let child_file = dir2
            .path()
            .join(named_file.path().file_name().unwrap().to_str().unwrap());

        // 3. If parent file exists and is not empty, will return ok and child file will have its
        // contents.
        let some_line = "Parent line";
        writeln!(named_file, "{}", some_line).expect("Cannot write to file.");
        let result = inherit_from_parent(
            &mut PathBuf::from(path2),
            named_file.path().file_name().unwrap().to_str().unwrap(),
        );
        assert!(result.is_ok());
        let res = readln_special(&child_file).expect("Cannot read from file.");
        assert!(res == some_line);
    }
}
<|endoftext|>


<commit_before>fn largest<T>(list: &[T]) -> T {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

struct Point<T, U> {
    x: T,
    y: U,
}

impl<T, U> Point<T, U> {
    fn x(&self) -> &T {
        &self.x
    }
}

impl<T, U> Point<T, U> {
    fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
        Point {
            x: self.x,
            y: other.y
        }
    }
}

fn main() {
    let numbers = vec![1, 3, 2, 5, 0];

    let result = largest(&numbers);

    println!("The largest number is {}", result);
}
<commit_msg>Fix largest by adding traits bounds<commit_after>use std::cmp::PartialOrd;

fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

struct Point<T, U> {
    x: T,
    y: U,
}

impl<T, U> Point<T, U> {
    fn x(&self) -> &T {
        &self.x
    }
}

impl<T, U> Point<T, U> {
    fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
        Point {
            x: self.x,
            y: other.y
        }
    }
}

fn main() {
    let numbers = vec![1, 3, 2, 5, 0];

    let result = largest(&numbers);

    println!("The largest number is {}", result);
}
<|endoftext|>


<commit_before>extern crate sapper;
extern crate sapper_tmpl;
extern crate sapper_query;
extern crate sapper_body;
extern crate sapper_session;
extern crate sapper_logger;

extern crate serde;
extern crate serde_json;

use sapper::{Request, Response, Result};

pub use sapper::PathParams;
pub use sapper_query::QueryParams;
pub use sapper_body::FormParams;
pub use sapper_body::JsonParams;
pub use sapper_session::{ SessionVal, set_cookie };
pub use sapper_tmpl::{
    Context as WebContext,
    TERA,
    TeraResult,
    TeraValue,
    to_value,
    render,
};
pub use sapper_logger::splog;

pub fn init(req: &mut Request, cookie_key: Option<&'static str>) -> Result<()> {
    sapper_logger::init(req)?;
    sapper_query::parse(req)?;
    sapper_body::parse(req)?;
    sapper_session::session_val(req, cookie_key)?;

    Ok(())
}

pub fn finish(req: &Request, res: &mut Response) -> Result<()> {
    sapper_logger::splog(req, res.status())?;

    Ok(())
}

// ============ Status Code ============

#[macro_export]
macro_rules! res_redirect {
    ($redirect_uri:expr) => ({
        Err(SapperError::Found($redirect_uri.to_string()))
    })
}

#[macro_export]
macro_rules! res_400 {
    ($info:expr) => ({
        Err(SapperError::Break($info.to_string()))
    })
}

#[macro_export]
macro_rules! res_404 {
    () => ({
        Err(SapperError::NotFound)
    })
}

#[macro_export]
macro_rules! res_500 {
    ($info:expr) => ({
        Err(SapperError::InternalServerError($info.to_string()))
    })
}

#[macro_export]
macro_rules! set_response_redirect {
    ($response:expr, $redirect_uri:expr) => ({
        use sapper::status;
        use sapper::header::Location;

        $response.set_status(status::Found);
        //response.set_status(status::TemporaryRedirect);
        $response.headers_mut().set(Location($redirect_uri.to_owned()));
        $response.write_body(format!("redirect to {}", $redirect_uri));
    })
}

// ============ Json ============

#[macro_export]
macro_rules! res_json {
    ($json:expr) => ({
        use serde_json;
        use sapper::Response;
        use sapper::header::ContentType;

        let mut response = Response::new();
        response.headers_mut().set(ContentType::json());
        response.write_body(serde_json::to_string(&$json).unwrap());

        Ok(response)
    })
}

#[macro_export]
macro_rules! res_json_ok {
    ($info:expr) => ({
        use sapper::Response;
        use serde_json;

        let json2ret = json!({
            "success": true,
            "info": $info
        });

        res_json!(json2ret)
    })
}

#[macro_export]
macro_rules! res_json_error {
    ($info:expr) => ({
        use sapper::Response;
        use serde_json;

        let json2ret = json!({
            "success": false,
            "info": $info
        });

        res_json!(json2ret)
    })
}

// ============ Page Render ============

#[macro_export]
macro_rules! res_html {
    ($html:expr, $context:expr) => ({
        use sapper::Response;
        use sapper::header::ContentType;

        let res_str = render($html, $context);

        let mut response = Response::new();
        response.headers_mut().set(ContentType::html());
        response.write_body(res_str);

        Ok(response)
    })
}

#[macro_export]
macro_rules! res_html_before {
    ($context:expr) => ({
        Err(SapperError::CustomHtml($context))
    })
}

#[macro_export]
macro_rules! res_xml_string {
    ($context:expr) => ({
        use sapper::Response;
        use sapper::status::StatusCode;

        let mut res = Response::new();
        res.set_status(StatusCode::Ok);
        res.headers_mut().set_raw("Content-Type", vec!["text/xml".as_bytes().to_vec()]);
        res.write_body($context);

        Ok(res)
    })
}

// ============ Params ============

#[macro_export]
macro_rules! get_params {
    ($req:expr, $tykey:ty) => ({
        match $req.ext().get::<$tykey>() {
            Some(params) => {
                params
            },
            None => {
                let info = "no params";
                info!("{}", info);
                return res_400!(info);
            }
        }
    })
}

#[macro_export]
macro_rules! get_path_params {
    ($req:expr) => ({
        get_params!($req, PathParams)
    })
}

#[macro_export]
macro_rules! get_query_params {
    ($req:expr) => ({
        get_params!($req, QueryParams)
    })
}

#[macro_export]
macro_rules! get_form_params {
    ($req:expr) => ({
        get_params!($req, FormParams)
    })
}

#[macro_export]
macro_rules! get_json_params {
    ($req:expr) => ({
        match serde_json::from_value(get_params!($req, JsonParams).clone()) {
            Ok(val) => val,
            Err(_) => {
                let info = "Json parameter not match to struct.";
                info!("{}", info);
                return res_400!(info);
            }
        }
    })
}

#[macro_export]
macro_rules! t_cond {
    ($bool:expr, $prompt:expr) => ({
        match $bool {
            true => (),
            false => {
                let info = format!("test param condition result: {}", $prompt);
                info!("{}", info);
                return res_400!(info);
            }
        }
    })
}

#[macro_export]
macro_rules! _missing_or_unrecognized {
    ($field:expr) => ({
        let info = format!("missing or unrecognized parameter {}.", $field);
        info!("{}",info);
        return res_400!(info);
    })
}

#[macro_export]
macro_rules! _using_default {
    ($field:expr, $default:expr) => ({
        info!("missing or unrecognized parameter {}, using default {}.", $field, $default);
        // return default
        $default
    })
}

// for PathParams, QueryParams and FormParams
#[macro_export]
macro_rules! t_param {
    ($params:expr, $field:expr) => ({
        match $params.get($field) {
            Some(ref astr) => &astr[0],
            None =>  _missing_or_unrecognized! ($field)
        }
    })
}

// for PathParams, QueryParams and FormParams, default version
#[macro_export]
macro_rules! t_param_default {
    ($params:expr, $field:expr, $default:expr) => ({
        match $params.get($field) {
            Some(ref astr) => &astr[0],
            None =>  _using_default! ($field, $default)
        }
    })
}

#[macro_export]
macro_rules! t_param_parse {
    ($params:expr, $field:expr, $tykey:ty) => ({
        match $params.get($field) {
            Some(ref astr) => {
                let _t = &astr[0];
                match _t.parse::<$tykey>() {
                    Ok(output) => output,
                    Err(_) => {
                        let info = format!("parse parameter type error {}.", $field);
                        info!("{}", info);
                        return res_400!(info);
                    }
                }
            },
            None =>  _missing_or_unrecognized! ($field)
        }
    })
}

#[macro_export]
macro_rules! t_param_parse_default {
    ($params:expr, $field:expr, $tykey:ty, $default:expr) => ({
        match $params.get($field) {
            Some(ref astr) => {
                let _t = &astr[0];
                match _t.parse::<$tykey>() {
                    Ok(output) => output,
                    Err(_) => {
                        _using_default! ($field, $default)
                    }
                }
            },
            None =>  _using_default! ($field, $default)
        }
    })
}

#[macro_export]
macro_rules! t_arr_param {
    ($params:expr, $field:expr) => ({
        match $params.get($field) {
            Some(ref arr) => *arr,
            None =>  _missing_or_unrecognized! ($field)
        }
    })
}

#[macro_export]
macro_rules! t_arr_param_default {
    ($params:expr, $field:expr, $default:expr) => ({
        match $params.get($field) {
            Some(ref arr) => *arr,
            None =>  _using_default! ($field, $default)
        }
    })
}

#[macro_export]
macro_rules! t_has_param {
    ($params:expr, $field:expr) => ({
        match $params.get($field) {
            Some(_) => true,
            None => false
        }
    })
}

// ============ Ext Type Params ============
#[macro_export]
macro_rules! ext_type {
    ($req:expr, $tykey:ty) => ({
        match $req.ext().get::<$tykey>() {
            Some(entity) => {
                Some(entity)
            },
            None => None
        }
    })
}

#[macro_export]
macro_rules! ext_type_owned {
    ($req:expr, $tykey:ty) => ({
        match $req.ext().get::<$tykey>() {
            Some(entity) => {
                Some(entity.clone())
            },
            None => None
        }
    })
}

<commit_msg>fix a bug on std res_redirect! implementation.<commit_after>extern crate sapper;
extern crate sapper_tmpl;
extern crate sapper_query;
extern crate sapper_body;
extern crate sapper_session;
extern crate sapper_logger;

extern crate serde;
extern crate serde_json;

use sapper::{Request, Response, Result};

pub use sapper::PathParams;
pub use sapper_query::QueryParams;
pub use sapper_body::FormParams;
pub use sapper_body::JsonParams;
pub use sapper_session::{ SessionVal, set_cookie };
pub use sapper_tmpl::{
    Context as WebContext,
    TERA,
    TeraResult,
    TeraValue,
    to_value,
    render,
};
pub use sapper_logger::splog;

pub fn init(req: &mut Request, cookie_key: Option<&'static str>) -> Result<()> {
    sapper_logger::init(req)?;
    sapper_query::parse(req)?;
    sapper_body::parse(req)?;
    sapper_session::session_val(req, cookie_key)?;

    Ok(())
}

pub fn finish(req: &Request, res: &mut Response) -> Result<()> {
    sapper_logger::splog(req, res.status())?;

    Ok(())
}

// ============ Status Code ============

#[macro_export]
macro_rules! res_redirect {
    ($redirect_uri:expr) => ({
        use sapper::Response;
        use sapper::status;
        use sapper::header::Location;

        let mut response = Response::new();

        response.set_status(status::Found);
        //response.set_status(status::TemporaryRedirect);
        response.headers_mut().set(Location($redirect_uri.to_owned()));
        response.write_body(format!("redirect to {}", $redirect_uri));

        Ok(response)
    })
}

#[macro_export]
macro_rules! res_400 {
    ($info:expr) => ({
        Err(SapperError::Break($info.to_string()))
    })
}

#[macro_export]
macro_rules! res_404 {
    () => ({
        Err(SapperError::NotFound)
    })
}

#[macro_export]
macro_rules! res_500 {
    ($info:expr) => ({
        Err(SapperError::InternalServerError($info.to_string()))
    })
}

#[macro_export]
macro_rules! set_response_redirect {
    ($response:expr, $redirect_uri:expr) => ({
        use sapper::status;
        use sapper::header::Location;

        $response.set_status(status::Found);
        //response.set_status(status::TemporaryRedirect);
        $response.headers_mut().set(Location($redirect_uri.to_owned()));
        $response.write_body(format!("redirect to {}", $redirect_uri));
    })
}

// ============ Json ============

#[macro_export]
macro_rules! res_json {
    ($json:expr) => ({
        use serde_json;
        use sapper::Response;
        use sapper::header::ContentType;

        let mut response = Response::new();
        response.headers_mut().set(ContentType::json());
        response.write_body(serde_json::to_string(&$json).unwrap());

        Ok(response)
    })
}

#[macro_export]
macro_rules! res_json_ok {
    ($info:expr) => ({
        use sapper::Response;
        use serde_json;

        let json2ret = json!({
            "success": true,
            "info": $info
        });

        res_json!(json2ret)
    })
}

#[macro_export]
macro_rules! res_json_error {
    ($info:expr) => ({
        use sapper::Response;
        use serde_json;

        let json2ret = json!({
            "success": false,
            "info": $info
        });

        res_json!(json2ret)
    })
}

// ============ Page Render ============

#[macro_export]
macro_rules! res_html {
    ($html:expr, $context:expr) => ({
        use sapper::Response;
        use sapper::header::ContentType;

        let res_str = render($html, $context);

        let mut response = Response::new();
        response.headers_mut().set(ContentType::html());
        response.write_body(res_str);

        Ok(response)
    })
}

#[macro_export]
macro_rules! res_html_before {
    ($context:expr) => ({
        Err(SapperError::CustomHtml($context))
    })
}

#[macro_export]
macro_rules! res_xml_string {
    ($context:expr) => ({
        use sapper::Response;
        use sapper::status::StatusCode;

        let mut res = Response::new();
        res.set_status(StatusCode::Ok);
        res.headers_mut().set_raw("Content-Type", vec!["text/xml".as_bytes().to_vec()]);
        res.write_body($context);

        Ok(res)
    })
}

// ============ Params ============

#[macro_export]
macro_rules! get_params {
    ($req:expr, $tykey:ty) => ({
        match $req.ext().get::<$tykey>() {
            Some(params) => {
                params
            },
            None => {
                let info = "no params";
                info!("{}", info);
                return res_400!(info);
            }
        }
    })
}

#[macro_export]
macro_rules! get_path_params {
    ($req:expr) => ({
        get_params!($req, PathParams)
    })
}

#[macro_export]
macro_rules! get_query_params {
    ($req:expr) => ({
        get_params!($req, QueryParams)
    })
}

#[macro_export]
macro_rules! get_form_params {
    ($req:expr) => ({
        get_params!($req, FormParams)
    })
}

#[macro_export]
macro_rules! get_json_params {
    ($req:expr) => ({
        match serde_json::from_value(get_params!($req, JsonParams).clone()) {
            Ok(val) => val,
            Err(_) => {
                let info = "Json parameter not match to struct.";
                info!("{}", info);
                return res_400!(info);
            }
        }
    })
}

#[macro_export]
macro_rules! t_cond {
    ($bool:expr, $prompt:expr) => ({
        match $bool {
            true => (),
            false => {
                let info = format!("test param condition result: {}", $prompt);
                info!("{}", info);
                return res_400!(info);
            }
        }
    })
}

#[macro_export]
macro_rules! _missing_or_unrecognized {
    ($field:expr) => ({
        let info = format!("missing or unrecognized parameter {}.", $field);
        info!("{}",info);
        return res_400!(info);
    })
}

#[macro_export]
macro_rules! _using_default {
    ($field:expr, $default:expr) => ({
        info!("missing or unrecognized parameter {}, using default {}.", $field, $default);
        // return default
        $default
    })
}

// for PathParams, QueryParams and FormParams
#[macro_export]
macro_rules! t_param {
    ($params:expr, $field:expr) => ({
        match $params.get($field) {
            Some(ref astr) => &astr[0],
            None =>  _missing_or_unrecognized! ($field)
        }
    })
}

// for PathParams, QueryParams and FormParams, default version
#[macro_export]
macro_rules! t_param_default {
    ($params:expr, $field:expr, $default:expr) => ({
        match $params.get($field) {
            Some(ref astr) => &astr[0],
            None =>  _using_default! ($field, $default)
        }
    })
}

#[macro_export]
macro_rules! t_param_parse {
    ($params:expr, $field:expr, $tykey:ty) => ({
        match $params.get($field) {
            Some(ref astr) => {
                let _t = &astr[0];
                match _t.parse::<$tykey>() {
                    Ok(output) => output,
                    Err(_) => {
                        let info = format!("parse parameter type error {}.", $field);
                        info!("{}", info);
                        return res_400!(info);
                    }
                }
            },
            None =>  _missing_or_unrecognized! ($field)
        }
    })
}

#[macro_export]
macro_rules! t_param_parse_default {
    ($params:expr, $field:expr, $tykey:ty, $default:expr) => ({
        match $params.get($field) {
            Some(ref astr) => {
                let _t = &astr[0];
                match _t.parse::<$tykey>() {
                    Ok(output) => output,
                    Err(_) => {
                        _using_default! ($field, $default)
                    }
                }
            },
            None =>  _using_default! ($field, $default)
        }
    })
}

#[macro_export]
macro_rules! t_arr_param {
    ($params:expr, $field:expr) => ({
        match $params.get($field) {
            Some(ref arr) => *arr,
            None =>  _missing_or_unrecognized! ($field)
        }
    })
}

#[macro_export]
macro_rules! t_arr_param_default {
    ($params:expr, $field:expr, $default:expr) => ({
        match $params.get($field) {
            Some(ref arr) => *arr,
            None =>  _using_default! ($field, $default)
        }
    })
}

#[macro_export]
macro_rules! t_has_param {
    ($params:expr, $field:expr) => ({
        match $params.get($field) {
            Some(_) => true,
            None => false
        }
    })
}

// ============ Ext Type Params ============
#[macro_export]
macro_rules! ext_type {
    ($req:expr, $tykey:ty) => ({
        match $req.ext().get::<$tykey>() {
            Some(entity) => {
                Some(entity)
            },
            None => None
        }
    })
}

#[macro_export]
macro_rules! ext_type_owned {
    ($req:expr, $tykey:ty) => ({
        match $req.ext().get::<$tykey>() {
            Some(entity) => {
                Some(entity.clone())
            },
            None => None
        }
    })
}

<|endoftext|>


<commit_before>use std::fmt;
use std::collections::HashSet;

type Piece = Vec<[i32; 3]>;
type Puzzle = Vec<Piece>;

const SIN: [i32; 4] = [0, 1, 0, -1];
const COS: [i32; 4] = [1, 0, -1, 0];

#[derive(Clone, Debug)]
struct PuzzleDense {
    data: [[[i32; 3]; 3]; 3],
}

impl fmt::Display for PuzzleDense {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "{:?}", self.data[0])?;
        writeln!(f, "{:?}", self.data[1])?;
        writeln!(f, "{:?}", self.data[2])
    }
}

fn main() {
    let puzzle = blue();
    let pieces = push_to_zero(puzzle);
    for piece in &pieces {
        for part in piece {
            println!("{:?}", part);
        }
        println!("");
    }

    let mut zero = Vec::new();
    zero.push(PuzzleDense { data: zeros() });

    let piece = &pieces[0];

    let rots = all_rotations(piece);
    for solution in &rots {
        for part in solution {
            println!("{:?}", part);
        }
        println!("");
    }

    let mut solutions = Vec::new();
    for rot in rots {
        for s in all_puts(zero.clone(), 1, &rot) {
            solutions.push(s);
        }
    }
    // solutions = all_puts(solutions, 1, piece);

    //let piece = &pieces[1];
    //solutions = all_puts(solutions, 2, piece);

    for solution in solutions {
        println!("{:}", solution);
    }

}

fn all_rotations(piece: &Piece) -> Vec<Vec<[i32; 3]>> {
    let mut all_rots = Vec::new();
    for theta in 0..4 {
        let mut rotations = Vec::new();
        for [x, y, z] in piece {
            let rotated_z = [
                x*COS[theta] - y*SIN[theta],
                x*SIN[theta] + y*COS[theta],
                *z,
            ];
            rotations.push(rotated_z);
        }
        all_rots.push(rotations);
    }

    let mut all_rotss = all_rots.clone();
    for piece in &all_rots {
        for theta in 0..4 {
            let mut rotations = Vec::new();
            for [x, y, z] in piece {
                let rotated_yz = [
                     x*COS[theta] + z*SIN[theta],
                     *y,
                    -x*SIN[theta] + z*COS[theta],
                ];
                rotations.push(rotated_yz);
            }
            all_rotss.push(rotations);
        }
    }

    let mut all_rotsss = all_rotss.clone();
    for piece in &all_rotss {
        for theta in 0..4 {
            let mut rotations = Vec::new();
            for [x, y, z] in piece {
                let rotated_xyz = [
                    *x,
                    y*COS[theta] - z*SIN[theta],
                    y*SIN[theta] + z*COS[theta],
                ];
                rotations.push(rotated_xyz);
            }
            all_rotsss.push(rotations)
        }
    }

    let mut unique_solutions = HashSet::new();
    let rots = push_to_zero(all_rotsss);
    for mut solution in rots {
        solution.sort();
        unique_solutions.insert(solution);
    }

    let mut rotations = Vec::new();
    for solution in unique_solutions {
        rotations.push(solution);
    }
    rotations
}

fn max_xyz(piece: &Piece) -> (i32, i32, i32) {
    let mut max_x = -1;
    let mut max_y = -1;
    let mut max_z = -1;

    for [x, y, z] in piece {
        if x > &max_x {
            max_x = *x;
        }
        if y > &max_y{
            max_y = *y;
        }
        if z > &max_z{
            max_z = *z;
        }
    }
    (max_x, max_y, max_z)
}

fn all_puts(already_placed: Vec<PuzzleDense>, piece_count: i32, piece: &Piece) -> Vec<PuzzleDense> {
    let mut all_solutions = Vec::new();
    let (max_x, max_y, max_z) = max_xyz(&piece);

    for x_step in 0..3 - max_x {
        for y_step in 0..3 - max_y {
            for z_step in 0..3 - max_z {
                let already_placed = already_placed.clone();
                'next_piece:
                for mut puzzle in already_placed {

                    for [x, y, z] in piece {
                        if puzzle.data[(x + x_step) as usize][(y + y_step) as usize][(z + z_step) as usize] > 0 {
                            continue 'next_piece;
                        }
                    }

                    for [x, y, z] in piece {
                        puzzle.data[(x + x_step) as usize][(y + y_step) as usize][(z + z_step) as usize] = piece_count;
                    }

                    all_solutions.push(puzzle);
                }
            }
        }
    }

    all_solutions
}

fn zeros() -> [[[i32; 3]; 3]; 3] {
    let zeros = [
        [
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
        ],
        [
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
        ],
        [
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
        ],
    ];
    zeros
}

fn push_to_zero(puzzle: Puzzle) -> Puzzle {
    let mut pieces = Vec::new();

    for i in 0..puzzle.len() {
        let mut piece = Vec::new();
        let mut min_x = 99;
        let mut min_y = 99;
        let mut min_z = 99;

        for [x, y, z] in &puzzle[i] {
            if x < &min_x {
                min_x = *x;
            }
            if y < &min_y {
                min_y = *y;
            }
            if z < &min_z {
                min_z = *z;
            }
        }
        for [x, y, z] in &puzzle[i] {
            piece.push([x - min_x, y - min_y, z - min_z]);
        }

        pieces.push(piece);
    }

    pieces
}

fn blue() -> Puzzle {
    let mut blue = Vec::new();

    blue.push(vec!(
        [2, 0, 2],
        [2, 1, 2],
        [2, 2, 2],
    ));

    let piece_2 = vec!(
        [1, 0, 2],
        [1, 1, 1],
        [1, 1, 2],
        [2, 0, 2],
    );
    for _ in 0..3 {
        blue.push(piece_2.clone());
    }

    let piece_3 = vec!(
        [1, 0, 2],
        [1, 1, 2],
        [2, 0, 1],
        [2, 0, 2],
    );
    for _ in 0..3 {
        blue.push(piece_3.clone());
    }

    blue
}
<commit_msg>Finish, but somethings wrong.<commit_after>use std::fmt;
use std::collections::HashSet;

type Piece = Vec<[i32; 3]>;
type Puzzle = Vec<Piece>;

const SIN: [i32; 4] = [0, 1, 0, -1];
const COS: [i32; 4] = [1, 0, -1, 0];

#[derive(Clone, Debug)]
struct PuzzleDense {
    data: [[[i32; 3]; 3]; 3],
}

impl fmt::Display for PuzzleDense {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "{:?}", self.data[0])?;
        writeln!(f, "{:?}", self.data[1])?;
        writeln!(f, "{:?}", self.data[2])
    }
}

fn main() {
    let puzzle = blue();
    let pieces = push_to_zero(puzzle);
    for piece in &pieces {
        for part in piece {
            println!("{:?}", part);
        }
        println!("");
    }

    let mut zero = Vec::new();
    zero.push(PuzzleDense { data: zeros() });

    let mut solutions = Vec::new();
    for (i, piece) in pieces.iter().enumerate() {
        if i == 0 {
            for s in all_puts(zero.clone(), (i + 1) as i32, &piece) {
                solutions.push(s);
            }
        } else {
            for s in all_rotations_and_puts(solutions.clone(), (i + 1) as i32, &piece) {
                solutions.drain(..);
                solutions.push(s);
            }
        }
    }

    for solution in solutions {
        println!("{:}", solution);
    }
}

fn all_rotations_and_puts(already_placed: Vec<PuzzleDense>, piece_count: i32, piece: &Piece) -> Vec<PuzzleDense> {
    let mut solutions = Vec::new();
    for rotation in all_rotations(piece) {
        for s in all_puts(already_placed.clone(), piece_count, &rotation) {
            solutions.push(s);
        }
    }
    solutions
}

fn all_rotations(piece: &Piece) -> Vec<Vec<[i32; 3]>> {
    let mut all_rots = Vec::new();
    for theta in 0..4 {
        let mut rotations = Vec::new();
        for [x, y, z] in piece {
            let rotated_z = [
                x*COS[theta] - y*SIN[theta],
                x*SIN[theta] + y*COS[theta],
                *z,
            ];
            rotations.push(rotated_z);
        }
        all_rots.push(rotations);
    }

    let mut all_rotss = all_rots.clone();
    for piece in &all_rots {
        for theta in 0..4 {
            let mut rotations = Vec::new();
            for [x, y, z] in piece {
                let rotated_yz = [
                     x*COS[theta] + z*SIN[theta],
                     *y,
                    -x*SIN[theta] + z*COS[theta],
                ];
                rotations.push(rotated_yz);
            }
            all_rotss.push(rotations);
        }
    }

    let mut all_rotsss = all_rotss.clone();
    for piece in &all_rotss {
        for theta in 0..4 {
            let mut rotations = Vec::new();
            for [x, y, z] in piece {
                let rotated_xyz = [
                    *x,
                    y*COS[theta] - z*SIN[theta],
                    y*SIN[theta] + z*COS[theta],
                ];
                rotations.push(rotated_xyz);
            }
            all_rotsss.push(rotations)
        }
    }

    let mut unique_solutions = HashSet::new();
    let rots = push_to_zero(all_rotsss);
    for mut solution in rots {
        solution.sort();
        unique_solutions.insert(solution);
    }

    let mut rotations = Vec::new();
    for solution in unique_solutions {
        rotations.push(solution);
    }
    rotations
}

fn max_xyz(piece: &Piece) -> (i32, i32, i32) {
    let mut max_x = -1;
    let mut max_y = -1;
    let mut max_z = -1;

    for [x, y, z] in piece {
        if x > &max_x {
            max_x = *x;
        }
        if y > &max_y{
            max_y = *y;
        }
        if z > &max_z{
            max_z = *z;
        }
    }
    (max_x, max_y, max_z)
}

fn all_puts(already_placed: Vec<PuzzleDense>, piece_count: i32, piece: &Piece) -> Vec<PuzzleDense> {
    let mut all_solutions = Vec::new();
    let (max_x, max_y, max_z) = max_xyz(&piece);

    for x_step in 0..3 - max_x {
        for y_step in 0..3 - max_y {
            for z_step in 0..3 - max_z {
                let already_placed = already_placed.clone();
                'next_piece:
                for mut puzzle in already_placed {

                    for [x, y, z] in piece {
                        if puzzle.data[(x + x_step) as usize][(y + y_step) as usize][(z + z_step) as usize] > 0 {
                            continue 'next_piece;
                        }
                    }

                    for [x, y, z] in piece {
                        puzzle.data[(x + x_step) as usize][(y + y_step) as usize][(z + z_step) as usize] = piece_count;
                    }

                    all_solutions.push(puzzle);
                }
            }
        }
    }

    all_solutions
}

fn zeros() -> [[[i32; 3]; 3]; 3] {
    let zeros = [
        [
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
        ],
        [
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
        ],
        [
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
        ],
    ];
    zeros
}

fn push_to_zero(puzzle: Puzzle) -> Puzzle {
    let mut pieces = Vec::new();

    for i in 0..puzzle.len() {
        let mut piece = Vec::new();
        let mut min_x = 99;
        let mut min_y = 99;
        let mut min_z = 99;

        for [x, y, z] in &puzzle[i] {
            if x < &min_x {
                min_x = *x;
            }
            if y < &min_y {
                min_y = *y;
            }
            if z < &min_z {
                min_z = *z;
            }
        }
        for [x, y, z] in &puzzle[i] {
            piece.push([x - min_x, y - min_y, z - min_z]);
        }

        pieces.push(piece);
    }

    pieces
}

fn blue() -> Puzzle {
    let mut blue = Vec::new();

    blue.push(vec!(
        [2, 0, 2],
        [2, 1, 2],
        [2, 2, 2],
    ));

    let piece_2 = vec!(
        [1, 0, 2],
        [1, 1, 1],
        [1, 1, 2],
        [2, 0, 2],
    );
    for _ in 0..3 {
        blue.push(piece_2.clone());
    }

    let piece_3 = vec!(
        [1, 0, 2],
        [1, 1, 2],
        [2, 0, 1],
        [2, 0, 2],
    );
    for _ in 0..3 {
        blue.push(piece_3.clone());
    }

    blue
}
<|endoftext|>


<commit_before>#![feature(globs)]

extern crate graphics;
extern crate piston;
// extern crate sdl2_game_window;
extern crate glfw_game_window;

// use sdl2_game_window::WindowSDL2;
use glfw_game_window::WindowGLFW;
use piston::input::keyboard;
use piston::input::{
    Keyboard,
    Mouse,
    MouseCursor,
    MouseRelative,
    MouseScroll,
    Move,
    Press,
    Release,
    Resize,
    Text,
};
use piston::{
    Input,
    Render,
    Update
};

pub struct App {
    capture_cursor: bool
}

impl App {
    /// Creates a new application.
    pub fn new() -> App {
        App {
            capture_cursor: false
        }
    }

    fn key_press<W: piston::Window>(
        &mut self,
        window: &mut W,
        key: keyboard::Key
    ) {
        if key == keyboard::C {
            println!("Turned capture cursor on");
            self.capture_cursor = !self.capture_cursor;

            window.capture_cursor(self.capture_cursor);
        }

        println!("Pressed keyboard key '{}'", key);
    }
}

fn main() {
    let mut window = WindowGLFW::new(
        piston::shader_version::opengl::OpenGL_3_2,
        piston::WindowSettings {
            title: "Keycode".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    println!("Press C to turn capture cursor on/off");

    let mut app = App::new();
    let event_settings = piston::EventSettings {
            updates_per_second: 120,
            max_frames_per_second: 60,
        };
    for e in piston::EventIterator::new(&mut window, &event_settings) {
        match e {
            Input(Press(Keyboard(key))) =>
                app.key_press(&mut window, key),
            Input(Release(Keyboard(key))) =>
                println!("Released keyboard key '{}'", key),
            Input(Press(Mouse(button))) =>
                println!("Pressed mouse button '{}'", button),
            Input(Release(Mouse(button))) =>
                println!("Released mouse button '{}'", button),
            Input(Move(MouseCursor(x, y))) =>
                println!("Mouse moved '{} {}'", x, y),
            Input(Move(MouseScroll(dx, dy))) =>
                println!("Scrolled mouse '{}, {}'", dx, dy),
            Input(Move(MouseRelative(dx, dy))) =>
                println!("Relative mouse moved '{} {}'", dx, dy),
            Input(Text(text)) => println!("Typed '{}'", text),
            Input(Resize(w, h)) => println!("Resized '{}, {}'", w, h),
            Render(_) => {},
            Update(_) => {},
        }
    }
}

<commit_msg>Handle focus event<commit_after>#![feature(globs)]

extern crate graphics;
extern crate piston;
// extern crate sdl2_game_window;
extern crate glfw_game_window;

// use sdl2_game_window::WindowSDL2;
use glfw_game_window::WindowGLFW;
use piston::input::keyboard;
use piston::input::{
    Focus,
    Keyboard,
    Mouse,
    MouseCursor,
    MouseRelative,
    MouseScroll,
    Move,
    Press,
    Release,
    Resize,
    Text,
};
use piston::{
    Input,
    Render,
    Update
};

pub struct App {
    capture_cursor: bool
}

impl App {
    /// Creates a new application.
    pub fn new() -> App {
        App {
            capture_cursor: false
        }
    }

    fn key_press<W: piston::Window>(
        &mut self,
        window: &mut W,
        key: keyboard::Key
    ) {
        if key == keyboard::C {
            println!("Turned capture cursor on");
            self.capture_cursor = !self.capture_cursor;

            window.capture_cursor(self.capture_cursor);
        }

        println!("Pressed keyboard key '{}'", key);
    }
}

fn main() {
    let mut window = WindowGLFW::new(
        piston::shader_version::opengl::OpenGL_3_2,
        piston::WindowSettings {
            title: "Keycode".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    println!("Press C to turn capture cursor on/off");

    let mut app = App::new();
    let event_settings = piston::EventSettings {
            updates_per_second: 120,
            max_frames_per_second: 60,
        };
    for e in piston::EventIterator::new(&mut window, &event_settings) {
        match e {
            Input(Press(Keyboard(key))) =>
                app.key_press(&mut window, key),
            Input(Release(Keyboard(key))) =>
                println!("Released keyboard key '{}'", key),
            Input(Press(Mouse(button))) =>
                println!("Pressed mouse button '{}'", button),
            Input(Release(Mouse(button))) =>
                println!("Released mouse button '{}'", button),
            Input(Move(MouseCursor(x, y))) =>
                println!("Mouse moved '{} {}'", x, y),
            Input(Move(MouseScroll(dx, dy))) =>
                println!("Scrolled mouse '{}, {}'", dx, dy),
            Input(Move(MouseRelative(dx, dy))) =>
                println!("Relative mouse moved '{} {}'", dx, dy),
            Input(Text(text)) => println!("Typed '{}'", text),
            Input(Resize(w, h)) => println!("Resized '{}, {}'", w, h),
            Input(Focus(true)) => println!("Gained focus"),
            Input(Focus(false)) => println!("Lost focus"),
            Render(_) => {},
            Update(_) => {},
        }
    }
}

<|endoftext|>


<commit_before>// Copyright 2016 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::collections::HashMap;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_LOG_DIR: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory_path<P: AsRef<Path>>(directory: P) -> Result<PathBuf, io::Error> {
    match dirs::data_local_dir() {
        Some(mut log_dir) => {
            log_dir.push(directory);
            Ok(log_dir)
        }
        None => Err(io::Error::new(
            io::ErrorKind::NotFound,
            "No standard logging directory known for this platform",
        )),
    }
}

fn setup_logging(logging_path_result: Option<PathBuf>) -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let mut fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    if let Some(logging_file_path) = &logging_path_result {
        // Ensure the logging directory is created
        let parent_path = logging_file_path.parent().ok_or(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!(
                "Unable to get the parent of the following Path: {}",
                logging_file_path.display(),
            ),
        ))?;
        fs::create_dir_all(parent_path)?;
        // Attach it to fern
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    };

    // Start fern
    fern_dispatch.apply()?;
    info!("Logging with fern is setup");

    // Log details of the logging_file_path result using fern/log
    // Either logging the path fern is outputting to or the error from obtaining the path
    match &logging_path_result {
        Some(logging_file_path) => info!(
            "Logging to the following file: {}",
            logging_file_path.display()
        ),
        None => warn!("There was no path supplied for the log file, falling back to stderr."),
    }
    Ok(())
}

fn generate_logging_path(logfile_config: LogfileConfig) -> Result<PathBuf, io::Error> {
    // Use the file name set in logfile_config or fallback to the default
    let logfile_file_name = match logfile_config.file {
        Some(file_name) => file_name,
        None => PathBuf::from(XI_LOG_FILE),
    };
    // Use the directory name set in logfile_config or fallback to the default
    let logfile_directory_name = match logfile_config.directory {
        Some(dir) => dir,
        None => PathBuf::from(XI_LOG_DIR),
    };

    let mut logging_directory_path = get_logging_directory_path(logfile_directory_name)?;

    // Add the file name & return the full path
    logging_directory_path.push(logfile_file_name);
    Ok(logging_directory_path)
}

fn get_flags() -> HashMap<String, Option<String>> {
    let mut flags: HashMap<String, Option<String>> = HashMap::new();

    let flag_prefix = "-";
    let mut args_itterator = std::env::args().peekable();
    while let Some(arg) = args_itterator.next() {
        if arg.starts_with(flag_prefix) {
            let key = arg.trim_left_matches(flag_prefix).to_string();

            // Check the next argument doesn't start with the flag prefix
            // map_or accounts for peek returning an Option
            let next_arg_not_a_flag: bool = args_itterator
                .peek()
                .map_or(false, |val| !val.starts_with(flag_prefix));
            if next_arg_not_a_flag {
                flags.insert(key, args_itterator.next());
            }
        }
    }
    flags
}

struct EnvFlagConfig {
    env_name: &'static str,
    flag_name: &'static str,
}

/// Extracts a value from the flags and the env.
///
/// In this order: `String` from the flags, then `String` from the env, then `None`
fn extract_env_or_flag(
    flags: &HashMap<String, Option<String>>,
    conf: EnvFlagConfig,
) -> Option<String> {
    flags
        .get(conf.flag_name)
        .cloned()
        .unwrap_or(std::env::var(conf.env_name).ok())
}

struct LogfileConfig {
    directory: Option<PathBuf>,
    file: Option<PathBuf>,
}

fn generate_logfile_config(flags: &HashMap<String, Option<String>>) -> LogfileConfig {
    // If the key is set, get the Option within
    let log_dir_env_flag = EnvFlagConfig {
        env_name: "XI_LOG_DIR",
        flag_name: "log-dir",
    };
    let log_file_env_flag = EnvFlagConfig {
        env_name: "XI_LOG_FILE",
        flag_name: "log-file",
    };
    let log_dir_flag_option = extract_env_or_flag(&flags, log_dir_env_flag).map(PathBuf::from);

    let log_file_flag_option = extract_env_or_flag(&flags, log_file_env_flag).map(PathBuf::from);

    LogfileConfig {
        directory: log_dir_flag_option,
        file: log_file_flag_option,
    }
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    let flags: HashMap<String, Option<String>> = get_flags();

    let logfile_config = generate_logfile_config(&flags);

    let logging_path_result: Result<PathBuf, io::Error> = generate_logging_path(logfile_config);

    let mut logging_path: Option<PathBuf> = None;
    let mut logging_error: Option<io::Error> = None;
    match logging_path_result {
        Ok(val) => logging_path = Some(val),
        Err(e) => logging_error = Some(e),
    };
    if let Err(e) = setup_logging(logging_path) {
        eprintln!(
            "[ERROR] setup_logging returned error, logging not enabled: {:?}",
            e
        );
    }
    if let Some(e) = logging_error {
        warn!("Unable to successfully generate the logging path: {:?}", e)
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<commit_msg>Fixed spelling mistake: itterator -> iterator<commit_after>// Copyright 2016 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::collections::HashMap;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_LOG_DIR: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory_path<P: AsRef<Path>>(directory: P) -> Result<PathBuf, io::Error> {
    match dirs::data_local_dir() {
        Some(mut log_dir) => {
            log_dir.push(directory);
            Ok(log_dir)
        }
        None => Err(io::Error::new(
            io::ErrorKind::NotFound,
            "No standard logging directory known for this platform",
        )),
    }
}

fn setup_logging(logging_path_result: Option<PathBuf>) -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let mut fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    if let Some(logging_file_path) = &logging_path_result {
        // Ensure the logging directory is created
        let parent_path = logging_file_path.parent().ok_or(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!(
                "Unable to get the parent of the following Path: {}",
                logging_file_path.display(),
            ),
        ))?;
        fs::create_dir_all(parent_path)?;
        // Attach it to fern
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    };

    // Start fern
    fern_dispatch.apply()?;
    info!("Logging with fern is setup");

    // Log details of the logging_file_path result using fern/log
    // Either logging the path fern is outputting to or the error from obtaining the path
    match &logging_path_result {
        Some(logging_file_path) => info!(
            "Logging to the following file: {}",
            logging_file_path.display()
        ),
        None => warn!("There was no path supplied for the log file, falling back to stderr."),
    }
    Ok(())
}

fn generate_logging_path(logfile_config: LogfileConfig) -> Result<PathBuf, io::Error> {
    // Use the file name set in logfile_config or fallback to the default
    let logfile_file_name = match logfile_config.file {
        Some(file_name) => file_name,
        None => PathBuf::from(XI_LOG_FILE),
    };
    // Use the directory name set in logfile_config or fallback to the default
    let logfile_directory_name = match logfile_config.directory {
        Some(dir) => dir,
        None => PathBuf::from(XI_LOG_DIR),
    };

    let mut logging_directory_path = get_logging_directory_path(logfile_directory_name)?;

    // Add the file name & return the full path
    logging_directory_path.push(logfile_file_name);
    Ok(logging_directory_path)
}

fn get_flags() -> HashMap<String, Option<String>> {
    let mut flags: HashMap<String, Option<String>> = HashMap::new();

    let flag_prefix = "-";
    let mut args_iterator = std::env::args().peekable();
    while let Some(arg) = args_iterator.next() {
        if arg.starts_with(flag_prefix) {
            let key = arg.trim_left_matches(flag_prefix).to_string();

            // Check the next argument doesn't start with the flag prefix
            // map_or accounts for peek returning an Option
            let next_arg_not_a_flag: bool = args_iterator
                .peek()
                .map_or(false, |val| !val.starts_with(flag_prefix));
            if next_arg_not_a_flag {
                flags.insert(key, args_iterator.next());
            }
        }
    }
    flags
}

struct EnvFlagConfig {
    env_name: &'static str,
    flag_name: &'static str,
}

/// Extracts a value from the flags and the env.
///
/// In this order: `String` from the flags, then `String` from the env, then `None`
fn extract_env_or_flag(
    flags: &HashMap<String, Option<String>>,
    conf: EnvFlagConfig,
) -> Option<String> {
    flags
        .get(conf.flag_name)
        .cloned()
        .unwrap_or(std::env::var(conf.env_name).ok())
}

struct LogfileConfig {
    directory: Option<PathBuf>,
    file: Option<PathBuf>,
}

fn generate_logfile_config(flags: &HashMap<String, Option<String>>) -> LogfileConfig {
    // If the key is set, get the Option within
    let log_dir_env_flag = EnvFlagConfig {
        env_name: "XI_LOG_DIR",
        flag_name: "log-dir",
    };
    let log_file_env_flag = EnvFlagConfig {
        env_name: "XI_LOG_FILE",
        flag_name: "log-file",
    };
    let log_dir_flag_option = extract_env_or_flag(&flags, log_dir_env_flag).map(PathBuf::from);

    let log_file_flag_option = extract_env_or_flag(&flags, log_file_env_flag).map(PathBuf::from);

    LogfileConfig {
        directory: log_dir_flag_option,
        file: log_file_flag_option,
    }
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    let flags: HashMap<String, Option<String>> = get_flags();

    let logfile_config = generate_logfile_config(&flags);

    let logging_path_result: Result<PathBuf, io::Error> = generate_logging_path(logfile_config);

    let mut logging_path: Option<PathBuf> = None;
    let mut logging_error: Option<io::Error> = None;
    match logging_path_result {
        Ok(val) => logging_path = Some(val),
        Err(e) => logging_error = Some(e),
    };
    if let Err(e) = setup_logging(logging_path) {
        eprintln!(
            "[ERROR] setup_logging returned error, logging not enabled: {:?}",
            e
        );
    }
    if let Some(e) = logging_error {
        warn!("Unable to successfully generate the logging path: {:?}", e)
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<|endoftext|>


<commit_before>use libc;
use cssparser;
use glib::translate::*;

use std::cell::Cell;

use color::*;
use drawing_ctx;
use drawing_ctx::*;
use error::*;
use handle::RsvgHandle;
use length::*;
use node::*;
use opacity::*;
use property_bag::{self, PropertyBag};
use state::RsvgState;

pub struct NodeStop {
    offset: Cell<f64>,
    rgba: Cell<u32>
}

impl NodeStop {
    fn new () -> NodeStop {
        NodeStop {
            offset: Cell::new (0.0),
            rgba: Cell::new (0)
        }
    }

    pub fn get_offset (&self) -> f64 {
        self.offset.get ()
    }

    pub fn get_rgba (&self) -> u32 {
        self.rgba.get ()
    }
}

fn validate_offset(length: RsvgLength) -> Result<RsvgLength, AttributeError> {
    match length.unit {
        LengthUnit::Default |
        LengthUnit::Percent => {
            let mut offset = length.length;

            if offset < 0.0 {
                offset = 0.0;
            } else if offset > 1.0 {
                offset = 1.0;
            }

            Ok(RsvgLength::new(offset, LengthUnit::Default, LengthDir::Both))
        },

        _ => {
            Err (AttributeError::Value ("stop offset must be in default or percent units".to_string()))
        }
    }
}

impl NodeTrait for NodeStop {
    fn set_atts (&self, node: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        let length = property_bag::parse_or_default (pbag, "offset", LengthDir::Both,
                                                     Some(validate_offset))?;
        assert! (length.unit == LengthUnit::Default || length.unit == LengthUnit::Percent);
        self.offset.set (length.length);

        let state = node.get_state ();

        // FIXME: this is the only place where rsvg_parse_style() and
        // rsvg_parse_presentation_attributes() are called outside of the
        // rsvg-base.c machinery.  That one indirectly calls them via
        // rsvg_parse_style_attrs().
        //
        // Should we resolve the stop-color / stop-opacity at
        // rendering time?

        if let Some (v) = pbag.lookup("style") {
            unsafe {
                rsvg_parse_style (state, v.to_glib_none ().0);
            }
        }

        unsafe {
            rsvg_parse_presentation_attributes (state, pbag.ffi());
        }

        let inherited_state = drawing_ctx::state_new ();
        let boxed_node = box_node (node.clone ());
        drawing_ctx::state_reconstruct (inherited_state, boxed_node);
        rsvg_node_unref (boxed_node);

        let mut color_rgba: cssparser::RGBA;

        let stop_color = drawing_ctx::state_get_stop_color (state)
            .map_err (|e| NodeError::attribute_error ("stop-color", e))?;

        match stop_color {
            None => color_rgba = cssparser::RGBA::transparent (),

            Some (Color::Inherit) => {
                let inherited_stop_color = drawing_ctx::state_get_stop_color (inherited_state)
                    .map_err (|e| NodeError::attribute_error ("stop-color", e))?;

                match inherited_stop_color {
                    None => unreachable! (),

                    Some (Color::Inherit) => color_rgba = cssparser::RGBA::transparent (),
                    Some (Color::CurrentColor) => {
                        let color = drawing_ctx::state_get_current_color (inherited_state);
                        match color {
                            Color::RGBA (rgba) => color_rgba = rgba,
                            _ => unreachable! ()
                        }
                    },

                    Some (Color::RGBA (rgba)) => color_rgba = rgba
                }
            },

            Some (Color::CurrentColor) => {
                let color = drawing_ctx::state_get_current_color (inherited_state);
                match color {
                    Color::RGBA (rgba) => color_rgba = rgba,
                    _ => unreachable! ()
                }
            }

            Some (Color::RGBA (rgba)) => color_rgba = rgba
        }

        let stop_opacity = drawing_ctx::state_get_stop_opacity (state)
            .map_err (|e| NodeError::attribute_error ("stop-opacity", e))?;

        match stop_opacity {
            None => color_rgba.alpha = 0xff,

            Some (Opacity::Inherit) => {
                let inherited_opacity = drawing_ctx::state_get_stop_opacity (inherited_state)
                    .map_err (|e| NodeError::attribute_error ("stop-opacity", e))?;

                match inherited_opacity {
                    Some (Opacity::Specified (opacity)) => color_rgba.alpha = opacity_to_u8 (opacity),
                    _ => color_rgba.alpha = 0xff
                }
            },

            Some (Opacity::Specified (opacity)) => color_rgba.alpha = opacity_to_u8 (opacity)
        }

        self.rgba.set (u32_from_rgba (color_rgba));

        drawing_ctx::state_free (inherited_state);

        Ok (())
    }

    fn draw (&self, _: &RsvgNode, _: *const RsvgDrawingCtx, _: i32) {
        // nothing; paint servers are handled specially
    }

    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
        unreachable! ();
    }
}

fn u32_from_rgba (rgba: cssparser::RGBA) -> u32 {
    (u32::from(rgba.red) << 24) |
    (u32::from(rgba.green) << 16) |
    (u32::from(rgba.blue) << 8) |
    u32::from(rgba.alpha)
}

extern "C" {
    fn rsvg_parse_presentation_attributes (state: *mut RsvgState, pbag: *const PropertyBag);
    fn rsvg_parse_style (state: *mut RsvgState, string: *const libc::c_char);
}

#[no_mangle]
pub extern fn rsvg_node_stop_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
    boxed_node_new (NodeType::Stop,
                    raw_parent,
                    Box::new (NodeStop::new ()))
}
<commit_msg>NodeStop: parse attributes with the PHF<commit_after>use libc;
use cssparser;
use glib::translate::*;

use std::cell::Cell;
use std::str::FromStr;

use attributes::Attribute;
use color::*;
use drawing_ctx;
use drawing_ctx::*;
use error::*;
use handle::RsvgHandle;
use length::*;
use node::*;
use opacity::*;
use parsers::parse;
use property_bag::PropertyBag;
use state::RsvgState;

pub struct NodeStop {
    offset: Cell<f64>,
    rgba: Cell<u32>
}

impl NodeStop {
    fn new () -> NodeStop {
        NodeStop {
            offset: Cell::new (0.0),
            rgba: Cell::new (0)
        }
    }

    pub fn get_offset (&self) -> f64 {
        self.offset.get ()
    }

    pub fn get_rgba (&self) -> u32 {
        self.rgba.get ()
    }
}

fn validate_offset(length: RsvgLength) -> Result<RsvgLength, AttributeError> {
    match length.unit {
        LengthUnit::Default |
        LengthUnit::Percent => {
            let mut offset = length.length;

            if offset < 0.0 {
                offset = 0.0;
            } else if offset > 1.0 {
                offset = 1.0;
            }

            Ok(RsvgLength::new(offset, LengthUnit::Default, LengthDir::Both))
        },

        _ => {
            Err (AttributeError::Value ("stop offset must be in default or percent units".to_string()))
        }
    }
}

impl NodeTrait for NodeStop {
    fn set_atts (&self, node: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        let state = node.get_state ();

        for (key, value) in pbag.iter() {
            if let Ok(attr) = Attribute::from_str(key) {
                match attr {
                    Attribute::Offset => {
                        let length = parse("offset", value, LengthDir::Both, Some(validate_offset))?;
                        assert! (length.unit == LengthUnit::Default || length.unit == LengthUnit::Percent);
                        self.offset.set (length.length);
                    },

                    Attribute::Style => {
                        // FIXME: this is the only place where rsvg_parse_style() and
                        // rsvg_parse_presentation_attributes() are called outside of the
                        // rsvg-base.c machinery.  That one indirectly calls them via
                        // rsvg_parse_style_attrs().
                        //
                        // Should we resolve the stop-color / stop-opacity at
                        // rendering time?

                        unsafe {
                            rsvg_parse_style (state, value.to_glib_none ().0);
                        }
                    },

                    _ => (),
                }
            }
        }

        unsafe {
            rsvg_parse_presentation_attributes (state, pbag.ffi());
        }

        let inherited_state = drawing_ctx::state_new ();
        let boxed_node = box_node (node.clone ());
        drawing_ctx::state_reconstruct (inherited_state, boxed_node);
        rsvg_node_unref (boxed_node);

        let mut color_rgba: cssparser::RGBA;

        let stop_color = drawing_ctx::state_get_stop_color (state)
            .map_err (|e| NodeError::attribute_error ("stop-color", e))?;

        match stop_color {
            None => color_rgba = cssparser::RGBA::transparent (),

            Some (Color::Inherit) => {
                let inherited_stop_color = drawing_ctx::state_get_stop_color (inherited_state)
                    .map_err (|e| NodeError::attribute_error ("stop-color", e))?;

                match inherited_stop_color {
                    None => unreachable! (),

                    Some (Color::Inherit) => color_rgba = cssparser::RGBA::transparent (),
                    Some (Color::CurrentColor) => {
                        let color = drawing_ctx::state_get_current_color (inherited_state);
                        match color {
                            Color::RGBA (rgba) => color_rgba = rgba,
                            _ => unreachable! ()
                        }
                    },

                    Some (Color::RGBA (rgba)) => color_rgba = rgba
                }
            },

            Some (Color::CurrentColor) => {
                let color = drawing_ctx::state_get_current_color (inherited_state);
                match color {
                    Color::RGBA (rgba) => color_rgba = rgba,
                    _ => unreachable! ()
                }
            }

            Some (Color::RGBA (rgba)) => color_rgba = rgba
        }

        let stop_opacity = drawing_ctx::state_get_stop_opacity (state)
            .map_err (|e| NodeError::attribute_error ("stop-opacity", e))?;

        match stop_opacity {
            None => color_rgba.alpha = 0xff,

            Some (Opacity::Inherit) => {
                let inherited_opacity = drawing_ctx::state_get_stop_opacity (inherited_state)
                    .map_err (|e| NodeError::attribute_error ("stop-opacity", e))?;

                match inherited_opacity {
                    Some (Opacity::Specified (opacity)) => color_rgba.alpha = opacity_to_u8 (opacity),
                    _ => color_rgba.alpha = 0xff
                }
            },

            Some (Opacity::Specified (opacity)) => color_rgba.alpha = opacity_to_u8 (opacity)
        }

        self.rgba.set (u32_from_rgba (color_rgba));

        drawing_ctx::state_free (inherited_state);

        Ok (())
    }

    fn draw (&self, _: &RsvgNode, _: *const RsvgDrawingCtx, _: i32) {
        // nothing; paint servers are handled specially
    }

    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
        unreachable! ();
    }
}

fn u32_from_rgba (rgba: cssparser::RGBA) -> u32 {
    (u32::from(rgba.red) << 24) |
    (u32::from(rgba.green) << 16) |
    (u32::from(rgba.blue) << 8) |
    u32::from(rgba.alpha)
}

extern "C" {
    fn rsvg_parse_presentation_attributes (state: *mut RsvgState, pbag: *const PropertyBag);
    fn rsvg_parse_style (state: *mut RsvgState, string: *const libc::c_char);
}

#[no_mangle]
pub extern fn rsvg_node_stop_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
    boxed_node_new (NodeType::Stop,
                    raw_parent,
                    Box::new (NodeStop::new ()))
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use futures::stream::Stream;
use std::task::Poll;

use crate::solicit::DEFAULT_SETTINGS;

use super::stream_queue_sync::StreamQueueSyncReceiver;
use super::types::Types;
use crate::common::increase_in_window::IncreaseInWindow;
use crate::data_or_headers::DataOrHeaders;
use crate::data_or_headers_with_flag::DataOrHeadersWithFlag;
use futures::task::Context;
use std::pin::Pin;

/// Stream that provides data from network.
/// Most importantly, it increases WINDOW.
pub(crate) struct StreamFromNetwork<T: Types> {
    pub rx: StreamQueueSyncReceiver<T>,
    pub increase_in_window: IncreaseInWindow<T>,
}

impl<T: Types> Stream for StreamFromNetwork<T> {
    type Item = crate::Result<DataOrHeadersWithFlag>;

    fn poll_next(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<crate::Result<DataOrHeadersWithFlag>>> {
        let part = match Pin::new(&mut self.rx).poll_next(cx) {
            Poll::Pending => return Poll::Pending,
            Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(e))),
            Poll::Ready(None) => return Poll::Ready(None),
            Poll::Ready(Some(Ok(part))) => part,
        };

        if let DataOrHeadersWithFlag {
            content: DataOrHeaders::Data(ref b),
            ..
        } = part
        {
            self.increase_in_window.data_frame_processed(b.len() as u32);

            // TODO: use different
            // TODO: increment after process of the frame (i. e. on next poll)
            let edge = DEFAULT_SETTINGS.initial_window_size / 2;
            if self.increase_in_window.in_window_size() < edge {
                let inc = DEFAULT_SETTINGS.initial_window_size;
                self.increase_in_window.increase_window(inc)?;
            }
        }

        Poll::Ready(Some(Ok(part)))
    }
}

impl<T: Types> Drop for StreamFromNetwork<T> {
    fn drop(&mut self) {
        // TODO: reset stream
    }
}
<commit_msg>Assert no integer overflow<commit_after>#![allow(dead_code)]

use futures::stream::Stream;
use std::task::Poll;

use crate::solicit::DEFAULT_SETTINGS;

use super::stream_queue_sync::StreamQueueSyncReceiver;
use super::types::Types;
use crate::common::increase_in_window::IncreaseInWindow;
use crate::data_or_headers::DataOrHeaders;
use crate::data_or_headers_with_flag::DataOrHeadersWithFlag;
use futures::task::Context;
use std::convert::TryFrom;
use std::pin::Pin;

/// Stream that provides data from network.
/// Most importantly, it increases WINDOW.
pub(crate) struct StreamFromNetwork<T: Types> {
    pub rx: StreamQueueSyncReceiver<T>,
    pub increase_in_window: IncreaseInWindow<T>,
}

impl<T: Types> Stream for StreamFromNetwork<T> {
    type Item = crate::Result<DataOrHeadersWithFlag>;

    fn poll_next(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<crate::Result<DataOrHeadersWithFlag>>> {
        let part = match Pin::new(&mut self.rx).poll_next(cx) {
            Poll::Pending => return Poll::Pending,
            Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(e))),
            Poll::Ready(None) => return Poll::Ready(None),
            Poll::Ready(Some(Ok(part))) => part,
        };

        if let DataOrHeadersWithFlag {
            content: DataOrHeaders::Data(ref b),
            ..
        } = part
        {
            self.increase_in_window
                .data_frame_processed(u32::try_from(b.len()).unwrap());

            // TODO: use different
            // TODO: increment after process of the frame (i. e. on next poll)
            let edge = DEFAULT_SETTINGS.initial_window_size / 2;
            if self.increase_in_window.in_window_size() < edge {
                let inc = DEFAULT_SETTINGS.initial_window_size;
                self.increase_in_window.increase_window(inc)?;
            }
        }

        Poll::Ready(Some(Ok(part)))
    }
}

impl<T: Types> Drop for StreamFromNetwork<T> {
    fn drop(&mut self) {
        // TODO: reset stream
    }
}
<|endoftext|>


<commit_before>use std::{env, fs};
use std::path::PathBuf;

fn is_same_location(a: &PathBuf, b: &PathBuf) -> bool {
    fs::canonicalize(a).unwrap() == fs::canonicalize(b).unwrap()
}

fn should_install(source: &PathBuf, target: &PathBuf) -> bool {
    !target.exists() || !is_same_location(source, target)
}

pub fn self_setup(nmk_dir: &PathBuf) {
    let current_exec = env::current_exe().expect("current_exe() failed");
    let target_bin = nmk_dir.join("bin").join("nmkup");
    if should_install(&current_exec, &target_bin) {
        fs::copy(current_exec, target_bin).expect("install nmkup failed");
        info!("Installed nmkup");
    }
}

pub fn find_nmkdir() -> PathBuf {
    const NMK_DIR: &str = "NMK_DIR";
    match std::env::var_os(NMK_DIR) {
        Some(nmk_dir) => nmk_dir.into(),
        None => {
            let nmk_dir = dirs::home_dir().expect("Can't find home directory");
            info!("Using default {}: {:?}", NMK_DIR, &nmk_dir);
            nmk_dir
        }
    }
}<commit_msg>Fix wrong default NMK_DIR<commit_after>use std::{env, fs};
use std::path::PathBuf;

fn is_same_location(a: &PathBuf, b: &PathBuf) -> bool {
    fs::canonicalize(a).unwrap() == fs::canonicalize(b).unwrap()
}

fn should_install(source: &PathBuf, target: &PathBuf) -> bool {
    !target.exists() || !is_same_location(source, target)
}

pub fn self_setup(nmk_dir: &PathBuf) {
    let current_exec = env::current_exe().expect("current_exe() failed");
    let target_bin = nmk_dir.join("bin").join("nmkup");
    if should_install(&current_exec, &target_bin) {
        fs::copy(current_exec, target_bin).expect("install nmkup failed");
        info!("Installed nmkup");
    }
}

pub fn find_nmkdir() -> PathBuf {
    const NMK_DIR: &str = "NMK_DIR";
    match std::env::var_os(NMK_DIR) {
        Some(nmk_dir) => nmk_dir.into(),
        None => {
            let nmk_dir = dirs::home_dir().expect("Can't find home directory").join(".nmk");
            info!("Using default {}: {:?}", NMK_DIR, &nmk_dir);
            nmk_dir
        }
    }
}<|endoftext|>


<commit_before>use std::{self, fmt};
use std::borrow::Cow;
use std::collections::HashMap;

use serde_json::{Value, to_value};
use serde::ser::Serialize;

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct ValidationError {
  pub code: Cow<'static, str>,
  pub message: Option<Cow<'static, str>>,
  pub params: HashMap<Cow<'static, str>, Value>,
}

impl ValidationError {
    pub fn new(code: &'static str) -> ValidationError {
        ValidationError {
            code: Cow::from(code),
            message: None,
            params: HashMap::new(),
        }
    }

    pub fn add_param<T: Serialize>(&mut self, name: Cow<'static, str>, val: &T) {
        self.params.insert(name, to_value(val).unwrap());
    }
}

impl fmt::Display for ValidationError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Validation error: {} [{:?}]", self.code, self.params)
    }
}

impl std::error::Error for ValidationError {
  fn description(&self) -> &str { &self.code }
  fn cause(&self) -> Option<&std::error::Error> { None }
}

#[derive(Debug, Serialize, Clone, PartialEq)]
pub struct ValidationErrors(HashMap<&'static str, Vec<ValidationError>>);

impl ValidationErrors {
    pub fn new() -> ValidationErrors {
        ValidationErrors(HashMap::new())
    }

    pub fn inner(self) -> HashMap<&'static str, Vec<ValidationError>> {
        self.0
    }

    pub fn add(&mut self, field: &'static str, error: ValidationError) {
        self.0.entry(field).or_insert_with(|| vec![]).push(error);
    }

    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }
}
<commit_msg>[#29] Implement Error and Display for ValidationErrors<commit_after>use std::{self, fmt};
use std::borrow::Cow;
use std::collections::HashMap;

use serde_json::{Value, to_value};
use serde::ser::Serialize;

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct ValidationError {
  pub code: Cow<'static, str>,
  pub message: Option<Cow<'static, str>>,
  pub params: HashMap<Cow<'static, str>, Value>,
}

impl ValidationError {
    pub fn new(code: &'static str) -> ValidationError {
        ValidationError {
            code: Cow::from(code),
            message: None,
            params: HashMap::new(),
        }
    }

    pub fn add_param<T: Serialize>(&mut self, name: Cow<'static, str>, val: &T) {
        self.params.insert(name, to_value(val).unwrap());
    }
}

impl fmt::Display for ValidationError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Validation error: {} [{:?}]", self.code, self.params)
    }
}

impl std::error::Error for ValidationError {
  fn description(&self) -> &str { &self.code }
  fn cause(&self) -> Option<&std::error::Error> { None }
}

#[derive(Debug, Serialize, Clone, PartialEq)]
pub struct ValidationErrors(HashMap<&'static str, Vec<ValidationError>>);

impl ValidationErrors {
    pub fn new() -> ValidationErrors {
        ValidationErrors(HashMap::new())
    }

    pub fn inner(self) -> HashMap<&'static str, Vec<ValidationError>> {
        self.0
    }

    pub fn add(&mut self, field: &'static str, error: ValidationError) {
        self.0.entry(field).or_insert_with(|| vec![]).push(error);
    }

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

impl std::error::Error for ValidationErrors {
    fn description(&self) -> &str { "Validation failed" }
    fn cause(&self) -> Option<&std::error::Error> { None }
}

impl fmt::Display for ValidationErrors {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self, fmt)
    }
}
<|endoftext|>