<commit_before>use std::ffi::{OsString, OsStr};
use std::env;

use crate::stacked_borrows::Tag;
use crate::rustc_target::abi::LayoutOf;
use crate::*;

use rustc_data_structures::fx::FxHashMap;
use rustc::ty::layout::Size;
use rustc_mir::interpret::Pointer;

#[derive(Default)]
pub struct EnvVars {
    /// Stores pointers to the environment variables. These variables must be stored as
    /// null-terminated C strings with the `"{name}={value}"` format.
    map: FxHashMap<OsString, Pointer<Tag>>,
}

impl EnvVars {
    pub(crate) fn init<'mir, 'tcx>(
        ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
        excluded_env_vars: Vec<String>,
    ) -> InterpResult<'tcx> {
        if ecx.machine.communicate {
            for (name, value) in env::vars() {
                if !excluded_env_vars.contains(&name) {
                    let var_ptr =
                        alloc_env_var_as_c_str(name.as_ref(), value.as_ref(), ecx);
                    ecx.machine.env_vars.map.insert(OsString::from(name), var_ptr);
                }
            }
        }
        // Initialize the `environ` static
        let layout = ecx.layout_of(ecx.tcx.types.usize)?;
        let place = ecx.allocate(layout, MiriMemoryKind::Machine.into());
        ecx.write_scalar(Scalar::from_machine_usize(0, &*ecx.tcx), place.into())?;
        ecx.memory.extra.environ = Some(place);
        ecx.update_environ()
    }
}

fn alloc_env_var_as_c_str<'mir, 'tcx>(
    name: &OsStr,
    value: &OsStr,
    ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
) -> Pointer<Tag> {
    let mut name_osstring = name.to_os_string();
    name_osstring.push("=");
    name_osstring.push(value);
    ecx.alloc_os_str_as_c_str(name_osstring.as_os_str(), MiriMemoryKind::Machine.into())
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn getenv(&mut self, name_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, Scalar<Tag>> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let name = this.read_os_str_from_c_str(name_ptr)?;
        Ok(match this.machine.env_vars.map.get(name) {
            // The offset is used to strip the "{name}=" part of the string.
            Some(var_ptr) => {
                Scalar::from(var_ptr.offset(Size::from_bytes(name.len() as u64 + 1), this)?)
            }
            None => Scalar::ptr_null(&*this.tcx),
        })
    }

    fn setenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
        value_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let mut this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let value_ptr = this.read_scalar(value_op)?.not_undef()?;
        let value = this.read_os_str_from_c_str(value_ptr)?;
        let mut new = None;
        if !this.is_null(name_ptr)? {
            let name = this.read_os_str_from_c_str(name_ptr)?;
            if !name.is_empty() && !name.to_string_lossy().contains('=') {
                new = Some((name.to_owned(), value.to_owned()));
            }
        }
        if let Some((name, value)) = new {
            let var_ptr = alloc_env_var_as_c_str(&name, &value, &mut this);
            if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), var_ptr) {
                this.memory
                    .deallocate(var, None, MiriMemoryKind::Machine.into())?;
            }
            this.update_environ()?;
            Ok(0)
        } else {
            Ok(-1)
        }
    }

    fn unsetenv(&mut self, name_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let mut success = None;
        if !this.is_null(name_ptr)? {
            let name = this.read_os_str_from_c_str(name_ptr)?.to_owned();
            if !name.is_empty() && !name.to_string_lossy().contains('=') {
                success = Some(this.machine.env_vars.map.remove(&name));
            }
        }
        if let Some(old) = success {
            if let Some(var) = old {
                this.memory
                    .deallocate(var, None, MiriMemoryKind::Machine.into())?;
            }
            this.update_environ()?;
            Ok(0)
        } else {
            Ok(-1)
        }
    }

    fn getcwd(
        &mut self,
        buf_op: OpTy<'tcx, Tag>,
        size_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, Scalar<Tag>> {
        let this = self.eval_context_mut();

        this.check_no_isolation("getcwd")?;

        let buf = this.read_scalar(buf_op)?.not_undef()?;
        let size = this.read_scalar(size_op)?.to_machine_usize(&*this.tcx)?;
        // If we cannot get the current directory, we return null
        match env::current_dir() {
            Ok(cwd) => {
                if this.write_os_str_to_c_str(&OsString::from(cwd), buf, size)?.0 {
                    return Ok(buf);
                }
                let erange = this.eval_libc("ERANGE")?;
                this.set_last_error(erange)?;
            }
            Err(e) => this.set_last_error_from_io_error(e)?,
        }
        Ok(Scalar::ptr_null(&*this.tcx))
    }

    fn chdir(&mut self, path_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.check_no_isolation("chdir")?;

        let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;

        match env::set_current_dir(path) {
            Ok(()) => Ok(0),
            Err(e) => {
                this.set_last_error_from_io_error(e)?;
                Ok(-1)
            }
        }
    }

    /// Updates the `environ` static. It should not be called before
    /// `EnvVars::init`.
    fn update_environ(&mut self) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();
        // Deallocate the old environ value.
        let old_vars_ptr = this.read_scalar(this.memory.extra.environ.unwrap().into())?.not_undef()?;
        // The pointer itself can be null because `EnvVars::init` only
        // initializes the place for the static but not the static itself.
        if !this.is_null(old_vars_ptr)? {
            this.memory.deallocate(this.force_ptr(old_vars_ptr)?, None, MiriMemoryKind::Machine.into())?;
        }
        // Collect all the pointers to each variable in a vector.
        let mut vars: Vec<Scalar<Tag>> = this.machine.env_vars.map.values().map(|&ptr| ptr.into()).collect();
        // Add the trailing null pointer.
        vars.push(Scalar::from_int(0, this.pointer_size()));
        // Make an array with all these pointers inside Miri.
        let tcx = this.tcx;
        let vars_layout =
            this.layout_of(tcx.mk_array(tcx.types.usize, vars.len() as u64))?;
        let vars_place = this.allocate(vars_layout, MiriMemoryKind::Machine.into());
        for (idx, var) in vars.into_iter().enumerate() {
            let place = this.mplace_field(vars_place, idx as u64)?;
            this.write_scalar(var, place.into())?;
        }
        this.write_scalar(
            vars_place.ptr,
            this.memory.extra.environ.unwrap().into(),
        )?;

        Ok(())
    }
}
<commit_msg>move environ init to update_environ<commit_after>use std::ffi::{OsString, OsStr};
use std::env;

use crate::stacked_borrows::Tag;
use crate::rustc_target::abi::LayoutOf;
use crate::*;

use rustc_data_structures::fx::FxHashMap;
use rustc::ty::layout::Size;
use rustc_mir::interpret::Pointer;

#[derive(Default)]
pub struct EnvVars {
    /// Stores pointers to the environment variables. These variables must be stored as
    /// null-terminated C strings with the `"{name}={value}"` format.
    map: FxHashMap<OsString, Pointer<Tag>>,
}

impl EnvVars {
    pub(crate) fn init<'mir, 'tcx>(
        ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
        excluded_env_vars: Vec<String>,
    ) -> InterpResult<'tcx> {
        if ecx.machine.communicate {
            for (name, value) in env::vars() {
                if !excluded_env_vars.contains(&name) {
                    let var_ptr =
                        alloc_env_var_as_c_str(name.as_ref(), value.as_ref(), ecx);
                    ecx.machine.env_vars.map.insert(OsString::from(name), var_ptr);
                }
            }
        }
        ecx.update_environ()
    }
}

