<commit_before>use std::mem;
use std::os::unix::io::RawFd;
use std::option::Option;
use libc::{self, c_int, c_void, pid_t};
use {Errno, Error, Result};

// For some functions taking with a parameter of type CloneFlags,
// only a subset of these flags have an effect.
libc_bitflags!{
    flags CloneFlags: libc::c_int {
        CLONE_VM,
        CLONE_FS,
        CLONE_FILES,
        CLONE_SIGHAND,
        CLONE_PTRACE,
        CLONE_VFORK,
        CLONE_PARENT,
        CLONE_THREAD,
        CLONE_NEWNS,
        CLONE_SYSVSEM,
        CLONE_SETTLS,
        CLONE_PARENT_SETTID,
        CLONE_CHILD_CLEARTID,
        CLONE_DETACHED,
        CLONE_UNTRACED,
        CLONE_CHILD_SETTID,
        CLONE_NEWUTS,
        CLONE_NEWIPC,
        CLONE_NEWUSER,
        CLONE_NEWPID,
        CLONE_NEWNET,
        CLONE_IO,
    }
}

pub type CloneCb<'a> = Box<FnMut() -> isize + 'a>;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct CpuSet {
    cpu_set: libc::cpu_set_t,
}

impl CpuSet {
    pub fn new() -> CpuSet {
        CpuSet { cpu_set: unsafe { mem::zeroed() } }
    }

    pub fn is_set(&self, field: usize) -> Result<bool> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) })
        }
    }

    pub fn set(&mut self, field: usize) -> Result<()> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) })
        }
    }

    pub fn unset(&mut self, field: usize) -> Result<()> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) })
        }
    }
}

mod ffi {
    use libc::{c_void, c_int};

    pub type CloneCb = extern "C" fn(data: *const super::CloneCb) -> c_int;

    // We cannot give a proper #[repr(C)] to super::CloneCb
    #[allow(improper_ctypes)]
    extern "C" {
        // create a child process
        // doc: http://man7.org/linux/man-pages/man2/clone.2.html
        pub fn clone(cb: *const CloneCb,
                     child_stack: *mut c_void,
                     flags: c_int,
                     arg: *mut super::CloneCb,
                     ...)
                     -> c_int;
    }
}

pub fn sched_setaffinity(pid: isize, cpuset: &CpuSet) -> Result<()> {
    let res = unsafe {
        libc::sched_setaffinity(pid as libc::pid_t,
                                mem::size_of::<CpuSet>() as libc::size_t,
                                mem::transmute(cpuset))
    };

    Errno::result(res).map(drop)
}

pub fn clone(mut cb: CloneCb,
             stack: &mut [u8],
             flags: CloneFlags,
             signal: Option<c_int>)
             -> Result<pid_t> {
    extern "C" fn callback(data: *mut CloneCb) -> c_int {
        let cb: &mut CloneCb = unsafe { &mut *data };
        (*cb)() as c_int
    }

    let res = unsafe {
        let combined = flags.bits() | signal.unwrap_or(0);
        let ptr = stack.as_mut_ptr().offset(stack.len() as isize);
        ffi::clone(mem::transmute(callback as extern "C" fn(*mut Box<::std::ops::FnMut() -> isize>) -> i32),
                   ptr as *mut c_void,
                   combined,
                   &mut cb)
    };

    Errno::result(res)
}

pub fn unshare(flags: CloneFlags) -> Result<()> {
    let res = unsafe { libc::unshare(flags.bits()) };

    Errno::result(res).map(drop)
}

pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
    let res = unsafe { libc::setns(fd, nstype.bits()) };

    Errno::result(res).map(drop)
}
<commit_msg>Auto merge of #457 - dgreid:clone_newcgroup, r=posborne<commit_after>use std::mem;
use std::os::unix::io::RawFd;
use std::option::Option;
use libc::{self, c_int, c_void, pid_t};
use {Errno, Error, Result};

// For some functions taking with a parameter of type CloneFlags,
// only a subset of these flags have an effect.
libc_bitflags!{
    flags CloneFlags: libc::c_int {
        CLONE_VM,
        CLONE_FS,
        CLONE_FILES,
        CLONE_SIGHAND,
        CLONE_PTRACE,
        CLONE_VFORK,
        CLONE_PARENT,
        CLONE_THREAD,
        CLONE_NEWNS,
        CLONE_SYSVSEM,
        CLONE_SETTLS,
        CLONE_PARENT_SETTID,
        CLONE_CHILD_CLEARTID,
        CLONE_DETACHED,
        CLONE_UNTRACED,
        CLONE_CHILD_SETTID,
        CLONE_NEWCGROUP,
        CLONE_NEWUTS,
        CLONE_NEWIPC,
        CLONE_NEWUSER,
        CLONE_NEWPID,
        CLONE_NEWNET,
        CLONE_IO,
    }
}

pub type CloneCb<'a> = Box<FnMut() -> isize + 'a>;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct CpuSet {
    cpu_set: libc::cpu_set_t,
}

impl CpuSet {
    pub fn new() -> CpuSet {
        CpuSet { cpu_set: unsafe { mem::zeroed() } }
    }

    pub fn is_set(&self, field: usize) -> Result<bool> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) })
        }
    }

    pub fn set(&mut self, field: usize) -> Result<()> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) })
        }
    }

    pub fn unset(&mut self, field: usize) -> Result<()> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) })
        }
    }
}

mod ffi {
    use libc::{c_void, c_int};

    pub type CloneCb = extern "C" fn(data: *const super::CloneCb) -> c_int;

    // We cannot give a proper #[repr(C)] to super::CloneCb
    #[allow(improper_ctypes)]
    extern "C" {
        // create a child process
        // doc: http://man7.org/linux/man-pages/man2/clone.2.html
        pub fn clone(cb: *const CloneCb,
                     child_stack: *mut c_void,
                     flags: c_int,
                     arg: *mut super::CloneCb,
                     ...)
                     -> c_int;
    }
}

pub fn sched_setaffinity(pid: isize, cpuset: &CpuSet) -> Result<()> {
    let res = unsafe {
        libc::sched_setaffinity(pid as libc::pid_t,
                                mem::size_of::<CpuSet>() as libc::size_t,
                                mem::transmute(cpuset))
    };

    Errno::result(res).map(drop)
}

pub fn clone(mut cb: CloneCb,
             stack: &mut [u8],
             flags: CloneFlags,
             signal: Option<c_int>)
             -> Result<pid_t> {
    extern "C" fn callback(data: *mut CloneCb) -> c_int {
        let cb: &mut CloneCb = unsafe { &mut *data };
        (*cb)() as c_int
    }

    let res = unsafe {
        let combined = flags.bits() | signal.unwrap_or(0);
        let ptr = stack.as_mut_ptr().offset(stack.len() as isize);
        ffi::clone(mem::transmute(callback as extern "C" fn(*mut Box<::std::ops::FnMut() -> isize>) -> i32),
                   ptr as *mut c_void,
                   combined,
                   &mut cb)
    };

    Errno::result(res)
}

pub fn unshare(flags: CloneFlags) -> Result<()> {
    let res = unsafe { libc::unshare(flags.bits()) };

    Errno::result(res).map(drop)
}

pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
    let res = unsafe { libc::setns(fd, nstype.bits()) };

    Errno::result(res).map(drop)
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused)]

use lift::{Higher, SemiGroup, Monoid, Functor, Monad};
use functor::*;
use monoid::*;
use semigroup::*;
use monad::*;
<commit_msg>added examples<commit_after>#![allow(dead_code, unused)]

use lift::{Higher, SemiGroup, Monoid, Functor, Monad};
use functor::*;
use monoid::*;
use semigroup::*;
use monad::*;
use applicative::*;
<|endoftext|>


<commit_before>use serde::{Deserialize, Deserializer, Serialize, Serializer};

use crate::LanguageTag;

impl Serialize for LanguageTag {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(self.as_str())
    }
}

impl<'de> Deserialize<'de> for LanguageTag {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let input: &str = Deserialize::deserialize(deserializer)?;
        LanguageTag::parse(input).map_err(serde::de::Error::custom)
    }
}

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

    #[test]
    fn basic() {
        let input = "\"en-Latn-gb-boont-r-extended-sequence-x-private\"";
        let deser: LanguageTag = serde_json::from_str(input).unwrap();
        deser.validate().unwrap();
        let ser = serde_json::to_string(&deser).unwrap();
        assert!(ser.eq_ignore_ascii_case(input));
    }
}
<commit_msg>prevent serde deserialization error, raised when using with reader: "invalid type: string, expected a borrowed string"<commit_after>use crate::LanguageTag;
use serde::de::{Error, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;

impl Serialize for LanguageTag {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(self.as_str())
    }
}

struct LanguageTagVisitor;

impl<'de> Visitor<'de> for LanguageTagVisitor {
    type Value = LanguageTag;

    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a language tag string")
    }

    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        value.parse::<Self::Value>().map_err(Error::custom)
    }
}

impl<'de> Deserialize<'de> for LanguageTag {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(LanguageTagVisitor {})
    }
}

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

    #[test]
    fn basic() {
        let input = "\"en-Latn-gb-boont-r-extended-sequence-x-private\"";
        let deser: LanguageTag = serde_json::from_str(input).unwrap();
        deser.validate().unwrap();
        let ser = serde_json::to_string(&deser).unwrap();
        assert!(ser.eq_ignore_ascii_case(input));
    }

    #[test]
    fn reader_works() {
        let input = "\"en-Latn-gb-boont-r-extended-sequence-x-private\"";
        let rdr = Cursor::new(input);
        let _: LanguageTag = serde_json::from_reader(rdr).unwrap();
    }
}
<|endoftext|>


<commit_before>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

fn find_by<T, F>(list: &[T], start: Option<usize>, mut predicate: F) -> Option<usize>
where F: FnMut(&T) -> bool {
    let start = start.unwrap_or(0);
    for (offset, element) in list.iter().enumerate() {
        if predicate(element) { return Some(start + offset); }
    }

    return None;
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(index), ProgramStatus::Seeking(goal)) if index < self.instructions.len() => {

            }

            (Some(start), ProgramStatus::Normal) if start < self.instructions.len() => {
                for index in start..self.instructions.len() {
                }
            }

            _ => {}
        }
    }
}
<commit_msg>Add ProgramPatch struct<commit_after>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

#[derive(Clone, Copy, Debug)]
pub struct ProgramPatch {
    pub instruction_pointer: usize,
    pub current_depth: u64,
    pub status: ProgramStatus,
}

fn find_by<T, F>(list: &[T], start: Option<usize>, mut predicate: F) -> Option<usize>
where F: FnMut(&T) -> bool {
    let start = start.unwrap_or(0);
    for (offset, element) in list.iter().enumerate() {
        if predicate(element) { return Some(start + offset); }
    }

    return None;
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(index), ProgramStatus::Seeking(goal)) if index < self.instructions.len() => {

            }

            (Some(start), ProgramStatus::Normal) if start < self.instructions.len() => {
                for index in start..self.instructions.len() {
                }
            }

            _ => {}
        }
    }
}
<|endoftext|>


<commit_before>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(mut index), ProgramStatus::Normal) => {
                while index < self.instructions.len() {
                    match self.instructions[index] {
                        Command::JumpForward => self.handle_jump_forward(vm, &mut index),
                        Command::JumpBackward => index = self.handle_jump_backward(&vm, index),
                        command => {
                            vm.apply(command);
                            index += 1;
                        }
                    }
                }
                self.instruction_pointer = Some(index);
            }

            (Some(mut index), ProgramStatus::Seeking(_)) => {
                self.handle_jump_forward(vm, &mut index);
                self.execute(vm);
            }

            _ => {}
        }
    }

    fn handle_jump_backward(&mut self, vm: &VM, starting_index: usize) -> usize {
        match vm.cells[vm.data_pointer] {
            0 => {
                self.current_depth -= 1;
                return starting_index + 1;
            }
            _ => {
                let goal_depth = self.current_depth;
                for index in (0..starting_index).rev() {
                    match self.instructions[index] {
                        Command::JumpBackward => self.current_depth += 1,
                        Command::JumpForward => {
                            if self.current_depth == goal_depth {
                                return index + 1;
                            }
                            self.current_depth -= 1;
                        }
                        _ => {}
                    }
                }
                panic!("No starting brace found!");
            }
        }
    }

    fn seek_forward(&mut self, index_ref: &mut usize) {
        if let ProgramStatus::Seeking(goal_depth) = self.status {
            for index in (*index_ref)..self.instructions.len() {
                match self.instructions[index] {
                    Command::JumpForward => self.current_depth += 1,
                    Command::JumpBackward => self.current_depth -= 1,
                    _ => {}
                }
                if self.current_depth == goal_depth {
                    *index_ref = index + 1;
                    self.status = ProgramStatus::Normal;
                    return;
                }
            }

            *index_ref = self.instructions.len();
            self.status = ProgramStatus::Seeking(goal_depth);
        }
    }

    fn handle_jump_forward(&mut self, vm: &VM, index: &mut usize) {
        match (vm.cells[vm.data_pointer], self.status) {
            (0, ProgramStatus::Normal) => {
                self.status = ProgramStatus::Seeking(self.current_depth);
                self.seek_forward(index);
            }

            (_, ProgramStatus::Normal) => {
                *index += 1;
                self.current_depth += 1;
                self.status = ProgramStatus::Normal;
            }

            (_, ProgramStatus::Seeking(_)) => self.seek_forward(index),

        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    pub fn test_seek_forward_normal() {
        let mut program = Program {
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Seeking(0),
            instructions: vec![
                Command::JumpForward,
                Command::JumpForward,
                Command::JumpBackward,
                Command::JumpBackward,
            ],
        };
        let mut index = 0;
        program.seek_forward(&mut index);
        assert_eq!(index, 4);
        assert_eq!(program.status, ProgramStatus::Normal);
    }

    #[test]
    pub fn test_seek_forward_seeking() {
        let mut index = 0;
        let mut program = Program {
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Seeking(0),
            instructions: vec![
                Command::JumpForward,
                Command::JumpForward,
                Command::JumpBackward,
            ],
        };
        program.seek_forward(&mut index);
        assert_eq!(index, 3);
        assert_eq!(program.status, ProgramStatus::Seeking(0));
    }
}
<commit_msg>Change handle_jump_backward to utilize &mut index params<commit_after>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(mut index), ProgramStatus::Normal) => {
                while index < self.instructions.len() {
                    match self.instructions[index] {
                        Command::JumpForward => self.handle_jump_forward(vm, &mut index),
                        Command::JumpBackward => self.handle_jump_backward(vm, &mut index),
                        command => {
                            vm.apply(command);
                            index += 1;
                        }
                    }
                }
                self.instruction_pointer = Some(index);
            }

            (Some(mut index), ProgramStatus::Seeking(_)) => {
                self.handle_jump_forward(vm, &mut index);
                self.execute(vm);
            }

            _ => {}
        }
    }

    fn handle_jump_backward(&mut self, vm: &VM, index_ref: &mut usize) {
        match vm.cells[vm.data_pointer] {
            0 => {
                self.current_depth -= 1;
                *index_ref += 1;
            }

            _ => {
                let goal_depth = self.current_depth;
                for index in (0..*index_ref).rev() {
                    match self.instructions[index] {
                        Command::JumpBackward => self.current_depth += 1,
                        Command::JumpForward => {
                            if self.current_depth == goal_depth {
                                *index_ref = index + 1;
                                return;
                            }
                            self.current_depth -= 1;
                        }
                        _ => {}
                    }
                }
                panic!("No starting brace found!");
            }
        }
    }

    fn seek_forward(&mut self, index_ref: &mut usize) {
        if let ProgramStatus::Seeking(goal_depth) = self.status {
            for index in (*index_ref)..self.instructions.len() {
                match self.instructions[index] {
                    Command::JumpForward => self.current_depth += 1,
                    Command::JumpBackward => self.current_depth -= 1,
                    _ => {}
                }
                if self.current_depth == goal_depth {
                    *index_ref = index + 1;
                    self.status = ProgramStatus::Normal;
                    return;
                }
            }

            *index_ref = self.instructions.len();
            self.status = ProgramStatus::Seeking(goal_depth);
        }
    }

    fn handle_jump_forward(&mut self, vm: &VM, index: &mut usize) {
        match (vm.cells[vm.data_pointer], self.status) {
            (0, ProgramStatus::Normal) => {
                self.status = ProgramStatus::Seeking(self.current_depth);
                self.seek_forward(index);
            }

            (_, ProgramStatus::Normal) => {
                *index += 1;
                self.current_depth += 1;
                self.status = ProgramStatus::Normal;
            }

            (_, ProgramStatus::Seeking(_)) => self.seek_forward(index),

        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    pub fn test_seek_forward_normal() {
        let mut program = Program {
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Seeking(0),
            instructions: vec![
                Command::JumpForward,
                Command::JumpForward,
                Command::JumpBackward,
                Command::JumpBackward,
            ],
        };
        let mut index = 0;
        program.seek_forward(&mut index);
        assert_eq!(index, 4);
        assert_eq!(program.status, ProgramStatus::Normal);
    }

    #[test]
    pub fn test_seek_forward_seeking() {
        let mut index = 0;
        let mut program = Program {
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Seeking(0),
            instructions: vec![
                Command::JumpForward,
                Command::JumpForward,
                Command::JumpBackward,
            ],
        };
        program.seek_forward(&mut index);
        assert_eq!(index, 3);
        assert_eq!(program.status, ProgramStatus::Seeking(0));
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use czmq::{ZCert, ZFrame, ZMsg, ZSock, SocketType};
use error::Result;
use inapi::ProjectConfig;
use language::{Language, LanguageProject, CProject, PhpProject, RustProject};
use {read_conf, write_conf};
use std::{error, fmt, fs};
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;

pub const CONFIGNAME: &'static str = "project.json";

#[derive(Debug)]
pub struct Project {
    path: PathBuf,
    pub name: String,
    conf: ProjectConfig,
}

impl Project {
    pub fn load<P: AsRef<Path>>(path: P) -> Result<Project> {
        let mut buf = path.as_ref().to_owned();

        // Load config
        buf.push(CONFIGNAME);
        let conf: ProjectConfig = read_conf(&buf)?;
        buf.pop();

        let name = buf.file_name()
                      .ok_or(ProjectError::InvalidPath)?
                      .to_str()
                      .ok_or(ProjectError::InvalidPath)?
                      .into();

        Ok(Project {
            path: buf,
            name: name,
            conf: conf,
        })
    }

    pub fn create<P: AsRef<Path>>(project_path: P, language: Language) -> Result<Project> {
        let mut path = project_path.as_ref().to_owned();

        // Make sure folder doesn't already exist
        if path.exists() {
            return Err(ProjectError::ProjectExists.into());
        }

        path.push("data/hosts");
        try!(fs::create_dir_all(&path));
        path.pop();
        path.pop();

        path.push("payloads");
        try!(fs::create_dir(&path));
        path.pop();

        // Create git repo
        let output = try!(Command::new("git").args(&["init", path.to_str().unwrap()]).output());
        if !output.status.success() {
            return Err(ProjectError::CreateFailed(try!(String::from_utf8(output.stderr))).into());
        }

        // Update .gitignore
        path.push(".gitignore");
        let mut fh = try!(fs::OpenOptions::new()
            .create(true)
            .append(true)
            .open(&path));
        try!(fh.write_all(b"user.crt\nauth.crt\n"));
        path.pop();

        match language {
            Language::C => try!(CProject::init_project(&path)),
            Language::Php => try!(PhpProject::init_project(&path)),
            Language::Rust => try!(RustProject::init_project(&path)),
        }

        // Create project.json
        path.push(CONFIGNAME);
        let project_conf = ProjectConfig {
            language: language,
            auth_server: "auth.example.com".into(),
            auth_api_port: 7101,
            auth_update_port: 7102,
            build_server: None,
        };
        write_conf(&project_conf, &path)?;
        path.pop();

        println!("Remember to copy your user certificate to {}/user.crt.
If you do not have a user certificate, obtain one from your administrator.", path.to_str().unwrap());

        let name = path.file_name()
                       .ok_or(ProjectError::InvalidPath)?
                       .to_str()
                       .ok_or(ProjectError::InvalidPath)?
                       .into();

        Ok(Project {
            path: path,
            name: name,
            conf: project_conf,
        })
    }

    pub fn run(&self, args: &[&str], local: bool) -> Result<Option<i32>> {
        match self.conf.build_server {
            Some(ref hostname) if !local => {
                let mut buf = self.path.clone();

                buf.push("build.crt");
                let build_cert = try!(ZCert::load(buf.to_str().unwrap()));
                buf.pop();

                buf.push("user.crt");
                let user_cert = try!(ZCert::load(buf.to_str().unwrap()));
                buf.pop();

                let mut sock = ZSock::new(SocketType::DEALER);
                user_cert.apply(&mut sock);
                sock.set_curve_serverkey(build_cert.public_txt());
                sock.set_sndtimeo(Some(1000));
                try!(sock.connect(&format!("tcp://{}", hostname)));

                let msg = ZMsg::new();
                msg.addstr("RUN")?;
                for arg in args {
                    msg.addstr(arg)?;
                }
                msg.send(&mut sock)?;

                let mut err = false;

                loop {
                    let reply = ZFrame::recv(&mut sock)?;
                    match reply.data()? {
                        Ok(ref data) if data == "OK" => break,
                        Ok(ref data) if data == "ERR" => err = true,
                        Ok(data) => {
                            print!("{}", data);
                            if err {
                                break;
                            }
                        },
                        Err(bytes) => println!("Non-UTF8 bytes: {:?}", bytes),
                    }
                }

                if err {
                    Ok(Some(1))
                } else {
                    Ok(Some(0))
                }
            }
            _ => {
                let status = match self.conf.language {
                    Language::Php => PhpProject::run(args)?,
                    Language::C => CProject::run(args)?,
                    Language::Rust => RustProject::run(args)?,
                };
                Ok(status.code())
            }
        }
    }
}

#[derive(Debug)]
pub enum ProjectError {
    CreateFailed(String),
    InvalidPath,
    ProjectExists,
}

impl fmt::Display for ProjectError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ProjectError::CreateFailed(ref e) => write!(f, "Could not create project: {}", e),
            ProjectError::InvalidPath => write!(f, "Invalid path to project"),
            ProjectError::ProjectExists => write!(f, "Project already exists"),
        }
    }
}

impl error::Error for ProjectError {
    fn description(&self) -> &str {
        match *self {
            ProjectError::CreateFailed(_) => "Could not create project",
            ProjectError::InvalidPath => "Invalid path to project",
            ProjectError::ProjectExists => "Project already exists",
        }
    }
}

#[cfg(test)]
mod tests {
    use language::Language;
    use std::fs::{File, metadata};
    use std::io::Write;
    use super::*;
    use tempdir::TempDir;

    #[test]
    fn test_load_noconf() {
        let dir = TempDir::new("test_load_noconf").unwrap();
        assert!(Project::load(dir.path()).is_err());
    }

    #[test]
    fn test_load_ok() {
        let dir = TempDir::new("test_load_ok").unwrap();
        let mut path = dir.path().to_owned();

        path.push(CONFIGNAME);
        let mut file = File::create(&path).unwrap();
        file.write_all("{
            \"language\":\"Php\",
            \"auth_server\":\"auth.example.com\",
            \"auth_api_port\": 7101,
            \"auth_update_port\": 7102
        }".as_bytes()).unwrap();
        path.pop();

        assert!(Project::load(&path).is_ok());
    }

    #[test]
    fn test_create_exists() {
        let dir = TempDir::new("test_create_exists").unwrap();
        assert!(Project::create(dir.path(), Language::Php).is_err());
    }

    #[test]
    fn test_create_ok() {
        let dir = TempDir::new("test_create_ok").unwrap();
        let mut buf = dir.path().to_owned();
        buf.push("proj_dir");

        assert!(Project::create(&buf, Language::Rust).is_ok());
        assert!(metadata(format!("{}/{}", buf.to_str().unwrap(), CONFIGNAME)).is_ok());
    }
}
<commit_msg>More reliable log output<commit_after>// Copyright 2015-2017 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use czmq::{ZCert, ZFrame, ZMsg, ZSock, SocketType};
use error::Result;
use inapi::ProjectConfig;
use language::{Language, LanguageProject, CProject, PhpProject, RustProject};
use {read_conf, write_conf};
use std::{error, fmt, fs};
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;

pub const CONFIGNAME: &'static str = "project.json";

#[derive(Debug)]
pub struct Project {
    path: PathBuf,
    pub name: String,
    conf: ProjectConfig,
}

impl Project {
    pub fn load<P: AsRef<Path>>(path: P) -> Result<Project> {
        let mut buf = path.as_ref().to_owned();

        // Load config
        buf.push(CONFIGNAME);
        let conf: ProjectConfig = read_conf(&buf)?;
        buf.pop();

        let name = buf.file_name()
                      .ok_or(ProjectError::InvalidPath)?
                      .to_str()
                      .ok_or(ProjectError::InvalidPath)?
                      .into();

        Ok(Project {
            path: buf,
            name: name,
            conf: conf,
        })
    }

    pub fn create<P: AsRef<Path>>(project_path: P, language: Language) -> Result<Project> {
        let mut path = project_path.as_ref().to_owned();

        // Make sure folder doesn't already exist
        if path.exists() {
            return Err(ProjectError::ProjectExists.into());
        }

        path.push("data/hosts");
        try!(fs::create_dir_all(&path));
        path.pop();
        path.pop();

        path.push("payloads");
        try!(fs::create_dir(&path));
        path.pop();

        // Create git repo
        let output = try!(Command::new("git").args(&["init", path.to_str().unwrap()]).output());
        if !output.status.success() {
            return Err(ProjectError::CreateFailed(try!(String::from_utf8(output.stderr))).into());
        }

        // Update .gitignore
        path.push(".gitignore");
        let mut fh = try!(fs::OpenOptions::new()
            .create(true)
            .append(true)
            .open(&path));
        try!(fh.write_all(b"user.crt\nauth.crt\n"));
        path.pop();

        match language {
            Language::C => try!(CProject::init_project(&path)),
            Language::Php => try!(PhpProject::init_project(&path)),
            Language::Rust => try!(RustProject::init_project(&path)),
        }

        // Create project.json
        path.push(CONFIGNAME);
        let project_conf = ProjectConfig {
            language: language,
            auth_server: "auth.example.com".into(),
            auth_api_port: 7101,
            auth_update_port: 7102,
            build_server: None,
        };
        write_conf(&project_conf, &path)?;
        path.pop();

        println!("Remember to copy your user certificate to {}/user.crt.
If you do not have a user certificate, obtain one from your administrator.", path.to_str().unwrap());

        let name = path.file_name()
                       .ok_or(ProjectError::InvalidPath)?
                       .to_str()
                       .ok_or(ProjectError::InvalidPath)?
                       .into();

        Ok(Project {
            path: path,
            name: name,
            conf: project_conf,
        })
    }

    pub fn run(&self, args: &[&str], local: bool) -> Result<Option<i32>> {
        match self.conf.build_server {
            Some(ref hostname) if !local => {
                let mut buf = self.path.clone();

                buf.push("build.crt");
                let build_cert = try!(ZCert::load(buf.to_str().unwrap()));
                buf.pop();

                buf.push("user.crt");
                let user_cert = try!(ZCert::load(buf.to_str().unwrap()));
                buf.pop();

                let mut sock = ZSock::new(SocketType::DEALER);
                user_cert.apply(&mut sock);
                sock.set_curve_serverkey(build_cert.public_txt());
                sock.set_sndtimeo(Some(1000));
                try!(sock.connect(&format!("tcp://{}", hostname)));

                let msg = ZMsg::new();
                msg.addstr("RUN")?;
                for arg in args {
                    msg.addstr(arg)?;
                }
                msg.send(&mut sock)?;

                let mut err = false;

                loop {
                    let reply = ZFrame::recv(&mut sock)?;
                    match reply.data()? {
                        Ok(ref data) if data == "OK" => break,
                        Ok(ref data) if data == "ERR" => err = true,
                        Ok(data) => {
                            println!("{}", data.trim());
                            if err {
                                break;
                            }
                        },
                        Err(bytes) => println!("{}", String::from_utf8_lossy(&bytes).trim()),
                    }
                }

                if err {
                    Ok(Some(1))
                } else {
                    Ok(Some(0))
                }
            }
            _ => {
                let status = match self.conf.language {
                    Language::Php => PhpProject::run(args)?,
                    Language::C => CProject::run(args)?,
                    Language::Rust => RustProject::run(args)?,
                };
                Ok(status.code())
            }
        }
    }
}

#[derive(Debug)]
pub enum ProjectError {
    CreateFailed(String),
    InvalidPath,
    ProjectExists,
}

impl fmt::Display for ProjectError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ProjectError::CreateFailed(ref e) => write!(f, "Could not create project: {}", e),
            ProjectError::InvalidPath => write!(f, "Invalid path to project"),
            ProjectError::ProjectExists => write!(f, "Project already exists"),
        }
    }
}