fn alloc_env_var_as_c_str<'mir, 'tcx>(
    name: &OsStr,
    value: &OsStr,
    ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
) -> Pointer<Tag> {
    let mut name_osstring = name.to_os_string();
    name_osstring.push("=");
    name_osstring.push(value);
    ecx.alloc_os_str_as_c_str(name_osstring.as_os_str(), MiriMemoryKind::Machine.into())
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn getenv(&mut self, name_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, Scalar<Tag>> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let name = this.read_os_str_from_c_str(name_ptr)?;
        Ok(match this.machine.env_vars.map.get(name) {
            // The offset is used to strip the "{name}=" part of the string.
            Some(var_ptr) => {
                Scalar::from(var_ptr.offset(Size::from_bytes(name.len() as u64 + 1), this)?)
            }
            None => Scalar::ptr_null(&*this.tcx),
        })
    }

    fn setenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
        value_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let mut this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let value_ptr = this.read_scalar(value_op)?.not_undef()?;
        let value = this.read_os_str_from_c_str(value_ptr)?;
        let mut new = None;
        if !this.is_null(name_ptr)? {
            let name = this.read_os_str_from_c_str(name_ptr)?;
            if !name.is_empty() && !name.to_string_lossy().contains('=') {
                new = Some((name.to_owned(), value.to_owned()));
            }
        }
        if let Some((name, value)) = new {
            let var_ptr = alloc_env_var_as_c_str(&name, &value, &mut this);
            if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), var_ptr) {
                this.memory
                    .deallocate(var, None, MiriMemoryKind::Machine.into())?;
            }
            this.update_environ()?;
            Ok(0)
        } else {
            Ok(-1)
        }
    }

    fn unsetenv(&mut self, name_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let mut success = None;
        if !this.is_null(name_ptr)? {
            let name = this.read_os_str_from_c_str(name_ptr)?.to_owned();
            if !name.is_empty() && !name.to_string_lossy().contains('=') {
                success = Some(this.machine.env_vars.map.remove(&name));
            }
        }
        if let Some(old) = success {
            if let Some(var) = old {
                this.memory
                    .deallocate(var, None, MiriMemoryKind::Machine.into())?;
            }
            this.update_environ()?;
            Ok(0)
        } else {
            Ok(-1)
        }
    }

    fn getcwd(
        &mut self,
        buf_op: OpTy<'tcx, Tag>,
        size_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, Scalar<Tag>> {
        let this = self.eval_context_mut();

        this.check_no_isolation("getcwd")?;

        let buf = this.read_scalar(buf_op)?.not_undef()?;
        let size = this.read_scalar(size_op)?.to_machine_usize(&*this.tcx)?;
        // If we cannot get the current directory, we return null
        match env::current_dir() {
            Ok(cwd) => {
                if this.write_os_str_to_c_str(&OsString::from(cwd), buf, size)?.0 {
                    return Ok(buf);
                }
                let erange = this.eval_libc("ERANGE")?;
                this.set_last_error(erange)?;
            }
            Err(e) => this.set_last_error_from_io_error(e)?,
        }
        Ok(Scalar::ptr_null(&*this.tcx))
    }

    fn chdir(&mut self, path_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.check_no_isolation("chdir")?;

        let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;

        match env::set_current_dir(path) {
            Ok(()) => Ok(0),
            Err(e) => {
                this.set_last_error_from_io_error(e)?;
                Ok(-1)
            }
        }
    }

    /// Updates the `environ` static.
    /// The first time it gets called, also initializes `extra.environ`.
    fn update_environ(&mut self) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();
        // Deallocate the old environ value, if any.
        if let Some(environ) = this.memory.extra.environ {
            let old_vars_ptr = this.read_scalar(environ.into())?.not_undef()?;
            this.memory.deallocate(this.force_ptr(old_vars_ptr)?, None, MiriMemoryKind::Machine.into())?;
        } else {
            // No `environ` allocated yet, let's do that.
            let layout = this.layout_of(this.tcx.types.usize)?;
            let place = this.allocate(layout, MiriMemoryKind::Machine.into());
            this.write_scalar(Scalar::from_machine_usize(0, &*this.tcx), place.into())?;
            this.memory.extra.environ = Some(place);
        }

        // Collect all the pointers to each variable in a vector.
        let mut vars: Vec<Scalar<Tag>> = this.machine.env_vars.map.values().map(|&ptr| ptr.into()).collect();
        // Add the trailing null pointer.
        vars.push(Scalar::from_int(0, this.pointer_size()));
        // Make an array with all these pointers inside Miri.
        let tcx = this.tcx;
        let vars_layout =
            this.layout_of(tcx.mk_array(tcx.types.usize, vars.len() as u64))?;
        let vars_place = this.allocate(vars_layout, MiriMemoryKind::Machine.into());
        for (idx, var) in vars.into_iter().enumerate() {
            let place = this.mplace_field(vars_place, idx as u64)?;
            this.write_scalar(var, place.into())?;
        }
        this.write_scalar(
            vars_place.ptr,
            this.memory.extra.environ.unwrap().into(),
        )?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use rustc::ty::layout::{Size, Align};
use rustc_mir::interpret::{Pointer, Memory};
use crate::stacked_borrows::Tag;
use crate::*;

#[derive(Default)]
pub struct EnvVars {
    map: HashMap<Vec<u8>, Pointer<Tag>>,
}

impl EnvVars {
    pub(crate) fn init<'mir, 'tcx>(
        ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
    ) {
        if ecx.machine.communicate {
            for (name, value) in std::env::vars() {
                let value = alloc_env_value(value.as_bytes(), ecx.memory_mut());
                ecx.machine.env_vars.map.insert(name.into_bytes(), value);
            }
        }
    }
}

fn alloc_env_value<'mir, 'tcx>(
    bytes: &[u8],
    memory: &mut Memory<'mir, 'tcx, Evaluator<'tcx>>,
) -> Pointer<Tag> {
    let tcx = {memory.tcx.tcx};
    let length = bytes.len() as u64;
    // `+1` for the null terminator.
    let ptr = memory.allocate(
        Size::from_bytes(length + 1),
        Align::from_bytes(1).unwrap(),
        MiriMemoryKind::Env.into(),
    );
    // We just allocated these, so the write cannot fail.
    let alloc = memory.get_mut(ptr.alloc_id).unwrap();
    alloc.write_bytes(&tcx, ptr, &bytes).unwrap();
    let trailing_zero_ptr = ptr.offset(
        Size::from_bytes(length),
        &tcx,
    ).unwrap();
    alloc.write_bytes(&tcx, trailing_zero_ptr, &[0]).unwrap();
    ptr
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn getenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, Scalar<Tag>> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let name = this.memory().read_c_str(name_ptr)?;
        Ok(match this.machine.env_vars.map.get(name) {
            Some(&var) => Scalar::Ptr(var),
            None => Scalar::ptr_null(&*this.tcx),
        })
    }

    fn setenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
        value_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let value_ptr = this.read_scalar(value_op)?.not_undef()?;
        let value = this.memory().read_c_str(value_ptr)?;
        let mut new = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?;
            if !name.is_empty() && !name.contains(&b'=') {
                new = Some((name.to_owned(), value.to_owned()));
            }
        }
        if let Some((name, value)) = new {
            let value_copy = alloc_env_value(&value, this.memory_mut());
            if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), value_copy) {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }

    fn unsetenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let mut success = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?.to_owned();
            if !name.is_empty() && !name.contains(&b'=') {
                success = Some(this.machine.env_vars.map.remove(&name));
            }
        }
        if let Some(old) = success {
            if let Some(var) = old {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }
}
<commit_msg>Write name and value for each env var<commit_after>use std::collections::HashMap;

use rustc::ty::layout::{Size, Align};
use rustc_mir::interpret::{Pointer, Memory};
use crate::stacked_borrows::Tag;
use crate::*;

#[derive(Default)]
pub struct EnvVars {
    map: HashMap<Vec<u8>, Pointer<Tag>>,
}

impl EnvVars {
    pub(crate) fn init<'mir, 'tcx>(
        ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
    ) {
        if ecx.machine.communicate {
            for (name, value) in std::env::vars() {
                let var_ptr = alloc_env_var(name.as_bytes(), value.as_bytes(), ecx.memory_mut());
                ecx.machine.env_vars.map.insert(name.into_bytes(), var_ptr);
            }
        }
    }
}

fn alloc_env_var<'mir, 'tcx>(
    name: &[u8],
    value: &[u8],
    memory: &mut Memory<'mir, 'tcx, Evaluator<'tcx>>,
) -> Pointer<Tag> {
    let bytes = [name, b"=", value].concat();
    let tcx = {memory.tcx.tcx};
    let length = bytes.len() as u64;
    // `+1` for the null terminator.
    let ptr = memory.allocate(
        Size::from_bytes(length + 1),
        Align::from_bytes(1).unwrap(),
        MiriMemoryKind::Env.into(),
    );
    // We just allocated these, so the write cannot fail.
    let alloc = memory.get_mut(ptr.alloc_id).unwrap();
    alloc.write_bytes(&tcx, ptr, &bytes).unwrap();
    let trailing_zero_ptr = ptr.offset(
        Size::from_bytes(length),
        &tcx,
    ).unwrap();
    alloc.write_bytes(&tcx, trailing_zero_ptr, &[0]).unwrap();
    ptr
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn getenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, Scalar<Tag>> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let name = this.memory().read_c_str(name_ptr)?;
        Ok(match this.machine.env_vars.map.get(name) {
            Some(var_ptr) => Scalar::Ptr(var_ptr.offset(Size::from_bytes(name.len() as u64 + 1), this)?),
            None => Scalar::ptr_null(&*this.tcx),
        })
    }

    fn setenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
        value_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let value_ptr = this.read_scalar(value_op)?.not_undef()?;
        let value = this.memory().read_c_str(value_ptr)?;
        let mut new = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?;
            if !name.is_empty() && !name.contains(&b'=') {
                new = Some((name.to_owned(), value.to_owned()));
            }
        }
        if let Some((name, value)) = new {
            let var_ptr = alloc_env_var(&name, &value, this.memory_mut());
            if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), var_ptr) {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }

    fn unsetenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let mut success = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?.to_owned();
            if !name.is_empty() && !name.contains(&b'=') {
                success = Some(this.machine.env_vars.map.remove(&name));
            }
        }
        if let Some(old) = success {
            if let Some(var) = old {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }
}
<|endoftext|>


<commit_before>extern crate structopt;

mod calculate;
mod measure;

use crate::calculate::Calculation;
use std::fmt::Display;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::exit;
use structopt::StructOpt;

#[derive(Clone, Debug, StructOpt)]
#[structopt(name = "performance", about = "performance regression testing runner")]
enum Opt {
    #[structopt(name = "measure")]
    Measure {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        projects_dir: PathBuf,
        #[structopt(short)]
        branch_name: String,
    },
    #[structopt(name = "calculate")]
    Calculate {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        results_dir: PathBuf,
    },
}

fn gracefully_exit_or<A, B, E: Display>(f: &dyn Fn(A) -> B, r: Result<A, E>) -> B {
    match r {
        Err(e) => {
            println!("{}", e);
            exit(1)
        },
        Ok(x) => f(x),
    }
}

// This is where all the printing, exiting, and error displaying
// should happen. Module functions should only return values.
fn main() {
    match Opt::from_args() {

        Opt::Measure { projects_dir, branch_name } => {
            let statuses = gracefully_exit_or(
                &|x| x,
                measure::measure(&projects_dir, &branch_name)
            );

            for status in statuses {
                match status.code() {
                    None => (),
                    Some(0) => (),
                    // if any child command exited with a non zero status code, exit with the same one here.
                    Some(nonzero) => {
                        println!("a child process exited with a nonzero status code.");
                        exit(nonzero)
                    },
                }
            }
        },

        Opt::Calculate { results_dir } => {
            let calculations = gracefully_exit_or(
                &|x| x,
                calculate::regressions(&results_dir)
            );

            // print calculations to stdout
            println!(":: All Calculations ::\n");
            for c in &calculations {
                println!("{:#?}\n", c);
            }
            println!("");

            // write calculations to file so it can be downloaded as an artifact
            let json_calcs = serde_json::to_string(&calculations)
                .expect("failed to serialize calculations to json");

            let outfile = &mut results_dir.into_os_string();
            outfile.push("/final_calculations.json");

            let mut f = File::create(outfile).expect("Unable to create file");
            f.write_all(json_calcs.as_bytes()).expect("unable to write data");

            // filter for regressions
            let regressions: Vec<Calculation> = calculations
                .into_iter()
                .filter(|c| c.regression)
                .collect();

            // exit with non zero exit code if there are regressions
            match regressions[..] {
                [] => println!("congrats! no regressions :)"),
                _ => {
                    println!(":: Regressions Found ::\n");
                    println!("");
                    for r in regressions {
                        println!("{:#?}\n", r);
                    }
                    println!("");
                    exit(1)
                }
            }
        },

    }
}
<commit_msg>make final json human readable<commit_after>extern crate structopt;

mod calculate;
mod measure;

use crate::calculate::Calculation;
use std::fmt::Display;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::exit;
use structopt::StructOpt;

#[derive(Clone, Debug, StructOpt)]
#[structopt(name = "performance", about = "performance regression testing runner")]
enum Opt {
    #[structopt(name = "measure")]
    Measure {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        projects_dir: PathBuf,
        #[structopt(short)]
        branch_name: String,
    },
    #[structopt(name = "calculate")]
    Calculate {
        #[structopt(parse(from_os_str))]
        #[structopt(short)]
        results_dir: PathBuf,
    },
}

fn gracefully_exit_or<A, B, E: Display>(f: &dyn Fn(A) -> B, r: Result<A, E>) -> B {
    match r {
        Err(e) => {
            println!("{}", e);
            exit(1)
        },
        Ok(x) => f(x),
    }
}