impl error::Error for ProjectError {
    fn description(&self) -> &str {
        match *self {
            ProjectError::CreateFailed(_) => "Could not create project",
            ProjectError::InvalidPath => "Invalid path to project",
            ProjectError::ProjectExists => "Project already exists",
        }
    }
}

#[cfg(test)]
mod tests {
    use language::Language;
    use std::fs::{File, metadata};
    use std::io::Write;
    use super::*;
    use tempdir::TempDir;

    #[test]
    fn test_load_noconf() {
        let dir = TempDir::new("test_load_noconf").unwrap();
        assert!(Project::load(dir.path()).is_err());
    }

    #[test]
    fn test_load_ok() {
        let dir = TempDir::new("test_load_ok").unwrap();
        let mut path = dir.path().to_owned();

        path.push(CONFIGNAME);
        let mut file = File::create(&path).unwrap();
        file.write_all("{
            \"language\":\"Php\",
            \"auth_server\":\"auth.example.com\",
            \"auth_api_port\": 7101,
            \"auth_update_port\": 7102
        }".as_bytes()).unwrap();
        path.pop();

        assert!(Project::load(&path).is_ok());
    }

    #[test]
    fn test_create_exists() {
        let dir = TempDir::new("test_create_exists").unwrap();
        assert!(Project::create(dir.path(), Language::Php).is_err());
    }

    #[test]
    fn test_create_ok() {
        let dir = TempDir::new("test_create_ok").unwrap();
        let mut buf = dir.path().to_owned();
        buf.push("proj_dir");

        assert!(Project::create(&buf, Language::Rust).is_ok());
        assert!(metadata(format!("{}/{}", buf.to_str().unwrap(), CONFIGNAME)).is_ok());
    }
}
<|endoftext|>


<commit_before>use test_data_generator::profile::pattern::{Pattern};
use test_data_generator::profile::fact::{Fact};
use std::collections::BTreeMap;
use std::ops::AddAssign;

type PatternMap = BTreeMap<String, u32>;
//type PatternRankMap  = BTreeMap<&str, f64>;
type SizeMap = BTreeMap<u32, u32>;
type SizeRankMap  = BTreeMap<u32, f64>;

pub struct Profile {
	pub patterns: PatternMap,
	pub pattern_total: u32,
	pub pattern_keys: Vec<String>,
	pub pattern_vals: Vec<u32>,
	pub pattern_percentages: Vec<(String, f64)>,
	pub pattern_ranks: Vec<(String, f64)>,
	pub sizes: SizeMap,
	pub size_total: u32,
	pub size_ranks: Vec<(u32, f64)>,
	pub processors: u8,
	pub facts: Vec<Vec<Fact>>,
}

impl Profile {
	//constructor
	pub fn new() -> Profile {
		Profile {
			patterns: PatternMap::new(),
			pattern_total: 0,
			pattern_keys: Vec::new(),
			pattern_vals: Vec::new(),
			pattern_percentages: Vec::new(),
			pattern_ranks: Vec::new(),
			sizes: SizeMap::new(),
			size_total: 0,
			size_ranks: Vec::new(),
			processors: 4,
			facts: Profile::new_facts(4),
		}
	}

	pub fn new_with(p: u8) -> Profile {
		Profile {
			patterns: PatternMap::new(),
			pattern_total: 0,
			pattern_keys: Vec::new(),
			pattern_vals: Vec::new(),
			pattern_percentages: Vec::new(),
			pattern_ranks: Vec::new(),
			sizes: SizeMap::new(),
			size_total: 0,
			size_ranks: Vec::new(),
			processors: p,
			facts: Profile::new_facts(p),
		}
	}

	// methods
	pub fn analyze(&mut self, entity: &str) {
		let mut pattrn =  Pattern::new();

		// analyze patterns
		let rslt = pattrn.analyze(entity);

		// balance the storing of facts across all the vectors that can be processed in parallel
		let mut i = 0;
		for f in rslt.1.into_iter() {
			if i == self.processors {
				i = 0;
			}

			self.facts[i as usize].push(f);
			i = i + 1;

		}

		// store the pattern
		AddAssign::add_assign(self.patterns.entry(rslt.0.to_string()).or_insert(0), 1);

		// store the total number of patterns generated so far
		self.pattern_total = self.patterns.values().sum::<u32>();

		// analyze sizes
		AddAssign::add_assign(self.sizes.entry(pattrn.size).or_insert(0), 1);
		self.size_total = self.sizes.values().sum::<u32>();

		self.pattern_keys = self.patterns.keys().cloned().collect();
		self.pattern_vals = self.patterns.values().cloned().collect();
	}

	// Reference: https://users.rust-lang.org/t/cannot-infer-an-appropriate-lifetime-for-autoref/13360/3
	pub fn cum_patternmap(&mut self) {
		// calculate the percentage by patterns
		// -> {"CcvccpSCvcc": 14.285714285714285, "CvccvccpSCvccvc": 14.285714285714285, "CvccvccpSCvccvv": 28.57142857142857, "CvcvcccpSCcvcv": 14.285714285714285, "CvcvpSCvccc": 14.285714285714285, "V~CcvvcpSCvccc": 14.285714285714285}
		let n = self.patterns.len();

		for m in 0..n {
			self.pattern_percentages.push((self.pattern_keys[m].clone(), (self.pattern_vals[m] as f64 / self.pattern_total as f64) * 100.0));
		}

		// sort the ranks by percentages in decreasing order
		// -> [("CvccvccpSCvccvv", 28.57142857142857), ("CcvccpSCvcc", 14.285714285714285), ("CvccvccpSCvccvc", 14.285714285714285), ("CvcvcccpSCcvcv", 14.285714285714285), ("CvcvpSCvccc", 14.285714285714285), ("V~CcvvcpSCvccc", 14.285714285714285)]
		self.pattern_percentages.sort_by(|&(_, a), &(_, b)| b.partial_cmp(&a).unwrap());

		// calculate the cumulative sum of the pattern rankings
		// -> [("CvccvccpSCvccvv", 28.57142857142857), ("CcvccpSCvcc", 42.857142857142854), ("CvccvccpSCvccvc", 57.14285714285714), ("CvcvcccpSCcvcv", 71.42857142857142), ("CvcvpSCvccc", 85.7142857142857), ("V~CcvvcpSCvccc", 99.99999999999997)]
		let mut rank: f64 = 0.00;

		for pttrn in self.pattern_percentages.iter() {
			let tmp = pttrn.1 + rank;
			self.pattern_ranks.push((pttrn.0.clone(),tmp));
			rank = tmp;
		}
	}

	/// calculates the sizes to use by the chance they will occur (as cumulative percentage) in decreasing order
	pub fn cum_sizemap(&mut self) {
		// calculate the percentage by sizes
		// -> {11: 28.57142857142857, 14: 14.285714285714285, 15: 57.14285714285714}
		let mut size_ranks = SizeRankMap::new();

		for key in self.sizes.keys(){
			size_ranks.insert(*key, (*self.sizes.get(key).unwrap() as f64 / self.size_total as f64)*100.0);
		}

		// sort the ranks by percentages in decreasing order
		// -> [(15, 57.14285714285714), (11, 28.57142857142857), (14, 14.285714285714285)]
		let mut sizes = size_ranks.iter().collect::<Vec<_>>();
		sizes.sort_by(|&(_, a), &(_, b)| b.partial_cmp(&a).unwrap());

		// calculate the cumulative sum of the size rankings
		// -> [(15, 57.14285714285714), (11, 85.71428571428571), (14, 100)]
		self.size_ranks = sizes.iter().scan((0 as u32, 0.00 as f64), |state, &(&k, &v)| {
			*state = (k, state.1 + &v);
			Some(*state)
		}).collect::<Vec<(_,_)>>();
	}

	pub fn pre_generate(&mut self){
		self.cum_sizemap();
		self.cum_patternmap();
	}

	pub fn generate(&mut self) -> bool{
		// first, determine the length of the entity
		 // 1. get a random number
	 	let mut s: f64 = 0 as f64;
	 	random_percentage!(s);
	 	 // 2. find the first size that falls within the percentage chance of occurring
		let size = self.size_ranks.iter().find(|&&x|&x.1 >= &s).unwrap().0;

		// second, determine the pattern to use

		// build the entity using facts that adhere to the pattern

		if size > 0 { true } else { false }
	}

	fn new_facts(p: u8) -> Vec<Vec<Fact>> {
		let mut vec_main = Vec::new();

		for _ in 0..p {
			vec_main.push(Vec::new());
		}

		vec_main
	}

	pub fn reset_analyze(&mut self) {
		self.patterns = PatternMap::new();
	}
}<commit_msg>working on getting a pattern to use for generation<commit_after>use test_data_generator::profile::pattern::{Pattern};
use test_data_generator::profile::fact::{Fact};
use std::collections::BTreeMap;
use std::ops::AddAssign;

type PatternMap = BTreeMap<String, u32>;
//type PatternRankMap  = BTreeMap<&str, f64>;
type SizeMap = BTreeMap<u32, u32>;
type SizeRankMap  = BTreeMap<u32, f64>;

pub struct Profile {
	pub patterns: PatternMap,
	pub pattern_total: u32,
	pub pattern_keys: Vec<String>,
	pub pattern_vals: Vec<u32>,
	pub pattern_percentages: Vec<(String, f64)>,
	pub pattern_ranks: Vec<(String, f64)>,
	pub sizes: SizeMap,
	pub size_total: u32,
	pub size_ranks: Vec<(u32, f64)>,
	pub processors: u8,
	pub facts: Vec<Vec<Fact>>,
}

impl Profile {
	//constructor
	pub fn new() -> Profile {
		Profile {
			patterns: PatternMap::new(),
			pattern_total: 0,
			pattern_keys: Vec::new(),
			pattern_vals: Vec::new(),
			pattern_percentages: Vec::new(),
			pattern_ranks: Vec::new(),
			sizes: SizeMap::new(),
			size_total: 0,
			size_ranks: Vec::new(),
			processors: 4,
			facts: Profile::new_facts(4),
		}
	}

	pub fn new_with(p: u8) -> Profile {
		Profile {
			patterns: PatternMap::new(),
			pattern_total: 0,
			pattern_keys: Vec::new(),
			pattern_vals: Vec::new(),
			pattern_percentages: Vec::new(),
			pattern_ranks: Vec::new(),
			sizes: SizeMap::new(),
			size_total: 0,
			size_ranks: Vec::new(),
			processors: p,
			facts: Profile::new_facts(p),
		}
	}

	// methods
	pub fn analyze(&mut self, entity: &str) {
		let mut pattrn =  Pattern::new();

		// analyze patterns
		let rslt = pattrn.analyze(entity);

		// balance the storing of facts across all the vectors that can be processed in parallel
		let mut i = 0;
		for f in rslt.1.into_iter() {
			if i == self.processors {
				i = 0;
			}

			self.facts[i as usize].push(f);
			i = i + 1;

		}

		// store the pattern
		AddAssign::add_assign(self.patterns.entry(rslt.0.to_string()).or_insert(0), 1);

		// store the total number of patterns generated so far
		self.pattern_total = self.patterns.values().sum::<u32>();

		// analyze sizes
		AddAssign::add_assign(self.sizes.entry(pattrn.size).or_insert(0), 1);
		self.size_total = self.sizes.values().sum::<u32>();

		self.pattern_keys = self.patterns.keys().cloned().collect();
		self.pattern_vals = self.patterns.values().cloned().collect();
	}

	// Reference: https://users.rust-lang.org/t/cannot-infer-an-appropriate-lifetime-for-autoref/13360/3
	pub fn cum_patternmap(&mut self) {
		// calculate the percentage by patterns
		// -> {"CcvccpSCvcc": 14.285714285714285, "CvccvccpSCvccvc": 14.285714285714285, "CvccvccpSCvccvv": 28.57142857142857, "CvcvcccpSCcvcv": 14.285714285714285, "CvcvpSCvccc": 14.285714285714285, "V~CcvvcpSCvccc": 14.285714285714285}
		let n = self.patterns.len();

		for m in 0..n {
			self.pattern_percentages.push((self.pattern_keys[m].clone(), (self.pattern_vals[m] as f64 / self.pattern_total as f64) * 100.0));
		}

		// sort the ranks by percentages in decreasing order
		// -> [("CvccvccpSCvccvv", 28.57142857142857), ("CcvccpSCvcc", 14.285714285714285), ("CvccvccpSCvccvc", 14.285714285714285), ("CvcvcccpSCcvcv", 14.285714285714285), ("CvcvpSCvccc", 14.285714285714285), ("V~CcvvcpSCvccc", 14.285714285714285)]
		self.pattern_percentages.sort_by(|&(_, a), &(_, b)| b.partial_cmp(&a).unwrap());

		// calculate the cumulative sum of the pattern rankings
		// -> [("CvccvccpSCvccvv", 28.57142857142857), ("CcvccpSCvcc", 42.857142857142854), ("CvccvccpSCvccvc", 57.14285714285714), ("CvcvcccpSCcvcv", 71.42857142857142), ("CvcvpSCvccc", 85.7142857142857), ("V~CcvvcpSCvccc", 99.99999999999997)]
		let mut rank: f64 = 0.00;

		for pttrn in self.pattern_percentages.iter() {
			let tmp = pttrn.1 + rank;
			self.pattern_ranks.push((pttrn.0.clone(),tmp));
			rank = tmp;
		}
	}

	/// calculates the sizes to use by the chance they will occur (as cumulative percentage) in decreasing order
	pub fn cum_sizemap(&mut self) {
		// calculate the percentage by sizes
		// -> {11: 28.57142857142857, 14: 14.285714285714285, 15: 57.14285714285714}
		let mut size_ranks = SizeRankMap::new();

		for key in self.sizes.keys(){
			size_ranks.insert(*key, (*self.sizes.get(key).unwrap() as f64 / self.size_total as f64)*100.0);
		}

		// sort the ranks by percentages in decreasing order
		// -> [(15, 57.14285714285714), (11, 28.57142857142857), (14, 14.285714285714285)]
		let mut sizes = size_ranks.iter().collect::<Vec<_>>();
		sizes.sort_by(|&(_, a), &(_, b)| b.partial_cmp(&a).unwrap());

		// calculate the cumulative sum of the size rankings
		// -> [(15, 57.14285714285714), (11, 85.71428571428571), (14, 100)]
		self.size_ranks = sizes.iter().scan((0 as u32, 0.00 as f64), |state, &(&k, &v)| {
			*state = (k, state.1 + &v);
			Some(*state)
		}).collect::<Vec<(_,_)>>();
	}

	pub fn pre_generate(&mut self){
		self.cum_sizemap();
		self.cum_patternmap();
	}

	pub fn generate(&mut self) -> bool{
		// first, determine the length of the entity
		 // 1. get a random number
	 	let mut s: f64 = 0 as f64;
	 	random_percentage!(s);
	 	 // 2. find the first size that falls within the percentage chance of occurring
		let size = self.size_ranks.iter().find(|&&x|&x.1 >= &s).unwrap().0;

		// second, determine the pattern to use
		let pattern = self.pattern_ranks.iter().find(|x|&x.1 >= &s && x.0.len() == size as usize).unwrap().clone();
println!("random: {:?}, size: {:?}, pattern: {:?}",s, size, pattern.0);

		// build the entity using facts that adhere to the pattern

		if size > 0 { true } else { false }
	}

	fn new_facts(p: u8) -> Vec<Vec<Fact>> {
		let mut vec_main = Vec::new();

		for _ in 0..p {
			vec_main.push(Vec::new());
		}

		vec_main
	}

	pub fn reset_analyze(&mut self) {
		self.patterns = PatternMap::new();
	}
}<|endoftext|>


<commit_before>use std::cmp;
use std::collections::BTreeMap;
use mio;

use super::{Operation,OpResp};
use event_handler::EventHandler;

const REPLICATION_CREDIT : u64 = 1024;

#[derive(Debug)]
struct Forwarder {
    last_sent_downstream: Option<u64>,
    last_acked_downstream: Option<u64>,
    pending_operations: BTreeMap<u64, mio::Token>,
}