// This is where all the printing, exiting, and error displaying
// should happen. Module functions should only return values.
fn main() {
    match Opt::from_args() {

        Opt::Measure { projects_dir, branch_name } => {
            let statuses = gracefully_exit_or(
                &|x| x,
                measure::measure(&projects_dir, &branch_name)
            );

            for status in statuses {
                match status.code() {
                    None => (),
                    Some(0) => (),
                    // if any child command exited with a non zero status code, exit with the same one here.
                    Some(nonzero) => {
                        println!("a child process exited with a nonzero status code.");
                        exit(nonzero)
                    },
                }
            }
        },

        Opt::Calculate { results_dir } => {
            let calculations = gracefully_exit_or(
                &|x| x,
                calculate::regressions(&results_dir)
            );

            // print calculations to stdout
            println!(":: All Calculations ::\n");
            for c in &calculations {
                println!("{:#?}\n", c);
            }
            println!("");

            // write calculations to file so it can be downloaded as an artifact
            let json_calcs = serde_json::to_string_pretty(&calculations)
                .expect("failed to serialize calculations to json");

            let outfile = &mut results_dir.into_os_string();
            outfile.push("/final_calculations.json");

            let mut f = File::create(outfile).expect("Unable to create file");
            f.write_all(json_calcs.as_bytes()).expect("unable to write data");

            // filter for regressions
            let regressions: Vec<Calculation> = calculations
                .into_iter()
                .filter(|c| c.regression)
                .collect();

            // exit with non zero exit code if there are regressions
            match regressions[..] {
                [] => println!("congrats! no regressions :)"),
                _ => {
                    println!(":: Regressions Found ::\n");
                    println!("");
                    for r in regressions {
                        println!("{:#?}\n", r);
                    }
                    println!("");
                    exit(1)
                }
            }
        },

    }
}
<|endoftext|>


<commit_before>use std::ops::FnMut;

use ansi_term::Style;
use ansi_term::Colour::*;

pub struct LSColors<'var>(pub &'var str);

impl<'var> LSColors<'var> {
    pub fn each_pair<C>(&mut self, mut callback: C) where C: FnMut(Pair<'var>) -> () {
        for next in self.0.split(":") {
            let bits = next.split("=")
                           .take(3)
                           .collect::<Vec<_>>();

            if bits.len() == 2 && !bits[0].is_empty() && !bits[1].is_empty() {
                callback(Pair { key: bits[0], value: bits[1] });
            }
        }
    }
}

pub struct Pair<'var> {
    pub key: &'var str,
    pub value: &'var str,
}

impl<'var> Pair<'var> {
    pub fn to_style(&self) -> Style {
        let mut style = Style::default();

        for num in self.value.split(";") {
            match num {

                // Bold and italic
                "1"  => style = style.bold(),
                "4"  => style = style.underline(),

                // Foreground colours
                "30" => style = style.fg(Black),
                "31" => style = style.fg(Red),
                "32" => style = style.fg(Green),
                "33" => style = style.fg(Yellow),
                "34" => style = style.fg(Blue),
                "35" => style = style.fg(Purple),
                "36" => style = style.fg(Cyan),
                "37" => style = style.fg(White),

                // Background colours
                "40" => style = style.on(Black),
                "41" => style = style.on(Red),
                "42" => style = style.on(Green),
                "43" => style = style.on(Yellow),
                "44" => style = style.on(Blue),
                "45" => style = style.on(Purple),
                "46" => style = style.on(Cyan),
                "47" => style = style.on(White),
                 _    => {/* ignore the error and do nothing */},
            }
        }

        style
    }
}

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

    macro_rules! test {
        ($name:ident: $input:expr => $result:expr) => {
            #[test]
            fn $name() {
                assert_eq!(Pair { key: "", value: $input }.to_style(), $result);
            }
        };
    }

    // Styles
    test!(bold:  "1"         => Style::default().bold());
    test!(under: "4"         => Style::default().underline());
    test!(both:  "1;4"       => Style::default().bold().underline());
    test!(fg:    "31"        => Red.normal());
    test!(bg:    "43"        => Style::default().on(Yellow));
    test!(bfg:   "31;43"     => Red.on(Yellow));
    test!(all:   "43;31;1;4" => Red.on(Yellow).bold().underline());
    test!(again: "1;1;1;1;1" => Style::default().bold());

    // Failure cases
    test!(empty: ""          => Style::default());
    test!(semis: ";;;;;;"    => Style::default());
    test!(nines: "99999999"  => Style::default());
    test!(word:  "GREEN"     => Style::default());
}

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

    macro_rules! test {
        ($name:ident: $input:expr => $result:expr) => {
            #[test]
            fn $name() {
                let mut lscs = Vec::new();
                LSColors($input).each_pair(|p| lscs.push( (p.key.clone(), p.to_style()) ));
                assert_eq!(lscs, $result.to_vec());
            }
        };
    }

    // Bad parses
    test!(empty:    ""       => []);
    test!(jibber:   "blah"   => []);

    test!(equals:     "="    => []);
    test!(starts:     "=di"  => []);
    test!(ends:     "id="    => []);

    // Foreground colours
    test!(green:   "cb=32"   => [ ("cb", Green.normal()) ]);
    test!(red:     "di=31"   => [ ("di", Red.normal()) ]);
    test!(blue:    "la=34"   => [ ("la", Blue.normal()) ]);

    // Background colours
    test!(yellow:  "do=43"   => [ ("do", Style::default().on(Yellow)) ]);
    test!(purple:  "re=45"   => [ ("re", Style::default().on(Purple)) ]);
    test!(cyan:    "mi=46"   => [ ("mi", Style::default().on(Cyan)) ]);

    // Bold and underline
    test!(bold:    "fa=1"    => [ ("fa", Style::default().bold()) ]);
    test!(under:   "so=4"    => [ ("so", Style::default().underline()) ]);
    test!(both:    "la=1;4"  => [ ("la", Style::default().bold().underline()) ]);

    // More and many
    test!(more:  "me=43;21;55;34:yu=1;4;1"  => [ ("me", Blue.on(Yellow)), ("yu", Style::default().bold().underline()) ]);
    test!(many:  "red=31:green=32:blue=34"  => [ ("red", Red.normal()), ("green", Green.normal()), ("blue", Blue.normal()) ]);
}
<commit_msg>256 colour support in ls_colors<commit_after>use std::ops::FnMut;

use ansi_term::{Colour, Style};
use ansi_term::Colour::*;

pub struct LSColors<'var>(pub &'var str);

impl<'var> LSColors<'var> {
    pub fn each_pair<C>(&mut self, mut callback: C) where C: FnMut(Pair<'var>) -> () {
        for next in self.0.split(":") {
            let bits = next.split("=")
                           .take(3)
                           .collect::<Vec<_>>();

            if bits.len() == 2 && !bits[0].is_empty() && !bits[1].is_empty() {
                callback(Pair { key: bits[0], value: bits[1] });
            }
        }
    }
}

pub struct Pair<'var> {
    pub key: &'var str,
    pub value: &'var str,
}

use std::iter::Peekable;
fn parse_into_high_colour<'a, I>(iter: &mut Peekable<I>) -> Option<Colour>
where I: Iterator<Item=&'a str> {
    match iter.peek() {
        Some(&"5") => {
            let _5 = iter.next();
            if let Some(byte) = iter.next() {
                if let Ok(num) = byte.parse() {
                    return Some(Fixed(num));
                }
            }
        }
        _ => {},
    }

    None
}

impl<'var> Pair<'var> {
    pub fn to_style(&self) -> Style {
        let mut style = Style::default();
        let mut iter = self.value.split(";").peekable();

        while let Some(num) = iter.next() {
            match num {

                // Bold and italic
                "1"  => style = style.bold(),
                "4"  => style = style.underline(),

                // Foreground colours
                "30" => style = style.fg(Black),
                "31" => style = style.fg(Red),
                "32" => style = style.fg(Green),
                "33" => style = style.fg(Yellow),
                "34" => style = style.fg(Blue),
                "35" => style = style.fg(Purple),
                "36" => style = style.fg(Cyan),
                "37" => style = style.fg(White),
                "38" => if let Some(c) = parse_into_high_colour(&mut iter) { style = style.fg(c) },

                // Background colours
                "40" => style = style.on(Black),
                "41" => style = style.on(Red),
                "42" => style = style.on(Green),
                "43" => style = style.on(Yellow),
                "44" => style = style.on(Blue),
                "45" => style = style.on(Purple),
                "46" => style = style.on(Cyan),
                "47" => style = style.on(White),
                "48" => if let Some(c) = parse_into_high_colour(&mut iter) { style = style.on(c) },

                 _    => {/* ignore the error and do nothing */},
            }
        }

        style
    }
}

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

    macro_rules! test {
        ($name:ident: $input:expr => $result:expr) => {
            #[test]
            fn $name() {
                assert_eq!(Pair { key: "", value: $input }.to_style(), $result);
            }
        };
    }

    // Styles
    test!(bold:  "1"         => Style::default().bold());
    test!(under: "4"         => Style::default().underline());
    test!(both:  "1;4"       => Style::default().bold().underline());
    test!(fg:    "31"        => Red.normal());
    test!(bg:    "43"        => Style::default().on(Yellow));
    test!(bfg:   "31;43"     => Red.on(Yellow));
    test!(all:   "43;31;1;4" => Red.on(Yellow).bold().underline());
    test!(again: "1;1;1;1;1" => Style::default().bold());

    // Failure cases
    test!(empty: ""          => Style::default());
    test!(semis: ";;;;;;"    => Style::default());
    test!(nines: "99999999"  => Style::default());
    test!(word:  "GREEN"     => Style::default());

    // Higher colours
    test!(hifg:  "38;5;149"  => Fixed(149).normal());
    test!(hibg:  "48;5;1"    => Style::default().on(Fixed(1)));
    test!(hibo:  "48;5;1;1"  => Style::default().on(Fixed(1)).bold());
    test!(hiund: "4;48;5;1"  => Style::default().on(Fixed(1)).underline());

    test!(fgbg:  "38;5;121;48;5;212"  => Fixed(121).on(Fixed(212)));
    test!(bgfg:  "48;5;121;38;5;212"  => Fixed(212).on(Fixed(121)));
    test!(toohi: "48;5;999"           => Style::default());
}

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

    macro_rules! test {
        ($name:ident: $input:expr => $result:expr) => {
            #[test]
            fn $name() {
                let mut lscs = Vec::new();
                LSColors($input).each_pair(|p| lscs.push( (p.key.clone(), p.to_style()) ));
                assert_eq!(lscs, $result.to_vec());
            }
        };
    }

    // Bad parses
    test!(empty:    ""       => []);
    test!(jibber:   "blah"   => []);

    test!(equals:     "="    => []);
    test!(starts:     "=di"  => []);
    test!(ends:     "id="    => []);

    // Foreground colours
    test!(green:   "cb=32"   => [ ("cb", Green.normal()) ]);
    test!(red:     "di=31"   => [ ("di", Red.normal()) ]);
    test!(blue:    "la=34"   => [ ("la", Blue.normal()) ]);

    // Background colours
    test!(yellow:  "do=43"   => [ ("do", Style::default().on(Yellow)) ]);
    test!(purple:  "re=45"   => [ ("re", Style::default().on(Purple)) ]);
    test!(cyan:    "mi=46"   => [ ("mi", Style::default().on(Cyan)) ]);

    // Bold and underline
    test!(bold:    "fa=1"    => [ ("fa", Style::default().bold()) ]);
    test!(under:   "so=4"    => [ ("so", Style::default().underline()) ]);
    test!(both:    "la=1;4"  => [ ("la", Style::default().bold().underline()) ]);

    // More and many
    test!(more:  "me=43;21;55;34:yu=1;4;1"  => [ ("me", Blue.on(Yellow)), ("yu", Style::default().bold().underline()) ]);
    test!(many:  "red=31:green=32:blue=34"  => [ ("red", Red.normal()), ("green", Green.normal()), ("blue", Blue.normal()) ]);
}
<|endoftext|>


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