#[derive(Debug)]
struct Terminus {
    state: String,
}

#[derive(Debug)]
enum Role {
    Forwarder(Forwarder),
    Terminus(Terminus),
}

#[derive(Debug)]
struct Log (BTreeMap<u64, Operation>);

impl Log {
    pub fn seqno(&self) -> u64 {
        self.0.len() as u64
    }
}

#[derive(Debug)]
pub struct ReplModel {
    next: Role,
    log: Log,
    current_epoch: u64,
}

impl Role {
    fn process_operation(&mut self, channel: &mut EventHandler, epoch: u64, seqno: u64, op: Operation) {
        match self {
            &mut Role::Forwarder(ref mut f) => f.process_operation(channel, epoch, seqno, op),
            &mut Role::Terminus(ref mut t) => t.process_operation(channel, epoch, seqno, op),
        }
    }
    pub fn process_downstream_response(&mut self, reply: &OpResp) -> Option<mio::Token> {
        match self {
            &mut Role::Forwarder(ref mut f) => f.process_downstream_response(reply),
            _ => None,
        }
    }

    pub fn process_replication<F: FnMut(u64, Operation)>(&mut self, log: &Log, forward: F) -> bool {
        match self {
            &mut Role::Forwarder(ref mut f) => f.process_replication(log, forward),
            _ => false,
        }
    }
    fn has_pending(&self, token: mio::Token) -> bool {
        match self {
            &Role::Forwarder(ref f) => f.has_pending(token),
            _ => false,
        }
    }
    fn reset(&mut self) {
        match self {
            &mut Role::Forwarder(ref mut f) => f.reset(),
            _ => (),
        }
    }
}

impl Forwarder {
    fn new() -> Forwarder {
        Forwarder {
            last_sent_downstream: None,
            last_acked_downstream: None,
            pending_operations: BTreeMap::new(),
        }
    }

    fn process_operation(&mut self, channel: &mut EventHandler, epoch: u64, seqno: u64, op: Operation) {
        self.pending_operations.insert(seqno, channel.token());
    }

    fn process_downstream_response(&mut self, reply: &OpResp) -> Option<mio::Token> {
        match reply {
            &OpResp::Ok(epoch, seqno, _) | &OpResp::Err(epoch, seqno, _) => {
                self.last_acked_downstream = Some(seqno);
                if let Some(token) = self.pending_operations.remove(&seqno) {
                    info!("Found in-flight op {:?} for client token {:?}", seqno, token);
                    Some(token)
                } else {
                    warn!("Unexpected response for seqno: {:?}", seqno);
                    None
                }
            },
            &OpResp::HelloIWant(last_sent_downstream) => {
                info!("Downstream has {:?}", last_sent_downstream);
                // assert!(last_sent_downstream <= self.seqno());
                self.last_acked_downstream = Some(last_sent_downstream);
                self.last_sent_downstream = Some(last_sent_downstream);
                None
            },
        }
    }

    pub fn process_replication<F: FnMut(u64, Operation)>(&mut self, log: &Log, mut forward: F) -> bool {
        let mut changed = false;
        debug!("pre  Repl: Ours: {:?}; downstream sent: {:?}; acked: {:?}",
            log.seqno(), self.last_sent_downstream, self.last_acked_downstream);

        let mut changed = false;
        if let Some(send_next) = self.last_sent_downstream {
            if send_next < log.seqno() {
                let max_to_push_now = cmp::min(self.last_acked_downstream.unwrap_or(0) + REPLICATION_CREDIT, log.seqno());
                debug!("Window push {:?} - {:?}; waiting: {:?}", send_next, max_to_push_now, log.seqno() - max_to_push_now);
                for i in send_next..max_to_push_now {
                    debug!("Log item: {:?}: {:?}", i, log.0.get(&i));
                    let op = log.0[&i].clone();
                    debug!("Queueing seq:{:?}/{:?}; ds/seqno: {:?}", i, op, self.last_sent_downstream);
                    forward(i, op);
                    self.last_sent_downstream = Some(i+1);
                    changed = true
                }
            }
            debug!("post Repl: Ours: {:?}; downstream sent: {:?}; acked: {:?}",
                log.seqno(), self.last_sent_downstream, self.last_acked_downstream);
        }
        changed
    }

    fn has_pending(&self, token: mio::Token) -> bool {
        self.pending_operations.values().all(|tok| tok != &token)
    }

    fn reset(&mut self) {
        self.last_sent_downstream = None
    }
}

impl Terminus {
    fn new() -> Terminus {
        Terminus {
            state: "".to_string()
        }
    }

    fn process_operation(&mut self, channel: &mut EventHandler, epoch: u64, seqno: u64, op: Operation) {
        info!("Terminus! {:?}/{:?}", seqno, op);
        let resp = match op {
            Operation::Set(s) => {
                self.state = s;
                OpResp::Ok(epoch, seqno, None)
            },
                Operation::Get => OpResp::Ok(epoch, seqno, Some(self.state.clone()))
        };
        channel.response(resp)
    }
}

impl ReplModel {
    pub fn new() -> ReplModel {
        ReplModel {
            log: Log(BTreeMap::new()),
            current_epoch: Default::default(),
            next: Role::Terminus(Terminus::new()),
        }
    }

    pub fn seqno(&self) -> u64 {
        self.log.seqno()
    }

    fn next_seqno(&self) -> u64 {
        self.log.seqno()
    }

    pub fn process_operation(&mut self, channel: &mut EventHandler, seqno: Option<u64>, epoch: Option<u64>, op: Operation) {
        let seqno = seqno.unwrap_or_else(|| self.next_seqno());
        // assert!(seqno == 0 || self.log.get(&(seqno-1)).is_some());

        let epoch = epoch.unwrap_or_else(|| self.current_epoch);

       if epoch != self.current_epoch {
            warn!("Operation epoch ({}) differers from our last observed configuration: ({})",
                epoch, self.current_epoch);
            let resp = OpResp::Err(epoch, seqno, format!("BadEpoch: {}; last seen config: {}", epoch, self.current_epoch));
            channel.response(resp);
            return;
        }

        if !(seqno == 0 || self.log.0.get(&(seqno-1)).is_some()) {
            warn!("Hole in history: saw {}/{}; have: {:?}", epoch, seqno, self.log.0.keys().collect::<Vec<_>>());
            let resp = OpResp::Err(epoch, seqno, format!("Bad sequence number; previous: {:?}, saw: {:?}",
                self.log.0.keys().rev().next(), seqno));
            channel.response(resp);
            return;
        }

        let prev = self.log.0.insert(seqno, op.clone());
        debug!("Log entry {:?}: {:?}", seqno, op);
        if let Some(prev) = prev {
            panic!("Unexpectedly existing log entry for item {}: {:?}", seqno, prev);
        }

        self.next.process_operation(channel, epoch, seqno, op)
    }

    pub fn process_downstream_response(&mut self, reply: &OpResp) -> Option<mio::Token> {
        self.next.process_downstream_response(reply)
    }

    pub fn process_replication<F: FnMut(u64, u64, Operation)>(&mut self, mut forward: F) -> bool {
        let epoch = self.current_epoch;
        self.next.process_replication(&self.log, |i, op| forward(epoch, i, op))
    }

    pub fn epoch_changed(&mut self, epoch: u64) {
        self.current_epoch = epoch;
    }

    pub fn has_pending(&self, token: mio::Token) -> bool {
        self.next.has_pending(token)
    }

    pub fn reset(&mut self) {
        self.next.reset()
    }
}

<commit_msg>Trivial log wrapper.<commit_after>use std::cmp;
use std::collections::BTreeMap;
use mio;

use super::{Operation,OpResp};
use event_handler::EventHandler;

const REPLICATION_CREDIT : u64 = 1024;

#[derive(Debug)]
struct Forwarder {
    last_sent_downstream: Option<u64>,
    last_acked_downstream: Option<u64>,
    pending_operations: BTreeMap<u64, mio::Token>,
}

#[derive(Debug)]
struct Terminus {
    state: String,
}

#[derive(Debug)]
enum Role {
    Forwarder(Forwarder),
    Terminus(Terminus),
}

#[derive(Debug)]
struct Log (BTreeMap<u64, Operation>);

impl Log {
    pub fn seqno(&self) -> u64 {
        self.0.len() as u64
    }

    fn read(&self, idx: u64) -> Option<Operation> {
        self.0.get(&idx).map(|x| x.clone())
    }

    fn verify_sequential(&self, seqno: u64) -> bool {
        if !(seqno == 0 || self.0.contains_key(&(seqno-1))) {
            warn!("Hole in history: saw {}; have: {:?}", seqno, self.0.keys().collect::<Vec<_>>());
            false
        } else {
            true
        }
    }

    fn insert_at(&mut self, seqno: u64, op: &Operation) {
        let prev = self.0.insert(seqno, op.clone());
        debug!("Log entry {:?}: {:?}", seqno, op);
        if let Some(prev) = prev {
            panic!("Unexpectedly existing log entry for item {}: {:?}", seqno, prev);
        }
    }
}

#[derive(Debug)]
pub struct ReplModel {
    next: Role,
    log: Log,
    current_epoch: u64,
}

impl Role {
    fn process_operation(&mut self, channel: &mut EventHandler, epoch: u64, seqno: u64, op: Operation) {
        match self {
            &mut Role::Forwarder(ref mut f) => f.process_operation(channel, epoch, seqno, op),
            &mut Role::Terminus(ref mut t) => t.process_operation(channel, epoch, seqno, op),
        }
    }
    pub fn process_downstream_response(&mut self, reply: &OpResp) -> Option<mio::Token> {
        match self {
            &mut Role::Forwarder(ref mut f) => f.process_downstream_response(reply),
            _ => None,
        }
    }

    pub fn process_replication<F: FnMut(u64, Operation)>(&mut self, log: &Log, forward: F) -> bool {
        match self {
            &mut Role::Forwarder(ref mut f) => f.process_replication(log, forward),
            _ => false,
        }
    }
    fn has_pending(&self, token: mio::Token) -> bool {
        match self {
            &Role::Forwarder(ref f) => f.has_pending(token),
            _ => false,
        }
    }
    fn reset(&mut self) {
        match self {
            &mut Role::Forwarder(ref mut f) => f.reset(),
            _ => (),
        }
    }
}

impl Forwarder {
    fn new() -> Forwarder {
        Forwarder {
            last_sent_downstream: None,
            last_acked_downstream: None,
            pending_operations: BTreeMap::new(),
        }
    }

    fn process_operation(&mut self, channel: &mut EventHandler, epoch: u64, seqno: u64, op: Operation) {
        self.pending_operations.insert(seqno, channel.token());
    }

    fn process_downstream_response(&mut self, reply: &OpResp) -> Option<mio::Token> {
        match reply {
            &OpResp::Ok(epoch, seqno, _) | &OpResp::Err(epoch, seqno, _) => {
                self.last_acked_downstream = Some(seqno);
                if let Some(token) = self.pending_operations.remove(&seqno) {
                    info!("Found in-flight op {:?} for client token {:?}", seqno, token);
                    Some(token)
                } else {
                    warn!("Unexpected response for seqno: {:?}", seqno);
                    None
                }
            },
            &OpResp::HelloIWant(last_sent_downstream) => {
                info!("Downstream has {:?}", last_sent_downstream);
                // assert!(last_sent_downstream <= self.seqno());
                self.last_acked_downstream = Some(last_sent_downstream);
                self.last_sent_downstream = Some(last_sent_downstream);
                None
            },
        }
    }

    pub fn process_replication<F: FnMut(u64, Operation)>(&mut self, log: &Log, mut forward: F) -> bool {
        let mut changed = false;
        debug!("pre  Repl: Ours: {:?}; downstream sent: {:?}; acked: {:?}",
            log.seqno(), self.last_sent_downstream, self.last_acked_downstream);

        let mut changed = false;
        if let Some(send_next) = self.last_sent_downstream {
            if send_next < log.seqno() {
                let max_to_push_now = cmp::min(self.last_acked_downstream.unwrap_or(0) + REPLICATION_CREDIT, log.seqno());
                debug!("Window push {:?} - {:?}; waiting: {:?}", send_next, max_to_push_now, log.seqno() - max_to_push_now);
                for i in send_next..max_to_push_now {
                    if let Some(op) = log.read(i) {
                        debug!("Queueing seq:{:?}/{:?}; ds/seqno: {:?}", i, op, self.last_sent_downstream);
                        forward(i, op);
                        self.last_sent_downstream = Some(i+1);
                        changed = true
                    } else {
                        panic!("Attempted to replicate item not in log: {:?}", self);
                    }
                }
            }
            debug!("post Repl: Ours: {:?}; downstream sent: {:?}; acked: {:?}",
                log.seqno(), self.last_sent_downstream, self.last_acked_downstream);
        }
        changed
    }

    fn has_pending(&self, token: mio::Token) -> bool {
        self.pending_operations.values().all(|tok| tok != &token)
    }

    fn reset(&mut self) {
        self.last_sent_downstream = None
    }
}

impl Terminus {
    fn new() -> Terminus {
        Terminus {
            state: "".to_string()
        }
    }

    fn process_operation(&mut self, channel: &mut EventHandler, epoch: u64, seqno: u64, op: Operation) {
        info!("Terminus! {:?}/{:?}", seqno, op);
        let resp = match op {
            Operation::Set(s) => {
                self.state = s;
                OpResp::Ok(epoch, seqno, None)
            },
                Operation::Get => OpResp::Ok(epoch, seqno, Some(self.state.clone()))
        };
        channel.response(resp)
    }
}

impl ReplModel {
    pub fn new() -> ReplModel {
        ReplModel {
            log: Log(BTreeMap::new()),
            current_epoch: Default::default(),
            next: Role::Terminus(Terminus::new()),
        }
    }

    pub fn seqno(&self) -> u64 {
        self.log.seqno()
    }

    fn next_seqno(&self) -> u64 {
        self.log.seqno()
    }

    pub fn process_operation(&mut self, channel: &mut EventHandler, seqno: Option<u64>, epoch: Option<u64>, op: Operation) {
        let seqno = seqno.unwrap_or_else(|| self.next_seqno());
        let epoch = epoch.unwrap_or_else(|| self.current_epoch);

       if epoch != self.current_epoch {
            warn!("Operation epoch ({}) differers from our last observed configuration: ({})",
                epoch, self.current_epoch);
            let resp = OpResp::Err(epoch, seqno, format!("BadEpoch: {}; last seen config: {}", epoch, self.current_epoch));
            channel.response(resp);
            return;
        }

        if self.log.verify_sequential(seqno) {
            let resp = OpResp::Err(epoch, seqno, format!("Bad sequence number; saw: {:?}", seqno));
            channel.response(resp);
            return;
        }

        self.log.insert_at(seqno, &op);
        self.next.process_operation(channel, epoch, seqno, op)
    }

    pub fn process_downstream_response(&mut self, reply: &OpResp) -> Option<mio::Token> {
        self.next.process_downstream_response(reply)
    }

    pub fn process_replication<F: FnMut(u64, u64, Operation)>(&mut self, mut forward: F) -> bool {
        let epoch = self.current_epoch;
        self.next.process_replication(&self.log, |i, op| forward(epoch, i, op))
    }

    pub fn epoch_changed(&mut self, epoch: u64) {
        self.current_epoch = epoch;
    }

    pub fn has_pending(&self, token: mio::Token) -> bool {
        self.next.has_pending(token)
    }

    pub fn reset(&mut self) {
        self.next.reset()
    }
}
<|endoftext|>


<commit_before>#![deny(deprecated)]
#![deny(missing_docs)]
#![deny(non_snake_case)]
#![deny(non_upper_case_globals)]

#![feature(std_misc)]

#![doc = "Common stuff for tutorials."]
#![crate_name = "tutcommon"]

use std::default::Default;
use std::fs::File;
use std::io::Read;
use std::ops::Mul;
use std::path::Path;

#[doc = "Read content of file into string."]
pub fn read_source_from_file<P: AsRef<Path>>(path : P) -> String {
    let mut res = String::new();
    File::open(path).unwrap().read_to_string(&mut res).unwrap();
    return res;
}

#[doc = "Vector with 3 components (x,y,z)"]
pub struct Vector3f (pub f32, pub f32, pub f32);

impl Vector3f {
    #[doc = "Normalize vector to length 1."]
    pub fn normalize(&self) -> Vector3f {
        let l = (self.0 * self.0 + self.1 * self.1 + self.2 * self.2).sqrt();

        Vector3f(self.0 / l, self.1 / l, self.2 / l)
    }

    #[doc = "Cross product."]
    pub fn cross(&self, _rhs:&Vector3f) -> Vector3f {
        Vector3f (
            self.1 * _rhs.2 - self.2 * _rhs.1,
            self.2 * _rhs.0 - self.0 * _rhs.2,
            self.0 * _rhs.1 - self.1 * _rhs.0,
        )
    }

    fn sub(&self, _rhs:&Vector3f) -> Vector3f {
        Vector3f (
            self.0 - _rhs.0,
            self.1 - _rhs.1,
            self.2 - _rhs.2,
        )
    }
}

#[doc = "Matrix 4x4 to send into OpenGL."]
#[derive(Debug)]
pub struct Matrix4f {
    data : [[f32; 4]; 4], //column major order data[j][i] points to j-th column i-th row.
}

impl Matrix4f {
    #[doc = "Get raw data for OpenGL."]
    pub fn as_ptr(&self) -> * const f32 {
        self.data[0].as_ptr()
    }

    #[doc = "Get perspective projection matrix."]
    pub fn perspective(fov: f32, aspect: f32, znear: f32, zfar: f32) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        let f = 1.0 / (fov / 2.0 ).to_radians().tan();

        res.data[0][0] = f / aspect;
        res.data[1][1] = f;
        res.data[2][2] = (zfar + znear) / (znear - zfar);
        res.data[2][3] = - 1.0;
        res.data[3][2] = 2.0 * zfar * znear / (znear - zfar);
        res.data[3][3] = 0.0;

        res
    }

    #[doc = "Get orthographic projection matrix."]
    pub fn ortho(left: f32, right: f32, bottom: f32, top: f32, znear: f32, zfar: f32) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        res.data[0][0] = 2.0 / (right - left);
        res.data[1][1] = 2.0 / (top - bottom);
        res.data[2][2] = -2.0 / (zfar - znear);
        res.data[3][0] = - (right + left) / (right - left);
        res.data[3][1] = - (top + bottom) / (top - bottom);
        res.data[3][2] = - (zfar + znear) / (zfar - znear);

        res
    }

    #[doc = "Generate matrix for camera."]
    pub fn look_at(eye:Vector3f, center:Vector3f, up:Vector3f) -> Matrix4f {
        let f = center.sub(&eye).normalize();
        let up1 = up.normalize();
        let s = f.cross(&up1).normalize();
        let u = s.cross(&f);

        let mut m : Matrix4f = Default::default();
        m.data[0][0] = s.0;
        m.data[1][0] = s.1;
        m.data[2][0] = s.2;

        m.data[0][1] = u.0;
        m.data[1][1] = u.1;
        m.data[2][1] = u.2;

        m.data[0][2] = -f.0;
        m.data[1][2] = -f.1;
        m.data[2][2] = -f.2;

        let mut t : Matrix4f = Default::default();

        t.data[3][0] = -eye.0;
        t.data[3][1] = -eye.1;
        t.data[3][2] = -eye.2;

        m.mul(&t)
    }

    #[doc = "Generate translation matrix."]
    pub fn translate(t:Vector3f) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        res.data[3][0] = t.0;
        res.data[3][1] = t.1;
        res.data[3][2] = t.2;

        res
    }

    #[doc = "Generate translation matrix."]
    pub fn scale(s:Vector3f) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        res.data[0][0] = s.0;
        res.data[1][1] = s.1;
        res.data[2][2] = s.2;

        res
    }

    #[doc = "Generate rotate matrix."]
    pub fn rotate(angle:f32, axis:Vector3f) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        let a = (angle / 2.0).to_radians().sin();
        let vn = axis.normalize();

        let x = vn.0 * a;
        let y = vn.1 * a;
        let z = vn.2 * a;
        let w = (angle / 2.0).to_radians().cos();

        let x2 = x * x;
        let y2 = y * y;
        let z2 = z * z;
        let xy = x * y;
        let xz = x * z;
        let yz = y * z;
        let wx = w * x;
        let wy = w * y;
        let wz = w * z;

        res.data[0][0] = 1.0 - 2.0 * (y2 + z2);
        res.data[0][1] = 2.0 * (xy + wz);
        res.data[0][2] = 2.0 * (xz - wy);

        res.data[1][0] = 2.0 * (xy - wz);
        res.data[1][1] = 1.0 - 2.0 * (x2 + z2);
        res.data[1][2] = 2.0 * (yz + wx);

        res.data[2][0] = 2.0 * (xz + wy);
        res.data[2][1] = 2.0 * (yz - wx);
        res.data[2][2] = 1.0 - 2.0 * (x2 + y2);

        res
    }

    #[doc = "Matrix multiplication."]
    pub fn mul(&self, _rhs: &Matrix4f) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        for i in 0..4 { // row
            for j in 0..4 { // column
                let mut sum = 0.0;
                for k in 0..4 {
                    sum += self.data[k][i] * _rhs.data[j][k];
                }
                res.data[j][i] = sum;
            }
        }

        res
    }
}

impl Default for Matrix4f {
    fn default() -> Matrix4f {
        Matrix4f { data : [
            [1.0, 0.0, 0.0, 0.0,],
            [0.0, 1.0, 0.0, 0.0,],
            [0.0, 0.0, 1.0, 0.0,],
            [0.0, 0.0, 0.0, 1.0,],
        ] }
    }
}

<commit_msg>Add load_bmp to common library.<commit_after>#![deny(deprecated)]
#![deny(missing_docs)]
#![deny(non_snake_case)]
#![deny(non_upper_case_globals)]

#![feature(std_misc)]

#![doc = "Common stuff for tutorials."]
#![crate_name = "tutcommon"]

// Include SDL2 library.
extern crate sdl2;

use std::default::Default;
use std::fs::File;
use std::io::Read;
use std::ops::Mul;
use std::path::Path;
use std::ffi::OsStr;

#[doc = "Read content of file into string."]
pub fn read_source_from_file<P: AsRef<Path>>(path : P) -> String {
    let mut res = String::new();
    File::open(path).unwrap().read_to_string(&mut res).unwrap();
    return res;
}