libc_bitflags!(
    pub struct EpollFlags: libc::c_int {
        EPOLLIN;
        EPOLLPRI;
        EPOLLOUT;
        EPOLLRDNORM;
        EPOLLRDBAND;
        EPOLLWRNORM;
        EPOLLWRBAND;
        EPOLLMSG;
        EPOLLERR;
        EPOLLHUP;
        EPOLLRDHUP;
        #[cfg(target_os = "linux")]  // Added in 4.5; not in Android.
        EPOLLEXCLUSIVE;
        #[cfg(not(target_arch = "mips"))]
        EPOLLWAKEUP;
        EPOLLONESHOT;
        EPOLLET;
    }
);

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(i32)]
pub enum EpollOp {
    EpollCtlAdd = libc::EPOLL_CTL_ADD,
    EpollCtlDel = libc::EPOLL_CTL_DEL,
    EpollCtlMod = libc::EPOLL_CTL_MOD,
}

libc_bitflags!{
    pub struct EpollCreateFlags: c_int {
        EPOLL_CLOEXEC;
    }
}

#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
    event: libc::epoll_event,
}

impl EpollEvent {
    pub fn new(events: EpollFlags, data: u64) -> Self {
        EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
    }

    pub fn empty() -> Self {
        unsafe { mem::zeroed::<EpollEvent>() }
    }

    pub fn events(&self) -> EpollFlags {
        EpollFlags::from_bits(self.event.events as libc::c_int).unwrap()
    }

    pub fn data(&self) -> u64 {
        self.event.u64
    }
}

impl<'a> Into<&'a mut EpollEvent> for Option<&'a mut EpollEvent> {
    #[inline]
    fn into(self) -> &'a mut EpollEvent {
        match self {
            Some(epoll_event) => epoll_event,
            None => unsafe { &mut *ptr::null_mut::<EpollEvent>() }
        }
    }
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
    let res = unsafe { libc::epoll_create(1024) };

    Errno::result(res)
}

#[inline]
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
    let res = unsafe { libc::epoll_create1(flags.bits()) };

    Errno::result(res)
}

#[inline]
pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
    where T: Into<&'a mut EpollEvent>
{
    let event: &mut EpollEvent = event.into();
    if event as *const EpollEvent == ptr::null() && op != EpollOp::EpollCtlDel {
        Err(Error::Sys(Errno::EINVAL))
    } else {
        let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
        Errno::result(res).map(drop)
    }
}

#[inline]
pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
    let res = unsafe {
        libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
    };

    Errno::result(res).map(|r| r as usize)
}
<commit_msg>Fix UB in epoll_ctl<commit_after>use {Errno, Result};
use libc::{self, c_int};
use std::os::unix::io::RawFd;
use std::ptr;
use std::mem;
use ::Error;

libc_bitflags!(
    pub struct EpollFlags: libc::c_int {
        EPOLLIN;
        EPOLLPRI;
        EPOLLOUT;
        EPOLLRDNORM;
        EPOLLRDBAND;
        EPOLLWRNORM;
        EPOLLWRBAND;
        EPOLLMSG;
        EPOLLERR;
        EPOLLHUP;
        EPOLLRDHUP;
        #[cfg(target_os = "linux")]  // Added in 4.5; not in Android.
        EPOLLEXCLUSIVE;
        #[cfg(not(target_arch = "mips"))]
        EPOLLWAKEUP;
        EPOLLONESHOT;
        EPOLLET;
    }
);

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(i32)]
pub enum EpollOp {
    EpollCtlAdd = libc::EPOLL_CTL_ADD,
    EpollCtlDel = libc::EPOLL_CTL_DEL,
    EpollCtlMod = libc::EPOLL_CTL_MOD,
}

libc_bitflags!{
    pub struct EpollCreateFlags: c_int {
        EPOLL_CLOEXEC;
    }
}

#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
    event: libc::epoll_event,
}

impl EpollEvent {
    pub fn new(events: EpollFlags, data: u64) -> Self {
        EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
    }

    pub fn empty() -> Self {
        unsafe { mem::zeroed::<EpollEvent>() }
    }

    pub fn events(&self) -> EpollFlags {
        EpollFlags::from_bits(self.event.events as libc::c_int).unwrap()
    }

    pub fn data(&self) -> u64 {
        self.event.u64
    }
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
    let res = unsafe { libc::epoll_create(1024) };

    Errno::result(res)
}

#[inline]
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
    let res = unsafe { libc::epoll_create1(flags.bits()) };

    Errno::result(res)
}

#[inline]
pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
    where T: Into<Option<&'a mut EpollEvent>>
{
    let mut event: Option<&mut EpollEvent> = event.into();
    if event.is_none() && op != EpollOp::EpollCtlDel {
        Err(Error::Sys(Errno::EINVAL))
    } else {
        let res = unsafe {
            if let Some(ref mut event) = event {
                libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event)
            } else {
                libc::epoll_ctl(epfd, op as c_int, fd, ptr::null_mut())
            }
        };
        Errno::result(res).map(drop)
    }
}

#[inline]
pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
    let res = unsafe {
        libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
    };

    Errno::result(res).map(|r| r as usize)
}
<|endoftext|>


<commit_before>/* TOOD: Implement for other kqueue based systems
 */

use {Errno, Result};
#[cfg(not(target_os = "netbsd"))]
use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
#[cfg(target_os = "netbsd")]
use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
use libc;
use std::os::unix::io::RawFd;
use std::ptr;
use std::mem;

// Redefine kevent in terms of programmer-friendly enums and bitfields.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct KEvent {
    kevent: libc::kevent,
}

#[cfg(any(target_os = "openbsd", target_os = "freebsd",
          target_os = "dragonfly", target_os = "macos"))]
type type_of_udata = *mut ::c_void;
#[cfg(any(target_os = "netbsd"))]
type type_of_udata = intptr_t;

#[cfg(not(target_os = "netbsd"))]
type type_of_event_filter = i16;
#[cfg(not(target_os = "netbsd"))]
#[repr(i16)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_AIO = libc::EVFILT_AIO,
    #[cfg(target_os = "dragonfly")]
    EVFILT_EXCEPT = libc::EVFILT_EXCEPT,
    #[cfg(any(target_os = "macos",
              target_os = "dragonfly",
              target_os = "freebsd"))]
    EVFILT_FS = libc::EVFILT_FS,
    #[cfg(target_os = "freebsd")]
    EVFILT_LIO = libc::EVFILT_LIO,
    #[cfg(target_os = "macos")]
    EVFILT_MACHPORT = libc::EVFILT_MACHPORT,
    EVFILT_PROC = libc::EVFILT_PROC,
    EVFILT_READ = libc::EVFILT_READ,
    EVFILT_SIGNAL = libc::EVFILT_SIGNAL,
    EVFILT_TIMER = libc::EVFILT_TIMER,
    #[cfg(any(target_os = "macos",
              target_os = "dragonfly",
              target_os = "freebsd"))]
    EVFILT_USER = libc::EVFILT_USER,
    #[cfg(target_os = "macos")]
    EVFILT_VM = libc::EVFILT_VM,
    EVFILT_VNODE = libc::EVFILT_VNODE,
    EVFILT_WRITE = libc::EVFILT_WRITE,
}

#[cfg(target_os = "netbsd")]
type type_of_event_filter = i32;
#[cfg(target_os = "netbsd")]
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_READ = libc::EVFILT_READ,
    EVFILT_WRITE = libc::EVFILT_WRITE,
    EVFILT_AIO = libc::EVFILT_AIO,
    EVFILT_VNODE = libc::EVFILT_VNODE,
    EVFILT_PROC = libc::EVFILT_PROC,
    EVFILT_SIGNAL = libc::EVFILT_SIGNAL,
    EVFILT_TIMER = libc::EVFILT_TIMER,
}

#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly"))]
pub type type_of_event_flag = u16;
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
pub type type_of_event_flag = u32;
libc_bitflags!{
    flags EventFlag: type_of_event_flag {
        EV_ADD,
        EV_CLEAR,
        EV_DELETE,
        EV_DISABLE,
        EV_DISPATCH,
        #[cfg(target_os = "freebsd")]
        EV_DROP,
        EV_ENABLE,
        EV_EOF,
        EV_ERROR,
        #[cfg(target_os = "macos")]
        EV_FLAG0,
        EV_FLAG1,
        #[cfg(target_os = "dragonfly")]
        EV_NODATA,
        EV_ONESHOT,
        #[cfg(target_os = "macos")]
        EV_OOBAND,
        #[cfg(target_os = "macos")]
        EV_POLL,
        #[cfg(not(target_os = "openbsd"))]
        EV_RECEIPT,
        EV_SYSFLAGS,
    }
}