#[doc = "Load BMP into surface."]

pub fn load_bmp<S: AsRef<OsStr> + ?Sized>(s: &S) -> sdl2::surface::Surface {
    return sdl2::surface::Surface::from_bmp(Path::new(s)).unwrap();
}

#[doc = "Vector with 3 components (x,y,z)"]
pub struct Vector3f (pub f32, pub f32, pub f32);

impl Vector3f {
    #[doc = "Normalize vector to length 1."]
    pub fn normalize(&self) -> Vector3f {
        let l = (self.0 * self.0 + self.1 * self.1 + self.2 * self.2).sqrt();

        Vector3f(self.0 / l, self.1 / l, self.2 / l)
    }

    #[doc = "Cross product."]
    pub fn cross(&self, _rhs:&Vector3f) -> Vector3f {
        Vector3f (
            self.1 * _rhs.2 - self.2 * _rhs.1,
            self.2 * _rhs.0 - self.0 * _rhs.2,
            self.0 * _rhs.1 - self.1 * _rhs.0,
        )
    }

    fn sub(&self, _rhs:&Vector3f) -> Vector3f {
        Vector3f (
            self.0 - _rhs.0,
            self.1 - _rhs.1,
            self.2 - _rhs.2,
        )
    }
}

#[doc = "Matrix 4x4 to send into OpenGL."]
#[derive(Debug)]
pub struct Matrix4f {
    data : [[f32; 4]; 4], //column major order data[j][i] points to j-th column i-th row.
}

impl Matrix4f {
    #[doc = "Get raw data for OpenGL."]
    pub fn as_ptr(&self) -> * const f32 {
        self.data[0].as_ptr()
    }

    #[doc = "Get perspective projection matrix."]
    pub fn perspective(fov: f32, aspect: f32, znear: f32, zfar: f32) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        let f = 1.0 / (fov / 2.0 ).to_radians().tan();

        res.data[0][0] = f / aspect;
        res.data[1][1] = f;
        res.data[2][2] = (zfar + znear) / (znear - zfar);
        res.data[2][3] = - 1.0;
        res.data[3][2] = 2.0 * zfar * znear / (znear - zfar);
        res.data[3][3] = 0.0;

        res
    }

    #[doc = "Get orthographic projection matrix."]
    pub fn ortho(left: f32, right: f32, bottom: f32, top: f32, znear: f32, zfar: f32) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        res.data[0][0] = 2.0 / (right - left);
        res.data[1][1] = 2.0 / (top - bottom);
        res.data[2][2] = -2.0 / (zfar - znear);
        res.data[3][0] = - (right + left) / (right - left);
        res.data[3][1] = - (top + bottom) / (top - bottom);
        res.data[3][2] = - (zfar + znear) / (zfar - znear);

        res
    }

    #[doc = "Generate matrix for camera."]
    pub fn look_at(eye:Vector3f, center:Vector3f, up:Vector3f) -> Matrix4f {
        let f = center.sub(&eye).normalize();
        let up1 = up.normalize();
        let s = f.cross(&up1).normalize();
        let u = s.cross(&f);

        let mut m : Matrix4f = Default::default();
        m.data[0][0] = s.0;
        m.data[1][0] = s.1;
        m.data[2][0] = s.2;

        m.data[0][1] = u.0;
        m.data[1][1] = u.1;
        m.data[2][1] = u.2;

        m.data[0][2] = -f.0;
        m.data[1][2] = -f.1;
        m.data[2][2] = -f.2;

        let mut t : Matrix4f = Default::default();

        t.data[3][0] = -eye.0;
        t.data[3][1] = -eye.1;
        t.data[3][2] = -eye.2;

        m.mul(&t)
    }

    #[doc = "Generate translation matrix."]
    pub fn translate(t:Vector3f) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        res.data[3][0] = t.0;
        res.data[3][1] = t.1;
        res.data[3][2] = t.2;

        res
    }

    #[doc = "Generate translation matrix."]
    pub fn scale(s:Vector3f) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        res.data[0][0] = s.0;
        res.data[1][1] = s.1;
        res.data[2][2] = s.2;

        res
    }

    #[doc = "Generate rotate matrix."]
    pub fn rotate(angle:f32, axis:Vector3f) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        let a = (angle / 2.0).to_radians().sin();
        let vn = axis.normalize();

        let x = vn.0 * a;
        let y = vn.1 * a;
        let z = vn.2 * a;
        let w = (angle / 2.0).to_radians().cos();

        let x2 = x * x;
        let y2 = y * y;
        let z2 = z * z;
        let xy = x * y;
        let xz = x * z;
        let yz = y * z;
        let wx = w * x;
        let wy = w * y;
        let wz = w * z;

        res.data[0][0] = 1.0 - 2.0 * (y2 + z2);
        res.data[0][1] = 2.0 * (xy + wz);
        res.data[0][2] = 2.0 * (xz - wy);

        res.data[1][0] = 2.0 * (xy - wz);
        res.data[1][1] = 1.0 - 2.0 * (x2 + z2);
        res.data[1][2] = 2.0 * (yz + wx);

        res.data[2][0] = 2.0 * (xz + wy);
        res.data[2][1] = 2.0 * (yz - wx);
        res.data[2][2] = 1.0 - 2.0 * (x2 + y2);

        res
    }

    #[doc = "Matrix multiplication."]
    pub fn mul(&self, _rhs: &Matrix4f) -> Matrix4f {
        let mut res : Matrix4f = Default::default();

        for i in 0..4 { // row
            for j in 0..4 { // column
                let mut sum = 0.0;
                for k in 0..4 {
                    sum += self.data[k][i] * _rhs.data[j][k];
                }
                res.data[j][i] = sum;
            }
        }

        res
    }
}

impl Default for Matrix4f {
    fn default() -> Matrix4f {
        Matrix4f { data : [
            [1.0, 0.0, 0.0, 0.0,],
            [0.0, 1.0, 0.0, 0.0,],
            [0.0, 0.0, 1.0, 0.0,],
            [0.0, 0.0, 0.0, 1.0,],
        ] }
    }
}

<|endoftext|>


<commit_before>pub mod builtins;
pub mod utils;
pub mod read_line;
pub mod exec;

use std::env;
use std::path::{Path, PathBuf};
use std::fmt;
use std::io;
use std::io::Write;
use std::collections::HashMap;
use std::collections::hash_map::Entry;

#[derive(Clone)]
pub struct State {
    cwd: PathBuf,
    variables: HashMap<String, String>,
    aliases: HashMap<String, String>,
    argv: Vec<String>,
    argc: usize,
    exit_status: i32,
}

impl fmt::Debug for State {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "State {{
\tcwd: {},
\tvariables: {:?},
\taliases: {:?},
\targv: {:?}
\targc: {}
\texit_status: {}
}}
",
               self.cwd.display(),
               self.variables,
               self.aliases,
               self.argv,
               self.argc,
               self.exit_status)
    }
}

impl State {
    pub fn new(cwd: String) -> State {
        let mut vars = HashMap::new();
        vars.insert("PATH".to_string(),
                    "/usr/bin;/usr/local/bin;/bin;/sbin".to_string());

        State {
            cwd: utils::make_absolute(PathBuf::from(cwd)).unwrap(),
            variables: vars.clone(),
            aliases: HashMap::new(),
            argv: Vec::new(),
            argc: 0,
            exit_status: 0,
        }
    }

    pub fn default() -> State {
        match env::current_dir() {
            Ok(cwd) => {
                let mut vars = HashMap::new();
                vars.insert("PATH".to_string(),
                            "/usr/bin;/usr/local/bin;/bin;/sbin".to_string());

                State {
                    cwd: cwd,
                    variables: vars.clone(),
                    aliases: HashMap::new(),
                    argv: Vec::new(),
                    argc: 0,
                    exit_status: 0,
                }
            }
            Err(e) => panic!(e),
        }
    }

    #[cfg(any(unix))]
    pub fn exec_paths(&self) -> Vec<PathBuf> {
        let path = if let Ok(s) = env::var("PATH") {
            s.clone()
        } else {
            "".to_string()
        };

        path.split(":")
            .map(|x| Path::new(x).to_path_buf())
            .collect()
    }

    #[cfg(windows)]
    pub fn exec_paths(&self) -> Vec<PathBuf> {
        let path = if let Ok(s) = env::var("PATH") {
            s.clone()
        } else {
            "".to_string()
        };

        path.split(";")
            .map(|x| Path::new(x).to_path_buf())
            .collect()
    }

    pub fn env<'a>(&'a mut self, key: String, value: String) -> &'a mut State {
        self.variables.insert(key, value);
        self
    }

    pub fn alias<'a>(&'a mut self, alias: String, value: String) -> &'a mut State {
        self.aliases.insert(alias, value);
        self
    }
}

pub fn run(initial_state: State) {
    let mut s = initial_state.clone();
    let mut builtins = builtins::load();
    let i = read_line::Input::from(&s);

    println!("Welcome to rsh! {:?}", s);

    loop {

        let input = i.prompt(format!("{} -> ", s.cwd.display()));

        s.argv = parse_args(&input);
        s.argc = s.argv.len();

        print!("\n");
        println!("Input: {} {:?}", input, s);

        let first_arg = s.argv.get(0).unwrap().clone();
        if let Entry::Occupied(f) = builtins.entry(String::from(first_arg)) {
            let bn = f.get();
            s.exit_status = bn(&mut s);
            // prompt for input again.
            continue;
        }

        // else try to run the command
        exec::exec(&s);
    }
}

#[derive(PartialEq)]
enum BuildType {
    None,
    Single,
    Double,
}

struct ParseResult {
    result: Vec<String>,
    completed: bool,
    build_string: String,
    build_type: BuildType,
}

fn parse_args(args: &String) -> Vec<String> {
    if args.len() == 0 {
        return Vec::new();
    }

    let mut parse_result: ParseResult = ParseResult {
        result: Vec::new(),
        completed: false,
        build_string: String::from(""),
        build_type: BuildType::None,
    };

    let mut argstr = args.clone();

    parse_string_into_vec(&argstr, &mut parse_result);

    while !parse_result.completed {
        // prompt for the rest of input
        print!(">");
        io::stdout().flush();
        argstr = String::from("");
        io::stdin().read_line(&mut argstr).unwrap();

        parse_string_into_vec(&argstr, &mut parse_result);
    }

    let result: Vec<String> = parse_result.result
        .into_iter()
        .filter(|s| s.len() > 0)
        .collect();

    result
}

fn parse_string_into_vec(string: &String, parse_result: &mut ParseResult) {
    let &mut ParseResult { ref mut build_string,
                           ref mut build_type,
                           ref mut completed,
                           ref mut result } = parse_result;
    let mut iter = string.chars().peekable();

    while let Some(c) = iter.next() {
        match c {
            '\'' => {
                match *build_type {
                    BuildType::Single => {
                        *build_type = BuildType::None;
                        if iter.peek() == Some(&' ') {
                            result.push(build_string.clone());
                            *build_string = String::from("");
                        }
                    }

                    BuildType::None => {
                        *build_type = BuildType::Single;
                    }

                    _ => {
                        build_string.push(c);
                    }
                }
            }

            '\"' => {
                match *build_type {
                    BuildType::Double => {
                        *build_type = BuildType::None;
                        if iter.peek() == Some(&' ') {
                            result.push(build_string.clone());
                            *build_string = String::from("");
                        }
                    }

                    BuildType::None => {
                        *build_type = BuildType::Double;
                    }

                    _ => {
                        build_string.push(c);
                    }
                }
            }

            ' ' => {
                match *build_type {
                    BuildType::None => {
                        result.push(build_string.clone());
                        *build_string = String::from("");
                    }

                    _ => {
                        build_string.push(c);
                    }
                }
            }

            '\n' => {
                match *build_type {
                    BuildType::None => {
                        match iter.peek() {
                            Some(_) => {
                                build_string.push(c);
                            }
                            None => {}
                        }
                    }
                    _ => {
                        build_string.push(c);
                    }
                }
            }

            _ => {
                build_string.push(c);
            }
        }
    }

    if *build_type == BuildType::None {
        *completed = true;
        if build_string.len() > 0 {
            result.push(build_string.clone());
        }
    }
}

#[test]
fn parse_args_test() {
    // parse empty string
    {
        let expected: Vec<String> = Vec::new();
        let result = parse_args(&String::from(""));
        assert_eq!(result, expected);
    }

    // parse single-word string
    {
        let expected: Vec<String> = vec!["echo".to_string()];
        let result = parse_args(&String::from("echo"));
        assert_eq!(result, expected);
    }

    // parse single-word string inside quotes
    {
        let expected = vec!["echo".to_string()];
        let result = parse_args(&String::from("\"echo\""));
        assert_eq!(result, expected);
    }

    // parse multi-word string with closed quotes section
    {
        let expected = vec!["echo".to_string(), "-n".into(), "Hello Dear World".into()];
        let result = parse_args(&String::from("echo -n \"Hello Dear World\""));
        assert_eq!(result, expected);
    }

    // parse multi-word string with multiple closed quotes sections
    {
        let expected = vec!["echo".to_string(), "Hello".into(), "Dear World".into()];
        let result = parse_args(&String::from("echo \"Hello\" \"Dear World\""));
        assert_eq!(result, expected);
    }

    // parse multi-word string with no spaces around single quotes
    {
        let expected = vec!["echo".to_string(), "helloworld".into()];
        let result = parse_args(&String::from("echo 'hello'world"));
        assert_eq!(result, expected);
    }

    // parse multi-word string with no spaces around double quotes
    {
        let expected = vec!["echo".to_string(), "helloworld".into()];
        let result = parse_args(&String::from("echo \"hello\"world"));
        assert_eq!(result, expected);
    }

    // allow double quotes inside single quotes
    {
        let expected = vec!["\"".to_string()];
        let result = parse_args(&String::from("'\"'"));
        assert_eq!(result, expected);
    }

    // allow single quotes inside double quotes
    {
        let expected = vec!["\'".to_string()];
        let result = parse_args(&String::from("\"\'\""));
        assert_eq!(result, expected);
    }

    // handle multiple quote sections in succession
    {
        let expected = vec!["echo".to_string(), "hello world how are you".into()];
        let result = parse_args(&String::from("echo \"hello world\"\' how are you\'"));
        assert_eq!(result, expected);
    }

    // preserve newlines
    {
        let expected = vec!["echo".to_string(), "hello\nworld".into()];
        let result = parse_args(&String::from("echo \"hello\nworld\""));
        assert_eq!(result, expected);
    }

    // remove final newline
    {
        let expected = vec!["echo".to_string()];
        let result = parse_args(&String::from("echo\n"));
        assert_eq!(result, expected);
    }
}
<commit_msg>remove variables from state<commit_after>pub mod builtins;
pub mod utils;
pub mod read_line;
pub mod exec;

use std::env;
use std::path::{Path, PathBuf};
use std::fmt;
use std::io;
use std::io::Write;
use std::collections::HashMap;
use std::collections::hash_map::Entry;

#[derive(Clone)]
pub struct State {
    cwd: PathBuf,
    aliases: HashMap<String, String>,
    argv: Vec<String>,
    argc: usize,
    exit_status: i32,
}

impl fmt::Debug for State {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "State {{
\tcwd: {},
\taliases: {:?},
\targv: {:?}
\targc: {}
\texit_status: {}
}}
",
               self.cwd.display(),
               self.aliases,
               self.argv,
               self.argc,
               self.exit_status)
    }
}

impl State {
    pub fn new(cwd: String) -> State {
        State {
            cwd: utils::make_absolute(PathBuf::from(cwd)).unwrap(),
            aliases: HashMap::new(),
            argv: Vec::new(),
            argc: 0,
            exit_status: 0,
        }
    }

    pub fn default() -> State {
        match env::current_dir() {
            Ok(cwd) => {
                State {
                    cwd: cwd,
                    aliases: HashMap::new(),
                    argv: Vec::new(),
                    argc: 0,
                    exit_status: 0,
                }
            }
            Err(e) => panic!(e),
        }
    }

    #[cfg(any(unix))]
    pub fn exec_paths(&self) -> Vec<PathBuf> {
        let path = if let Ok(s) = env::var("PATH") {
            s.clone()
        } else {
            "".to_string()
        };

        path.split(":")
            .map(|x| Path::new(x).to_path_buf())
            .collect()
    }

    #[cfg(windows)]
    pub fn exec_paths(&self) -> Vec<PathBuf> {
        let path = if let Ok(s) = env::var("PATH") {
            s.clone()
        } else {
            "".to_string()
        };

        path.split(";")
            .map(|x| Path::new(x).to_path_buf())
            .collect()
    }
}

pub fn run(initial_state: State) {
    let mut s = initial_state.clone();
    let mut builtins = builtins::load();
    let i = read_line::Input::from(&s);

    println!("Welcome to rsh! {:?}", s);

    loop {

        let input = i.prompt(format!("{} -> ", s.cwd.display()));

        s.argv = parse_args(&input);
        s.argc = s.argv.len();

        print!("\n");
        println!("Input: {} {:?}", input, s);

        let first_arg = s.argv.get(0).unwrap().clone();
        if let Entry::Occupied(f) = builtins.entry(String::from(first_arg)) {
            let bn = f.get();
            s.exit_status = bn(&mut s);
            // prompt for input again.
            continue;
        }

        // else try to run the command
        exec::exec(&s);
    }
}

#[derive(PartialEq)]
enum BuildType {
    None,
    Single,
    Double,
}

struct ParseResult {
    result: Vec<String>,
    completed: bool,
    build_string: String,
    build_type: BuildType,
}

fn parse_args(args: &String) -> Vec<String> {
    if args.len() == 0 {
        return Vec::new();
    }

    let mut parse_result: ParseResult = ParseResult {
        result: Vec::new(),
        completed: false,
        build_string: String::from(""),
        build_type: BuildType::None,
    };

    let mut argstr = args.clone();

    parse_string_into_vec(&argstr, &mut parse_result);

    while !parse_result.completed {
        // prompt for the rest of input
        print!(">");
        io::stdout().flush();
        argstr = String::from("");
        io::stdin().read_line(&mut argstr).unwrap();

        parse_string_into_vec(&argstr, &mut parse_result);
    }

    let result: Vec<String> = parse_result.result
        .into_iter()
        .filter(|s| s.len() > 0)
        .collect();

    result
}

fn parse_string_into_vec(string: &String, parse_result: &mut ParseResult) {
    let &mut ParseResult { ref mut build_string,
                           ref mut build_type,
                           ref mut completed,
                           ref mut result } = parse_result;
    let mut iter = string.chars().peekable();

    while let Some(c) = iter.next() {
        match c {
            '\'' => {
                match *build_type {
                    BuildType::Single => {
                        *build_type = BuildType::None;
                        if iter.peek() == Some(&' ') {
                            result.push(build_string.clone());
                            *build_string = String::from("");
                        }
                    }

                    BuildType::None => {
                        *build_type = BuildType::Single;
                    }

                    _ => {
                        build_string.push(c);
                    }
                }
            }

            '\"' => {
                match *build_type {
                    BuildType::Double => {
                        *build_type = BuildType::None;
                        if iter.peek() == Some(&' ') {
                            result.push(build_string.clone());
                            *build_string = String::from("");
                        }
                    }

                    BuildType::None => {
                        *build_type = BuildType::Double;
                    }

                    _ => {
                        build_string.push(c);
                    }
                }
            }

            ' ' => {
                match *build_type {
                    BuildType::None => {
                        result.push(build_string.clone());
                        *build_string = String::from("");
                    }

                    _ => {
                        build_string.push(c);
                    }
                }
            }

            '\n' => {
                match *build_type {
                    BuildType::None => {
                        match iter.peek() {
                            Some(_) => {
                                build_string.push(c);
                            }
                            None => {}
                        }
                    }
                    _ => {
                        build_string.push(c);
                    }
                }
            }

            _ => {
                build_string.push(c);
            }
        }
    }

    if *build_type == BuildType::None {
        *completed = true;
        if build_string.len() > 0 {
            result.push(build_string.clone());
        }
    }
}

#[test]
fn parse_args_test() {
    // parse empty string
    {
        let expected: Vec<String> = Vec::new();
        let result = parse_args(&String::from(""));
        assert_eq!(result, expected);
    }

    // parse single-word string
    {
        let expected: Vec<String> = vec!["echo".to_string()];
        let result = parse_args(&String::from("echo"));
        assert_eq!(result, expected);
    }

    // parse single-word string inside quotes
    {
        let expected = vec!["echo".to_string()];
        let result = parse_args(&String::from("\"echo\""));
        assert_eq!(result, expected);
    }

    // parse multi-word string with closed quotes section
    {
        let expected = vec!["echo".to_string(), "-n".into(), "Hello Dear World".into()];
        let result = parse_args(&String::from("echo -n \"Hello Dear World\""));
        assert_eq!(result, expected);
    }

    // parse multi-word string with multiple closed quotes sections
    {
        let expected = vec!["echo".to_string(), "Hello".into(), "Dear World".into()];
        let result = parse_args(&String::from("echo \"Hello\" \"Dear World\""));
        assert_eq!(result, expected);
    }

    // parse multi-word string with no spaces around single quotes
    {
        let expected = vec!["echo".to_string(), "helloworld".into()];
        let result = parse_args(&String::from("echo 'hello'world"));
        assert_eq!(result, expected);
    }

    // parse multi-word string with no spaces around double quotes
    {
        let expected = vec!["echo".to_string(), "helloworld".into()];
        let result = parse_args(&String::from("echo \"hello\"world"));
        assert_eq!(result, expected);
    }

    // allow double quotes inside single quotes
    {
        let expected = vec!["\"".to_string()];
        let result = parse_args(&String::from("'\"'"));
        assert_eq!(result, expected);
    }

    // allow single quotes inside double quotes
    {
        let expected = vec!["\'".to_string()];
        let result = parse_args(&String::from("\"\'\""));
        assert_eq!(result, expected);
    }

    // handle multiple quote sections in succession
    {
        let expected = vec!["echo".to_string(), "hello world how are you".into()];
        let result = parse_args(&String::from("echo \"hello world\"\' how are you\'"));
        assert_eq!(result, expected);
    }

    // preserve newlines
    {
        let expected = vec!["echo".to_string(), "hello\nworld".into()];
        let result = parse_args(&String::from("echo \"hello\nworld\""));
        assert_eq!(result, expected);
    }

    // remove final newline
    {
        let expected = vec!["echo".to_string()];
        let result = parse_args(&String::from("echo\n"));
        assert_eq!(result, expected);
    }
}
<|endoftext|>