bitflags!(
    flags FilterFlag: u32 {
        #[cfg(target_os = "macos")]
        const NOTE_ABSOLUTE                        = libc::NOTE_ABSOLUTE,
        const NOTE_ATTRIB                          = libc::NOTE_ATTRIB,
        const NOTE_CHILD                           = libc::NOTE_CHILD,
        const NOTE_DELETE                          = libc::NOTE_DELETE,
        #[cfg(target_os = "openbsd")]
        const NOTE_EOF                             = libc::NOTE_EOF,
        const NOTE_EXEC                            = libc::NOTE_EXEC,
        const NOTE_EXIT                            = libc::NOTE_EXIT,
        #[cfg(target_os = "macos")]
        const NOTE_EXIT_REPARENTED                 = libc::NOTE_EXIT_REPARENTED,
        #[cfg(target_os = "macos")]
        const NOTE_EXITSTATUS                      = libc::NOTE_EXITSTATUS,
        const NOTE_EXTEND                          = libc::NOTE_EXTEND,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFAND                           = libc::NOTE_FFAND,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFCOPY                          = libc::NOTE_FFCOPY,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFCTRLMASK                      = libc::NOTE_FFCTRLMASK,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFLAGSMASK                      = libc::NOTE_FFLAGSMASK,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFNOP                           = libc::NOTE_FFNOP,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFOR                            = libc::NOTE_FFOR,
        const NOTE_FORK                            = libc::NOTE_FORK,
        const NOTE_LINK                            = libc::NOTE_LINK,
        const NOTE_LOWAT                           = libc::NOTE_LOWAT,
        #[cfg(target_os = "freebsd")]
        const NOTE_MSECONDS                        = libc::NOTE_MSECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_NONE                            = libc::NOTE_NONE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_NSECONDS                        = libc::NOTE_NSECONDS,
        #[cfg(target_os = "dragonfly")]
        const NOTE_OOB                             = libc::NOTE_OOB,
        const NOTE_PCTRLMASK                       = libc::NOTE_PCTRLMASK,
        const NOTE_PDATAMASK                       = libc::NOTE_PDATAMASK,
        #[cfg(target_os = "macos")]
        const NOTE_REAP                            = libc::NOTE_REAP,
        const NOTE_RENAME                          = libc::NOTE_RENAME,
        const NOTE_REVOKE                          = libc::NOTE_REVOKE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_SECONDS                         = libc::NOTE_SECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_SIGNAL                          = libc::NOTE_SIGNAL,
        const NOTE_TRACK                           = libc::NOTE_TRACK,
        const NOTE_TRACKERR                        = libc::NOTE_TRACKERR,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_TRIGGER                         = libc::NOTE_TRIGGER,
        #[cfg(target_os = "openbsd")]
        const NOTE_TRUNCATE                        = libc::NOTE_TRUNCATE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_USECONDS                        = libc::NOTE_USECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_VM_ERROR                        = libc::NOTE_VM_ERROR,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE                     = libc::NOTE_VM_PRESSURE,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE_SUDDEN_TERMINATE    = libc::NOTE_VM_PRESSURE_SUDDEN_TERMINATE,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE_TERMINATE           = libc::NOTE_VM_PRESSURE_TERMINATE,
        const NOTE_WRITE                           = libc::NOTE_WRITE,
    }
);

pub fn kqueue() -> Result<RawFd> {
    let res = unsafe { libc::kqueue() };

    Errno::result(res)
}

// KEvent can't derive Send because on some operating systems, udata is defined
// as a void*.  However, KEvent's public API always treats udata as a uintptr_t,
// which is safe to Send.
unsafe impl Send for KEvent {
}

impl KEvent {
    pub fn new(ident: uintptr_t, filter: EventFilter, flags: EventFlag,
               fflags:FilterFlag, data: intptr_t, udata: uintptr_t) -> KEvent {
        KEvent { kevent: libc::kevent {
            ident: ident,
            filter: filter as type_of_event_filter,
            flags: flags.bits(),
            fflags: fflags.bits(),
            data: data,
            udata: udata as type_of_udata
        } }
    }

    pub fn ident(&self) -> uintptr_t {
        self.kevent.ident
    }

    pub fn filter(&self) -> EventFilter {
        unsafe { mem::transmute(self.kevent.filter as type_of_event_filter) }
    }

    pub fn flags(&self) -> EventFlag {
        EventFlag::from_bits(self.kevent.flags).unwrap()
    }

    pub fn fflags(&self) -> FilterFlag {
        FilterFlag::from_bits(self.kevent.fflags).unwrap()
    }

    pub fn data(&self) -> intptr_t {
        self.kevent.data
    }

    pub fn udata(&self) -> uintptr_t {
        self.kevent.udata as uintptr_t
    }
}

pub fn kevent(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_ms: usize) -> Result<usize> {

    // Convert ms to timespec
    let timeout = timespec {
        tv_sec: (timeout_ms / 1000) as time_t,
        tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
    };

    kevent_ts(kq, changelist, eventlist, Some(timeout))
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "openbsd"))]
type type_of_nchanges = c_int;
#[cfg(target_os = "netbsd")]
type type_of_nchanges = size_t;

pub fn kevent_ts(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_opt: Option<timespec>) -> Result<usize> {

    let res = unsafe {
        libc::kevent(
            kq,
            changelist.as_ptr() as *const libc::kevent,
            changelist.len() as type_of_nchanges,
            eventlist.as_mut_ptr() as *mut libc::kevent,
            eventlist.len() as type_of_nchanges,
            if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
    };

    Errno::result(res).map(|r| r as usize)
}

#[inline]
pub fn ev_set(ev: &mut KEvent,
              ident: usize,
              filter: EventFilter,
              flags: EventFlag,
              fflags: FilterFlag,
              udata: uintptr_t) {

    ev.kevent.ident  = ident as uintptr_t;
    ev.kevent.filter = filter as type_of_event_filter;
    ev.kevent.flags  = flags.bits();
    ev.kevent.fflags = fflags.bits();
    ev.kevent.data   = 0;
    ev.kevent.udata  = udata as type_of_udata;
}

#[test]
fn test_struct_kevent() {
    let udata : uintptr_t = 12345;

    let expected = libc::kevent{ident: 0xdeadbeef,
                                filter: libc::EVFILT_READ,
                                flags: libc::EV_DISPATCH | libc::EV_ADD,
                                fflags: libc::NOTE_CHILD | libc::NOTE_EXIT,
                                data: 0x1337,
                                udata: udata as type_of_udata};
    let actual = KEvent::new(0xdeadbeef,
                             EventFilter::EVFILT_READ,
                             EV_DISPATCH | EV_ADD,
                             NOTE_CHILD | NOTE_EXIT,
                             0x1337,
                             udata);
    assert!(expected.ident == actual.ident());
    assert!(expected.filter == actual.filter() as type_of_event_filter);
    assert!(expected.flags == actual.flags().bits());
    assert!(expected.fflags == actual.fflags().bits());
    assert!(expected.data == actual.data());
    assert!(expected.udata == actual.udata() as type_of_udata);
    assert!(mem::size_of::<libc::kevent>() == mem::size_of::<KEvent>());
}
<commit_msg>Change KEvent to treat udata as an intptr_t instead of a uintptr_t.<commit_after>/* TOOD: Implement for other kqueue based systems
 */

use {Errno, Result};
#[cfg(not(target_os = "netbsd"))]
use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
#[cfg(target_os = "netbsd")]
use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
use libc;
use std::os::unix::io::RawFd;
use std::ptr;
use std::mem;

// Redefine kevent in terms of programmer-friendly enums and bitfields.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct KEvent {
    kevent: libc::kevent,
}

#[cfg(any(target_os = "openbsd", target_os = "freebsd",
          target_os = "dragonfly", target_os = "macos"))]
type type_of_udata = *mut ::c_void;
#[cfg(any(target_os = "netbsd"))]
type type_of_udata = intptr_t;

#[cfg(not(target_os = "netbsd"))]
type type_of_event_filter = i16;
#[cfg(not(target_os = "netbsd"))]
#[repr(i16)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_AIO = libc::EVFILT_AIO,
    #[cfg(target_os = "dragonfly")]
    EVFILT_EXCEPT = libc::EVFILT_EXCEPT,
    #[cfg(any(target_os = "macos",
              target_os = "dragonfly",
              target_os = "freebsd"))]
    EVFILT_FS = libc::EVFILT_FS,
    #[cfg(target_os = "freebsd")]
    EVFILT_LIO = libc::EVFILT_LIO,
    #[cfg(target_os = "macos")]
    EVFILT_MACHPORT = libc::EVFILT_MACHPORT,
    EVFILT_PROC = libc::EVFILT_PROC,
    EVFILT_READ = libc::EVFILT_READ,
    EVFILT_SIGNAL = libc::EVFILT_SIGNAL,
    EVFILT_TIMER = libc::EVFILT_TIMER,
    #[cfg(any(target_os = "macos",
              target_os = "dragonfly",
              target_os = "freebsd"))]
    EVFILT_USER = libc::EVFILT_USER,
    #[cfg(target_os = "macos")]
    EVFILT_VM = libc::EVFILT_VM,
    EVFILT_VNODE = libc::EVFILT_VNODE,
    EVFILT_WRITE = libc::EVFILT_WRITE,
}

#[cfg(target_os = "netbsd")]
type type_of_event_filter = i32;
#[cfg(target_os = "netbsd")]
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EventFilter {
    EVFILT_READ = libc::EVFILT_READ,
    EVFILT_WRITE = libc::EVFILT_WRITE,
    EVFILT_AIO = libc::EVFILT_AIO,
    EVFILT_VNODE = libc::EVFILT_VNODE,
    EVFILT_PROC = libc::EVFILT_PROC,
    EVFILT_SIGNAL = libc::EVFILT_SIGNAL,
    EVFILT_TIMER = libc::EVFILT_TIMER,
}

#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly"))]
pub type type_of_event_flag = u16;
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
pub type type_of_event_flag = u32;
libc_bitflags!{
    flags EventFlag: type_of_event_flag {
        EV_ADD,
        EV_CLEAR,
        EV_DELETE,
        EV_DISABLE,
        EV_DISPATCH,
        #[cfg(target_os = "freebsd")]
        EV_DROP,
        EV_ENABLE,
        EV_EOF,
        EV_ERROR,
        #[cfg(target_os = "macos")]
        EV_FLAG0,
        EV_FLAG1,
        #[cfg(target_os = "dragonfly")]
        EV_NODATA,
        EV_ONESHOT,
        #[cfg(target_os = "macos")]
        EV_OOBAND,
        #[cfg(target_os = "macos")]
        EV_POLL,
        #[cfg(not(target_os = "openbsd"))]
        EV_RECEIPT,
        EV_SYSFLAGS,
    }
}

bitflags!(
    flags FilterFlag: u32 {
        #[cfg(target_os = "macos")]
        const NOTE_ABSOLUTE                        = libc::NOTE_ABSOLUTE,
        const NOTE_ATTRIB                          = libc::NOTE_ATTRIB,
        const NOTE_CHILD                           = libc::NOTE_CHILD,
        const NOTE_DELETE                          = libc::NOTE_DELETE,
        #[cfg(target_os = "openbsd")]
        const NOTE_EOF                             = libc::NOTE_EOF,
        const NOTE_EXEC                            = libc::NOTE_EXEC,
        const NOTE_EXIT                            = libc::NOTE_EXIT,
        #[cfg(target_os = "macos")]
        const NOTE_EXIT_REPARENTED                 = libc::NOTE_EXIT_REPARENTED,
        #[cfg(target_os = "macos")]
        const NOTE_EXITSTATUS                      = libc::NOTE_EXITSTATUS,
        const NOTE_EXTEND                          = libc::NOTE_EXTEND,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFAND                           = libc::NOTE_FFAND,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFCOPY                          = libc::NOTE_FFCOPY,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFCTRLMASK                      = libc::NOTE_FFCTRLMASK,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFLAGSMASK                      = libc::NOTE_FFLAGSMASK,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFNOP                           = libc::NOTE_FFNOP,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_FFOR                            = libc::NOTE_FFOR,
        const NOTE_FORK                            = libc::NOTE_FORK,
        const NOTE_LINK                            = libc::NOTE_LINK,
        const NOTE_LOWAT                           = libc::NOTE_LOWAT,
        #[cfg(target_os = "freebsd")]
        const NOTE_MSECONDS                        = libc::NOTE_MSECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_NONE                            = libc::NOTE_NONE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_NSECONDS                        = libc::NOTE_NSECONDS,
        #[cfg(target_os = "dragonfly")]
        const NOTE_OOB                             = libc::NOTE_OOB,
        const NOTE_PCTRLMASK                       = libc::NOTE_PCTRLMASK,
        const NOTE_PDATAMASK                       = libc::NOTE_PDATAMASK,
        #[cfg(target_os = "macos")]
        const NOTE_REAP                            = libc::NOTE_REAP,
        const NOTE_RENAME                          = libc::NOTE_RENAME,
        const NOTE_REVOKE                          = libc::NOTE_REVOKE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_SECONDS                         = libc::NOTE_SECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_SIGNAL                          = libc::NOTE_SIGNAL,
        const NOTE_TRACK                           = libc::NOTE_TRACK,
        const NOTE_TRACKERR                        = libc::NOTE_TRACKERR,
        #[cfg(any(target_os = "macos",
                  target_os = "freebsd",
                  target_os = "dragonfly"))]
        const NOTE_TRIGGER                         = libc::NOTE_TRIGGER,
        #[cfg(target_os = "openbsd")]
        const NOTE_TRUNCATE                        = libc::NOTE_TRUNCATE,
        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
        const NOTE_USECONDS                        = libc::NOTE_USECONDS,
        #[cfg(target_os = "macos")]
        const NOTE_VM_ERROR                        = libc::NOTE_VM_ERROR,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE                     = libc::NOTE_VM_PRESSURE,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE_SUDDEN_TERMINATE    = libc::NOTE_VM_PRESSURE_SUDDEN_TERMINATE,
        #[cfg(target_os = "macos")]
        const NOTE_VM_PRESSURE_TERMINATE           = libc::NOTE_VM_PRESSURE_TERMINATE,
        const NOTE_WRITE                           = libc::NOTE_WRITE,
    }
);

pub fn kqueue() -> Result<RawFd> {
    let res = unsafe { libc::kqueue() };

    Errno::result(res)
}

// KEvent can't derive Send because on some operating systems, udata is defined
// as a void*.  However, KEvent's public API always treats udata as an intptr_t,
// which is safe to Send.
unsafe impl Send for KEvent {
}

impl KEvent {
    pub fn new(ident: uintptr_t, filter: EventFilter, flags: EventFlag,
               fflags:FilterFlag, data: intptr_t, udata: intptr_t) -> KEvent {
        KEvent { kevent: libc::kevent {
            ident: ident,
            filter: filter as type_of_event_filter,
            flags: flags.bits(),
            fflags: fflags.bits(),
            data: data,
            udata: udata as type_of_udata
        } }
    }

    pub fn ident(&self) -> uintptr_t {
        self.kevent.ident
    }

    pub fn filter(&self) -> EventFilter {
        unsafe { mem::transmute(self.kevent.filter as type_of_event_filter) }
    }

    pub fn flags(&self) -> EventFlag {
        EventFlag::from_bits(self.kevent.flags).unwrap()
    }

    pub fn fflags(&self) -> FilterFlag {
        FilterFlag::from_bits(self.kevent.fflags).unwrap()
    }

    pub fn data(&self) -> intptr_t {
        self.kevent.data
    }

    pub fn udata(&self) -> intptr_t {
        self.kevent.udata as intptr_t
    }
}

pub fn kevent(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_ms: usize) -> Result<usize> {

    // Convert ms to timespec
    let timeout = timespec {
        tv_sec: (timeout_ms / 1000) as time_t,
        tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
    };

    kevent_ts(kq, changelist, eventlist, Some(timeout))
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "openbsd"))]
type type_of_nchanges = c_int;
#[cfg(target_os = "netbsd")]
type type_of_nchanges = size_t;

pub fn kevent_ts(kq: RawFd,
              changelist: &[KEvent],
              eventlist: &mut [KEvent],
              timeout_opt: Option<timespec>) -> Result<usize> {

    let res = unsafe {
        libc::kevent(
            kq,
            changelist.as_ptr() as *const libc::kevent,
            changelist.len() as type_of_nchanges,
            eventlist.as_mut_ptr() as *mut libc::kevent,
            eventlist.len() as type_of_nchanges,
            if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
    };

    Errno::result(res).map(|r| r as usize)
}

#[inline]
pub fn ev_set(ev: &mut KEvent,
              ident: usize,
              filter: EventFilter,
              flags: EventFlag,
              fflags: FilterFlag,
              udata: intptr_t) {

    ev.kevent.ident  = ident as uintptr_t;
    ev.kevent.filter = filter as type_of_event_filter;
    ev.kevent.flags  = flags.bits();
    ev.kevent.fflags = fflags.bits();
    ev.kevent.data   = 0;
    ev.kevent.udata  = udata as type_of_udata;
}

#[test]
fn test_struct_kevent() {
    let udata : intptr_t = 12345;

    let expected = libc::kevent{ident: 0xdeadbeef,
                                filter: libc::EVFILT_READ,
                                flags: libc::EV_DISPATCH | libc::EV_ADD,
                                fflags: libc::NOTE_CHILD | libc::NOTE_EXIT,
                                data: 0x1337,
                                udata: udata as type_of_udata};
    let actual = KEvent::new(0xdeadbeef,
                             EventFilter::EVFILT_READ,
                             EV_DISPATCH | EV_ADD,
                             NOTE_CHILD | NOTE_EXIT,
                             0x1337,
                             udata);
    assert!(expected.ident == actual.ident());
    assert!(expected.filter == actual.filter() as type_of_event_filter);
    assert!(expected.flags == actual.flags().bits());
    assert!(expected.fflags == actual.fflags().bits());
    assert!(expected.data == actual.data());
    assert!(expected.udata == actual.udata() as type_of_udata);
    assert!(mem::size_of::<libc::kevent>() == mem::size_of::<KEvent>());
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::path::PathBuf;
use std::sync::Once;
use std::thread;

fn root() -> PathBuf {
    env::current_dir()
        .unwrap()
        .join("tmp")
        .join("tests")
        .join(thread::current().name().unwrap())
}

pub fn bare() -> PathBuf {
    root().join("bare")
}

pub fn init() {
    static INIT: Once = Once::new();
    let _ = fs::remove_dir_all(&bare());

    INIT.call_once(|| {
        fs::create_dir_all(root().parent().unwrap()).unwrap();
    });

    let bare = git2::Repository::init_bare(&bare()).unwrap();
    let mut config = bare.config().unwrap();
    config.set_str("user.name", "name").unwrap();
    config.set_str("user.email", "email").unwrap();
    let mut index = bare.index().unwrap();
    let id = index.write_tree().unwrap();
    let tree = bare.find_tree(id).unwrap();
    let sig = bare.signature().unwrap();
    bare.commit(Some("HEAD"), &sig, &sig, "Initial Commit", &tree, &[])
        .unwrap();
}
<commit_msg>Auto merge of #4017 - pietroalbini:ensure-test-git-index-branch, r=Turbo87<commit_after>use std::env;
use std::fs;
use std::path::PathBuf;
use std::sync::Once;
use std::thread;

fn root() -> PathBuf {
    env::current_dir()
        .unwrap()
        .join("tmp")
        .join("tests")
        .join(thread::current().name().unwrap())
}

pub fn bare() -> PathBuf {
    root().join("bare")
}

pub fn init() {
    static INIT: Once = Once::new();
    let _ = fs::remove_dir_all(&bare());

    INIT.call_once(|| {
        fs::create_dir_all(root().parent().unwrap()).unwrap();
    });

    let bare = git2::Repository::init_opts(
        &bare(),
        git2::RepositoryInitOptions::new()
            .bare(true)
            .initial_head("master"),
    )
    .unwrap();
    let mut config = bare.config().unwrap();
    config.set_str("user.name", "name").unwrap();
    config.set_str("user.email", "email").unwrap();
    let mut index = bare.index().unwrap();
    let id = index.write_tree().unwrap();
    let tree = bare.find_tree(id).unwrap();
    let sig = bare.signature().unwrap();
    bare.commit(Some("HEAD"), &sig, &sig, "Initial Commit", &tree, &[])
        .unwrap();
}
<|endoftext|>


<commit_before>use toml::Parser;
use regex::Regex;
use std::io::prelude::*;
use std::fs::File;
use std::io::Error;
use std::fs::OpenOptions;

#[derive(Debug)]
pub enum TomlError {
    parseError(&'static str),
    ioError(Error)
}

pub fn read_version(file: String) -> Option<String> {
   let file_map = Parser::new(&file).parse().unwrap();
   let package = file_map.get("package").unwrap();
   let version = package.as_table()
       .unwrap()
       .get("version");
   match version {
       Some(v) => Some(v.as_str().unwrap().into()),
       None => None
   }
}

pub fn file_with_new_version(file: String, new_version: &str) -> String {
    let re = Regex::new(r#"version\s=\s"\d+\.\d+\.\d+""#).unwrap();
    let new_version = format!("version = \"{}\"", new_version);
    re.replace(&file, &new_version[..])
}

pub fn read_from_file() -> Result<String, TomlError> {
    let cargo_file = match read_cargo_toml() {
        Ok(buffer) => buffer,
        Err(err) => return Err(TomlError::ioError(err))
    };

    match read_version(cargo_file) {
        Some(version) => Ok(version),
        None => Err(TomlError::parseError("No version field found"))
    }
}

pub fn write_new_version(new_version: String) -> Result<(), Error> {
    let cargo_toml = try!(read_cargo_toml());
    let new_cargo_toml = file_with_new_version(cargo_toml, &new_version);
    let mut handle = try!(OpenOptions::new().read(true).write(true).open("Cargo.toml"));
    handle.write_all(new_cargo_toml.as_bytes())
}

fn read_cargo_toml() -> Result<String, Error> {
    let mut handle = match File::open("Cargo.toml") {
        Ok(handle) => handle,
        Err(err) => {
            return Err(err)
        }
    };

    let mut buffer = String::new();
    match handle.read_to_string(&mut buffer) {
        Ok(_) => Ok(buffer),
        Err(err) => Err(err)
    }
}

#[cfg(test)]
mod tests {
    extern crate toml;
    extern crate regex;
    use super::*;

    fn example_file() -> String {
        "[package]
    name = \"semantic-rs\"
    version = \"0.1.0\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string()
    }

    fn example_file_without_version() -> String {
        "[package]
    name = \"semantic-rs\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string()
    }

    #[test]
    fn read_version_number() {
        let version_str = read_version(example_file());
        assert_eq!(version_str, Some("0.1.0".into()));
    }

    #[test]
    fn read_file_without_version_number() {
        let version_str = read_version(example_file_without_version());
        assert_eq!(version_str, None);
    }

    #[test]
    fn write_new_version_number() {
        let new_toml_file = file_with_new_version(example_file(), "0.2.0".into());
        let expected_file =
            "[package]
    name = \"semantic-rs\"
    version = \"0.2.0\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string();
        assert_eq!(new_toml_file, expected_file);
    }
}
<commit_msg>refactor(toml_file): Fix enum member naming<commit_after>use toml::Parser;
use regex::Regex;
use std::io::prelude::*;
use std::fs::File;
use std::io::Error;
use std::fs::OpenOptions;

#[derive(Debug)]
pub enum TomlError {
    ParseError(&'static str),
    IoError(Error)
}

pub fn read_version(file: String) -> Option<String> {
   let file_map = Parser::new(&file).parse().unwrap();
   let package = file_map.get("package").unwrap();
   let version = package.as_table()
       .unwrap()
       .get("version");
   match version {
       Some(v) => Some(v.as_str().unwrap().into()),
       None => None
   }
}

pub fn file_with_new_version(file: String, new_version: &str) -> String {
    let re = Regex::new(r#"version\s=\s"\d+\.\d+\.\d+""#).unwrap();
    let new_version = format!("version = \"{}\"", new_version);
    re.replace(&file, &new_version[..])
}

pub fn read_from_file() -> Result<String, TomlError> {
    let cargo_file = match read_cargo_toml() {
        Ok(buffer) => buffer,
        Err(err) => return Err(TomlError::IoError(err))
    };

    match read_version(cargo_file) {
        Some(version) => Ok(version),
        None => Err(TomlError::ParseError("No version field found"))
    }
}

pub fn write_new_version(new_version: String) -> Result<(), Error> {
    let cargo_toml = try!(read_cargo_toml());
    let new_cargo_toml = file_with_new_version(cargo_toml, &new_version);
    let mut handle = try!(OpenOptions::new().read(true).write(true).open("Cargo.toml"));
    handle.write_all(new_cargo_toml.as_bytes())
}

fn read_cargo_toml() -> Result<String, Error> {
    let mut handle = match File::open("Cargo.toml") {
        Ok(handle) => handle,
        Err(err) => {
            return Err(err)
        }
    };

    let mut buffer = String::new();
    match handle.read_to_string(&mut buffer) {
        Ok(_) => Ok(buffer),
        Err(err) => Err(err)
    }
}

#[cfg(test)]
mod tests {
    extern crate toml;
    extern crate regex;
    use super::*;

    fn example_file() -> String {
        "[package]
    name = \"semantic-rs\"
    version = \"0.1.0\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string()
    }

    fn example_file_without_version() -> String {
        "[package]
    name = \"semantic-rs\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string()
    }

    #[test]
    fn read_version_number() {
        let version_str = read_version(example_file());
        assert_eq!(version_str, Some("0.1.0".into()));
    }

    #[test]
    fn read_file_without_version_number() {
        let version_str = read_version(example_file_without_version());
        assert_eq!(version_str, None);
    }

    #[test]
    fn write_new_version_number() {
        let new_toml_file = file_with_new_version(example_file(), "0.2.0".into());
        let expected_file =
            "[package]
    name = \"semantic-rs\"
    version = \"0.2.0\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string();
        assert_eq!(new_toml_file, expected_file);
    }
}
<|endoftext|>


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

use std::gc::Gc;
use syntax::ast::TokenTree;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::{ToTokens, ExtParseUtils};

use node;
use super::PlatformContext;

/// Entry point for parsing an mcu node.
///
/// Arguments:
///   pcx:   PlatformContext, used to generate any static items in
///          mod platformtree
///   ecx:   ExtCtxt for building ASTs
///   nodes: a vector of nodes inside of the mcu node.
pub fn process_nodes(pcx: &mut PlatformContext, ecx: &ExtCtxt, nodes: &Vec<Gc<node::Node>>) {
  for n in nodes.iter() {
    let path = n.path.path.get(0).as_slice();
    match path {
      "clock" => process_clock(pcx, ecx, n),
      other => ecx.span_err(
          n.path.span.unwrap(),
          format!("unknown subnode `{}` in lpc17xx mcu", other).as_slice()),
    }
  }
}

/// A simple wrapper to allow custom tokenization of ClockSource
struct TokenSource {
  pub s: String,
}

impl ToTokens for TokenSource {
  fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
    (cx as &ExtParseUtils).parse_tts(self.s.clone())
  }
}

/// Parses @clock node into pll init code.
fn process_clock(pcx: &mut PlatformContext, ecx: &ExtCtxt, node: &Gc<node::Node>) {
  if node.path.path.len() != 1 {
    ecx.span_err(node.path.span.unwrap(), "node lpc17xx::clock is final");
    return
  }

  let some_source = node.unwrap_string(ecx, "source");
  let some_pll_m = node.unwrap_int(ecx, "pll_m");
  let some_pll_n = node.unwrap_int(ecx, "pll_n");
  let some_pll_divisor = node.unwrap_int(ecx, "pll_divisor");

  if some_source == None || some_pll_m == None || some_pll_m == None ||
      some_pll_divisor == None {
    return
  }

  let source = some_source.unwrap();
  let pll_m = some_pll_m.unwrap();
  let pll_n = some_pll_n.unwrap();
  let pll_divisor = some_pll_divisor.unwrap();

  let token_source = TokenSource { s: match source.as_slice() {
    "internal-oscillator" => "zinc::hal::lpc17xx::init::Internal".to_str(),
    "main-oscillator"     => {
      let source_frequency = node.unwrap_int(ecx, "source_frequency");
      if source_frequency == None {
        return
      }
      format!("zinc::hal::lpc17xx::init::Main({})", source_frequency)
    }
    "rtc-oscillator"      => "zinc::hal::lpc17xx::init::RTC".to_str(),
    other => {
      ecx.span_err(
          node.path.span.unwrap(), // TODO: span
          format!("unknown oscillator value `{}`", other).as_slice());
      return
    },
  }};

  let ex = quote_expr!(&*ecx,
      zinc::hal::lpc17xx::init::init_clock(
          zinc::hal::lpc17xx::init::Clock {
            source: $token_source,
            pll: zinc::hal::lpc17xx::init::PLL0 {
              enabled: true,
              m: $pll_m,
              n: $pll_n,
              divisor: $pll_divisor,
            }
          }
      );
  );
  pcx.add_main_statement(ecx.stmt_expr(ex));
}
<commit_msg>Renamed TokenSource to ClockSource.<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::gc::Gc;
use syntax::ast::TokenTree;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::{ToTokens, ExtParseUtils};

use node;
use super::PlatformContext;

/// Entry point for parsing an mcu node.
///
/// Arguments:
///   pcx:   PlatformContext, used to generate any static items in
///          mod platformtree
///   ecx:   ExtCtxt for building ASTs
///   nodes: a vector of nodes inside of the mcu node.
pub fn process_nodes(pcx: &mut PlatformContext, ecx: &ExtCtxt, nodes: &Vec<Gc<node::Node>>) {
  for n in nodes.iter() {
    let path = n.path.path.get(0).as_slice();
    match path {
      "clock" => process_clock(pcx, ecx, n),
      other => ecx.span_err(
          n.path.span.unwrap(),
          format!("unknown subnode `{}` in lpc17xx mcu", other).as_slice()),
    }
  }
}

/// A simple wrapper to allow custom tokenization of ClockSource
struct ClockSource {
  pub s: String,
}

impl ClockSource {
  pub fn new(s: String) -> ClockSource {
    ClockSource {
      s: s,
    }
  }
}

impl ToTokens for ClockSource {
  fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
    (cx as &ExtParseUtils).parse_tts(self.s.clone())
  }
}

/// Parses @clock node into pll init code.
fn process_clock(pcx: &mut PlatformContext, ecx: &ExtCtxt, node: &Gc<node::Node>) {
  if node.path.path.len() != 1 {
    ecx.span_err(node.path.span.unwrap(), "node lpc17xx::clock is final");
    return
  }

  let some_source = node.unwrap_string(ecx, "source");
  let some_pll_m = node.unwrap_int(ecx, "pll_m");
  let some_pll_n = node.unwrap_int(ecx, "pll_n");
  let some_pll_divisor = node.unwrap_int(ecx, "pll_divisor");

  if some_source == None || some_pll_m == None || some_pll_m == None ||
      some_pll_divisor == None {
    return
  }

  let source = some_source.unwrap();
  let pll_m = some_pll_m.unwrap();
  let pll_n = some_pll_n.unwrap();
  let pll_divisor = some_pll_divisor.unwrap();

    "internal-oscillator" => "zinc::hal::lpc17xx::init::Internal".to_str(),
  let clock_source = ClockSource::new(match source.as_slice() {
    "main-oscillator"     => {
      let source_frequency = node.unwrap_int(ecx, "source_frequency");
      if source_frequency == None {
        return
      }
      format!("zinc::hal::lpc17xx::init::Main({})", source_frequency)
    }
    "rtc-oscillator"      => "zinc::hal::lpc17xx::init::RTC".to_str(),
    other => {
      ecx.span_err(
          node.path.span.unwrap(), // TODO: span
          format!("unknown oscillator value `{}`", other).as_slice());
      return
    },
  });

  let ex = quote_expr!(&*ecx,
      zinc::hal::lpc17xx::init::init_clock(
          zinc::hal::lpc17xx::init::Clock {
            source: $token_source,
            pll: zinc::hal::lpc17xx::init::PLL0 {
              enabled: true,
              m: $pll_m,
              n: $pll_n,
              divisor: $pll_divisor,
            }
          }
      );
  );
  pcx.add_main_statement(ecx.stmt_expr(ex));
}
<|endoftext|>


<commit_before>use num::Num;
use length::length_values;

#[inline(always)]
pub fn transform_mat3<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], m: [T; 9]) -> &'a mut [T; 3] {
    out[0] = a[0] * m[0] + a[1] * m[3] + a[2] * m[6];
    out[1] = a[0] * m[1] + a[1] * m[4] + a[2] * m[7];
    out[2] = a[0] * m[2] + a[1] * m[5] + a[2] * m[8];
    out
}

#[inline(always)]
pub fn transform_mat4<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], m: [T; 16]) -> &'a mut [T; 3] {
    out[0] = a[0] * m[0] + a[1] * m[4] + a[2] * m[8] + m[12];
    out[1] = a[0] * m[1] + a[1] * m[5] + a[2] * m[9] + m[13];
    out[2] = a[0] * m[2] + a[1] * m[6] + a[2] * m[10] + m[14];
    out
}

#[inline(always)]
pub fn transform_mat4_rotation<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], m: [T; 16]) -> &'a mut [T; 3] {
    out[0] = a[0] * m[0] + a[1] * m[4] + a[2] * m[8];
    out[1] = a[0] * m[1] + a[1] * m[5] + a[2] * m[9];
    out[2] = a[0] * m[2] + a[1] * m[6] + a[2] * m[10];
    out
}

#[inline(always)]
pub fn transform_projection<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], m: [T; 16]) -> &'a mut [T; 3] {
    let mut d = a[0] * m[3] + a[1] * m[7] + a[2] * m[11] + m[15];
    d = if d != T::zero() {T::one() / d} else {d};

    out[0] = (a[0] * m[0] + a[1] * m[4] + a[2] * m[8] + m[12]) * d;
    out[1] = (a[0] * m[1] + a[1] * m[5] + a[2] * m[9] + m[13]) * d;
    out[2] = (a[0] * m[2] + a[1] * m[6] + a[2] * m[10] + m[14]) * d;
    out
}

#[inline(always)]
pub fn transform_projection_no_position<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], m: [T; 16]) -> &'a mut [T; 3] {
    let mut d = a[0] * m[3] + a[1] * m[7] + a[2] * m[11] + m[15];
    d = if d != T::zero() {T::one() / d} else {d};

    out[0] = (a[0] * m[0] + a[1] * m[4] + a[2] * m[8]) * d;
    out[1] = (a[0] * m[1] + a[1] * m[5] + a[2] * m[9]) * d;
    out[2] = (a[0] * m[2] + a[1] * m[6] + a[2] * m[10]) * d;
    out
}

#[inline(always)]
pub fn transform_quat<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], q: [T; 4]) -> &'a mut [T; 3] {
    let ix = q[3] * a[0] + q[1] * a[2] - q[2] * a[1];
    let iy = q[3] * a[1] + q[2] * a[0] - q[0] * a[2];
    let iz = q[3] * a[2] + q[0] * a[1] - q[1] * a[0];
    let iw = -q[0] * a[0] - q[1] * a[1] - q[2] * a[2];

    out[0] = ix * q[3] + iw * -q[0] + iy * -q[2] - iz * -q[1];
    out[1] = iy * q[3] + iw * -q[1] + iz * -q[0] - ix * -q[2];
    out[2] = iz * q[3] + iw * -q[2] + ix * -q[1] - iy * -q[0];
    out
}

#[inline(always)]
pub fn position_mat32<'a, 'b, T: Num>(out: &'a mut [T; 3], m: [T; 6]) -> &'a mut [T; 3] {
    out[0] = m[4];
    out[1] = m[5];
    out
}

#[inline(always)]
pub fn position_mat4<'a, 'b, T: Num>(out: &'a mut [T; 3], m: [T; 16]) -> &'a mut [T; 3] {
    out[0] = m[12];
    out[1] = m[13];
    out[2] = m[14];
    out
}

#[inline(always)]
pub fn scale_mat2<'a, 'b, T: Num>(out: &'a mut [T; 3], m: [T; 4]) -> &'a mut [T; 3] {
    out[0] = length_values(m[0], m[2], T::zero());
    out[1] = length_values(m[1], m[3], T::zero());
    out[2] = T::one();
    out
}

#[inline(always)]
pub fn scale_mat32<'a, 'b, T: Num>(out: &'a mut [T; 3], m: [T; 6]) -> &'a mut [T; 3] {
    out[0] = length_values(m[0], m[2], T::zero());
    out[1] = length_values(m[1], m[3], T::zero());
    out[2] = T::one();
    out
}

#[inline(always)]
pub fn scale_mat3<'a, 'b, T: Num>(out: &'a mut [T; 3], m: [T; 9]) -> &'a mut [T; 3] {
    out[0] = length_values(m[0], m[3], m[6]);
    out[1] = length_values(m[1], m[4], m[7]);
    out[2] = length_values(m[2], m[5], m[8]);
    out
}

#[inline(always)]
pub fn scale_mat4<'a, 'b, T: Num>(out: &'a mut [T; 3], m: [T; 16]) -> &'a mut [T; 3] {
    out[0] = length_values(m[0], m[4], m[8]);
    out[1] = length_values(m[1], m[5], m[9]);
    out[2] = length_values(m[2], m[6], m[10]);
    out
}
<commit_msg>updates<commit_after>use num::Num;
use length::length_values;

#[inline(always)]
pub fn transform_mat3<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], m: &'b [T; 9]) -> &'a mut [T; 3] {
    out[0] = a[0] * m[0] + a[1] * m[3] + a[2] * m[6];
    out[1] = a[0] * m[1] + a[1] * m[4] + a[2] * m[7];
    out[2] = a[0] * m[2] + a[1] * m[5] + a[2] * m[8];
    out
}

#[inline(always)]
pub fn transform_mat4<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], m: &'b [T; 16]) -> &'a mut [T; 3] {
    out[0] = a[0] * m[0] + a[1] * m[4] + a[2] * m[8] + m[12];
    out[1] = a[0] * m[1] + a[1] * m[5] + a[2] * m[9] + m[13];
    out[2] = a[0] * m[2] + a[1] * m[6] + a[2] * m[10] + m[14];
    out
}

#[inline(always)]
pub fn transform_mat4_rotation<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], m: &'b [T; 16]) -> &'a mut [T; 3] {
    out[0] = a[0] * m[0] + a[1] * m[4] + a[2] * m[8];
    out[1] = a[0] * m[1] + a[1] * m[5] + a[2] * m[9];
    out[2] = a[0] * m[2] + a[1] * m[6] + a[2] * m[10];
    out
}

#[inline(always)]
pub fn transform_projection<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], m: &'b [T; 16]) -> &'a mut [T; 3] {
    let mut d = a[0] * m[3] + a[1] * m[7] + a[2] * m[11] + m[15];
    d = if d != T::zero() {T::one() / d} else {d};

    out[0] = (a[0] * m[0] + a[1] * m[4] + a[2] * m[8] + m[12]) * d;
    out[1] = (a[0] * m[1] + a[1] * m[5] + a[2] * m[9] + m[13]) * d;
    out[2] = (a[0] * m[2] + a[1] * m[6] + a[2] * m[10] + m[14]) * d;
    out
}

#[inline(always)]
pub fn transform_projection_no_position<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], m: &'b [T; 16]) -> &'a mut [T; 3] {
    let mut d = a[0] * m[3] + a[1] * m[7] + a[2] * m[11] + m[15];
    d = if d != T::zero() {T::one() / d} else {d};

    out[0] = (a[0] * m[0] + a[1] * m[4] + a[2] * m[8]) * d;
    out[1] = (a[0] * m[1] + a[1] * m[5] + a[2] * m[9]) * d;
    out[2] = (a[0] * m[2] + a[1] * m[6] + a[2] * m[10]) * d;
    out
}

#[inline(always)]
pub fn transform_quat<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3], q: &'b [T; 4]) -> &'a mut [T; 3] {
    let ix = q[3] * a[0] + q[1] * a[2] - q[2] * a[1];
    let iy = q[3] * a[1] + q[2] * a[0] - q[0] * a[2];
    let iz = q[3] * a[2] + q[0] * a[1] - q[1] * a[0];
    let iw = -q[0] * a[0] - q[1] * a[1] - q[2] * a[2];

    out[0] = ix * q[3] + iw * -q[0] + iy * -q[2] - iz * -q[1];
    out[1] = iy * q[3] + iw * -q[1] + iz * -q[0] - ix * -q[2];
    out[2] = iz * q[3] + iw * -q[2] + ix * -q[1] - iy * -q[0];
    out
}

#[inline(always)]
pub fn position_mat32<'a, 'b, T: Num>(out: &'a mut [T; 3], m: &'b [T; 6]) -> &'a mut [T; 3] {
    out[0] = m[4];
    out[1] = m[5];
    out
}

#[inline(always)]
pub fn position_mat4<'a, 'b, T: Num>(out: &'a mut [T; 3], m: &'b [T; 16]) -> &'a mut [T; 3] {
    out[0] = m[12];
    out[1] = m[13];
    out[2] = m[14];
    out
}

#[inline(always)]
pub fn scale_mat2<'a, 'b, T: Num>(out: &'a mut [T; 3], m: &'b [T; 4]) -> &'a mut [T; 3] {
    out[0] = length_values(m[0], m[2], T::zero());
    out[1] = length_values(m[1], m[3], T::zero());
    out[2] = T::one();
    out
}

#[inline(always)]
pub fn scale_mat32<'a, 'b, T: Num>(out: &'a mut [T; 3], m: &'b [T; 6]) -> &'a mut [T; 3] {
    out[0] = length_values(m[0], m[2], T::zero());
    out[1] = length_values(m[1], m[3], T::zero());
    out[2] = T::one();
    out
}

#[inline(always)]
pub fn scale_mat3<'a, 'b, T: Num>(out: &'a mut [T; 3], m: &'b [T; 9]) -> &'a mut [T; 3] {
    out[0] = length_values(m[0], m[3], m[6]);
    out[1] = length_values(m[1], m[4], m[7]);
    out[2] = length_values(m[2], m[5], m[8]);
    out
}

#[inline(always)]
pub fn scale_mat4<'a, 'b, T: Num>(out: &'a mut [T; 3], m: &'b [T; 16]) -> &'a mut [T; 3] {
    out[0] = length_values(m[0], m[4], m[8]);
    out[1] = length_values(m[1], m[5], m[9]);
    out[2] = length_values(m[2], m[6], m[10]);
    out
}
<|endoftext|>