<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Kernel memory management.
//!
//! This module contains all of the non-arch-specific paging code, and
//! re-exports memory-related definitions.
use alloc::buddy;

use core::{ops, convert};

pub use arch::memory::{PAddr, HEAP_BASE, HEAP_TOP, PAGE_SHIFT, PAGE_SIZE};

pub mod paging;
#[macro_use] pub mod macros;

/// A virtual address is a machine-sized unsigned integer
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct VAddr(usize);

pub trait Addr: ops::Add<Self> + ops::Sub<Self>
              + ops::Mul<Self> + ops::Div<Self>
              + ops::Shl<Self> + ops::Shr<Self>
              + convert::From<*mut u8> + convert::From<*const u8>
              + Sized {
    type Repr;
}

derive_addr! { VAddr, usize }

impl VAddr {
    #[inline] pub fn from_ptr<T>(ptr: *mut T) -> Self { VAddr(ptr as usize) }
    #[inline] pub const fn from_usize(u: usize) -> Self { VAddr(u) }
    #[inline] pub const fn as_usize(&self) -> usize { self.0 }

    /// Calculate the index in the PML4 table corresponding to this address.
    #[inline] pub fn pml4_index(&self) -> usize {
        (self >> 39) & 0b111111111
    }

    /// Calculate the index in the PDPT table corresponding to this address.
    #[inline] pub fn pdpt_index(&self) -> usize {
        (self >> 30) & 0b111111111
    }

    /// Calculate the index in the PD table corresponding to this address.
    #[inline] pub fn pd_index(&self) -> usize {
        (self >> 21) & 0b111111111
    }

    /// Calculate the index in the PT table corresponding to this address.
    #[inline] pub fn pt_index(&self) -> usize {
        (self >> 12) & 0b111111111
    }
}

#[inline] pub fn heap_base_addr() -> usize {
    unsafe { (&mut HEAP_BASE as *mut _) as usize }
}

#[inline] pub fn heap_top_addr() -> usize {
    unsafe { (&mut HEAP_TOP as *mut _) as usize }
}

/// Initialise the kernel heap.
//  TODO: this is the Worst Thing In The Universe. De-stupid-ify it.
pub unsafe fn init_heap<'a>() -> Result<&'a str, &'a str> {
    let heap_base_ptr
        = &mut HEAP_BASE as *mut _;
    let heap_size
        = (&mut HEAP_TOP as *mut _) as usize - heap_base_ptr as usize;
    buddy::system::init_heap(heap_base_ptr, heap_size);
    Ok("[ OKAY ]")
}
//
//impl<A, P> convert::From<A> for P
//where P: Page<Address = A>  {
//
//}

//macro_rules! make_addr_range {
//    $($name:ident, $addr:ty),+ => {$(
//
//    )+}
//}
<commit_msg>[kernel] actually add memory::alloc module<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Kernel memory management.
//!
//! This module contains all of the non-arch-specific paging code, and
//! re-exports memory-related definitions.
use alloc::buddy;

use core::{ops, convert};

pub use arch::memory::{PAddr, HEAP_BASE, HEAP_TOP, PAGE_SHIFT, PAGE_SIZE};

pub mod alloc;
pub mod paging;
#[macro_use] pub mod macros;

/// A virtual address is a machine-sized unsigned integer
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct VAddr(usize);

pub trait Addr: ops::Add<Self> + ops::Sub<Self>
              + ops::Mul<Self> + ops::Div<Self>
              + ops::Shl<Self> + ops::Shr<Self>
              + convert::From<*mut u8> + convert::From<*const u8>
              + Sized {
    type Repr;
}

derive_addr! { VAddr, usize }

impl VAddr {
    #[inline] pub fn from_ptr<T>(ptr: *mut T) -> Self { VAddr(ptr as usize) }
    #[inline] pub const fn from_usize(u: usize) -> Self { VAddr(u) }
    #[inline] pub const fn as_usize(&self) -> usize { self.0 }

    /// Calculate the index in the PML4 table corresponding to this address.
    #[inline] pub fn pml4_index(&self) -> usize {
        (self >> 39) & 0b111111111
    }

    /// Calculate the index in the PDPT table corresponding to this address.
    #[inline] pub fn pdpt_index(&self) -> usize {
        (self >> 30) & 0b111111111
    }

    /// Calculate the index in the PD table corresponding to this address.
    #[inline] pub fn pd_index(&self) -> usize {
        (self >> 21) & 0b111111111
    }

    /// Calculate the index in the PT table corresponding to this address.
    #[inline] pub fn pt_index(&self) -> usize {
        (self >> 12) & 0b111111111
    }
}

#[inline] pub fn heap_base_addr() -> usize {
    unsafe { (&mut HEAP_BASE as *mut _) as usize }
}

#[inline] pub fn heap_top_addr() -> usize {
    unsafe { (&mut HEAP_TOP as *mut _) as usize }
}

/// Initialise the kernel heap.
//  TODO: this is the Worst Thing In The Universe. De-stupid-ify it.
pub unsafe fn init_heap<'a>() -> Result<&'a str, &'a str> {
    let heap_base_ptr
        = &mut HEAP_BASE as *mut _;
    let heap_size
        = (&mut HEAP_TOP as *mut _) as usize - heap_base_ptr as usize;
    buddy::system::init_heap(heap_base_ptr, heap_size);
    Ok("[ OKAY ]")
}
//
//impl<A, P> convert::From<A> for P
//where P: Page<Address = A>  {
//
//}

//macro_rules! make_addr_range {
//    $($name:ident, $addr:ty),+ => {$(
//
//    )+}
//}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Write;

use ppu::*;

#[cfg(test)]
mod spec_tests;

const ADDRESSABLE_MEMORY: usize = 65536;

pub trait Memory {
    fn store(&mut self, u16, u8);
    fn store16(&mut self, u16, u16);
    fn load(&self, u16) -> u8;
    fn load16(&self, u16) -> u16;

    // probably a premature optimization, but we implement inc and dec here so
    // that we can alter the values in place.
    fn inc(&mut self, u16) -> u8;
    fn dec(&mut self, u16) -> u8;
    fn dump(&self, file: &'static str);
}

pub struct NesMemory {
    ram: [u8; 2048],
    ppu: Ppu,
}

impl NesMemory {
    pub fn new() -> Self {
        NesMemory {
            ppu: Ppu::new(),
            ram: [0; 2048],
        }
    }
}

impl Memory for NesMemory {
    fn store(&mut self, addr: u16, data: u8) {
        let addr = addr as usize;
        match addr {
            0x0...0x1fff => {
                // 2048kb ram, mirrored 4 times
                self.ram[addr & 0x7ff] = data;
            }
            0x2000...0x3fff => {
                // PPU registers, mirrored every 8 bytes
                match addr & 0x7 {
                    0x0 => {
                        unimplemented!();
                    } // PPUCTRL
                    0x1 => {
                        unimplemented!();
                    } // PPUMASK
                    0x2 => {
                        unimplemented!();
                    } // PPUSTATUS
                    0x3 => {
                        unimplemented!();
                    } // OAMADDR
                    0x4 => {
                        unimplemented!();
                    } // OAMDATA
                    0x5 => {
                        unimplemented!();
                    } // PPUSCROLL
                    0x6 => {
                        unimplemented!();
                    } // PPUADDR
                    0x7 => {
                        unimplemented!();
                    } // PPUDATA
                    _ => {
                        panic!("This should never happen");
                    }
                }
            }
            0x4000 => {
                unimplemented!();
            } // APU Rectangle 1 W
            0x4001 => {
                unimplemented!();
            } // APU Rectangle 1 W
            0x4002 => {
                unimplemented!();
            } // APU Rectangle 1 W
            0x4003 => {
                unimplemented!();
            } // APU Rectangle 1 W
            0x4004 => {
                unimplemented!();
            } // APU Rectangle 2 W
            0x4005 => {
                unimplemented!();
            } // APU Rectangle 2 W
            0x4006 => {
                unimplemented!();
            } // APU Rectangle 2 W
            0x4007 => {
                unimplemented!();
            } // APU Rectangle 2 W
            0x4008 => {
                unimplemented!();
            } // APU Triangle W
            0x4009 => {
                unimplemented!();
            } // APU Triangle W
            0x400a => {
                unimplemented!();
            } // APU Triangle W
            0x400b => {
                unimplemented!();
            } // APU Triangle W
            0x400c => {
                unimplemented!();
            } // APU Noise W
            0x400d => {
                unimplemented!();
            } // APU Noise W
            0x400e => {
                unimplemented!();
            } // APU Noise W
            0x400f => {
                unimplemented!();
            } // APU Noise W
            0x4010 => {
                unimplemented!();
            } // APU DMC W
            0x4011 => {
                unimplemented!();
            } // APU DMC W
            0x4012 => {
                unimplemented!();
            } // APU DMC W
            0x4013 => {
                unimplemented!();
            } // APU DMC W
            0x4014 => {
                unimplemented!();
            } // Sprite DMA W
            0x4015 => {
                unimplemented!();
            } // Sound Status RW
            0x4016 => {
                unimplemented!();
            } // Input 1 RW
            0x4017 => {
                unimplemented!();
            } // Input 2, Frame Counter RW
            0x4018 => {
                unimplemented!();
            } // ??
            0x4019 => {
                unimplemented!();
            } // ??
            0x401a => {
                unimplemented!();
            } // ??
            0x401b => {
                unimplemented!();
            } // ??
            0x401c => {
                unimplemented!();
            } // ??
            0x401d => {
                unimplemented!();
            } // ??
            0x401e => {
                unimplemented!();
            } // ??
            0x401f => {
                unimplemented!();
            } // ??
            0x4020...0xffff => {
                unimplemented!();
            } // mapped to cartridge
            _ => {
                panic!("Should never get here.");
            }
        }
    }

    fn store16(&mut self, addr: u16, data: u16) {
        unimplemented!();
    }

    fn load(&self, addr: u16) -> u8 {
        unimplemented!();
    }

    fn load16(&self, addr: u16) -> u16 {
        unimplemented!();
    }

    fn inc(&mut self, addr: u16) -> u8 {
        unimplemented!();
    }

    fn dec(&mut self, addr: u16) -> u8 {
        unimplemented!();
    }

    fn dump(&self, file_loc: &'static str) {
        unimplemented!();
    }
}

pub struct SimpleMemory {
    addr: [u8; ADDRESSABLE_MEMORY],
}

impl SimpleMemory {
    pub fn new() -> Self {
        SimpleMemory { addr: [0; ADDRESSABLE_MEMORY] }
    }

    pub fn store_many(&mut self, addr: u16, data: &[u8]) {
        for i in 0..data.len() {
            self.store(addr + i as u16, data[i]);
        }
    }
}

impl Memory for SimpleMemory {
    fn store(&mut self, addr: u16, data: u8) {
        let addr = addr as usize;
        self.addr[addr] = data;
    }

    fn store16(&mut self, addr: u16, data: u16) {
        let lowb = (data & 0xff) as u8;
        let highb = ((data >> 8) & 0xff) as u8;
        self.store(addr, lowb);
        self.store(addr + 1, highb);
    }

    fn load(&self, addr: u16) -> u8 {
        let addr = addr as usize;
        self.addr[addr]
    }

    fn load16(&self, addr: u16) -> u16 {
        let addr = addr as usize;
        self.addr[addr] as u16 | (self.addr[addr + 1] as u16) << 8
    }

    fn inc(&mut self, addr: u16) -> u8 {
        let addr = addr as usize;
        self.addr[addr] = (self.addr[addr] as u16 + 1) as u8;
        self.addr[addr]
    }

    fn dec(&mut self, addr: u16) -> u8 {
        let addr = addr as usize;
        self.addr[addr] = (self.addr[addr] as i16 - 1) as u8;
        self.addr[addr]
    }

    fn dump(&self, file_loc: &'static str) {
        let mut f = File::create(file_loc).unwrap();
        f.write_all(&self.addr).unwrap();
    }
}
<commit_msg>Cleanup comments<commit_after>use std::fs::File;
use std::io::Write;

use ppu::*;

#[cfg(test)]
mod spec_tests;

const ADDRESSABLE_MEMORY: usize = 65536;

pub trait Memory {
    fn store(&mut self, u16, u8);
    fn store16(&mut self, u16, u16);
    fn load(&self, u16) -> u8;
    fn load16(&self, u16) -> u16;

    // probably a premature optimization, but we implement inc and dec here so
    // that we can alter the values in place.
    fn inc(&mut self, u16) -> u8;
    fn dec(&mut self, u16) -> u8;
    fn dump(&self, file: &'static str);
}

pub struct NesMemory {
    ram: [u8; 2048],
    ppu: Ppu,
}

impl NesMemory {
    pub fn new() -> Self {
        NesMemory {
            ppu: Ppu::new(),
            ram: [0; 2048],
        }
    }
}

impl Memory for NesMemory {
    fn store(&mut self, addr: u16, data: u8) {
        let addr = addr as usize;
        match addr {
            0x0...0x1fff => {
                // 2kb ram, mirrored 4 times
                self.ram[addr & 0x7ff] = data;
            }
            0x2000...0x3fff => {
                // PPU registers, mirrored every 8 bytes
                match addr & 0x7 {
                    0x0 => {
                        // PPUCTRL
                        unimplemented!();
                    }
                    0x1 => {
                        // PPUMASK
                        unimplemented!();
                    }
                    0x2 => {
                        // PPUSTATUS
                        unimplemented!();
                    }
                    0x3 => {
                        // OAMADDR
                        unimplemented!();
                    }
                    0x4 => {
                        // OAMDATA
                        unimplemented!();
                    }
                    0x5 => {
                        // PPUSCROLL
                        unimplemented!();
                    }
                    0x6 => {
                        // PPUADDR
                        unimplemented!();
                    }
                    0x7 => {
                        // PPUDATA
                        unimplemented!();
                    }
                    _ => {
                        panic!("This should never happen");
                    }
                }
            }
            0x4000 => {
                // APU Rectangle 1 W
                unimplemented!();
            }
            0x4001 => {
                // APU Rectangle 1 W
                unimplemented!();
            }
            0x4002 => {
                // APU Rectangle 1 W
                unimplemented!();
            }
            0x4003 => {
                // APU Rectangle 1 W
                unimplemented!();
            }
            0x4004 => {
                // APU Rectangle 2 W
                unimplemented!();
            }
            0x4005 => {
                // APU Rectangle 2 W
                unimplemented!();
            }
            0x4006 => {
                // APU Rectangle 2 W
                unimplemented!();
            }
            0x4007 => {
                // APU Rectangle 2 W
                unimplemented!();
            }
            0x4008 => {
                // APU Triangle W
                unimplemented!();
            }
            0x4009 => {
                // APU Triangle W
                unimplemented!();
            }
            0x400a => {
                // APU Triangle W
                unimplemented!();
            }
            0x400b => {
                // APU Triangle W
                unimplemented!();
            }
            0x400c => {
                // APU Noise W
                unimplemented!();
            }
            0x400d => {
                // APU Noise W
                unimplemented!();
            }
            0x400e => {
                // APU Noise W
                unimplemented!();
            }
            0x400f => {
                // APU Noise W
                unimplemented!();
            }
            0x4010 => {
                // APU DMC W
                unimplemented!();
            }
            0x4011 => {
                // APU DMC W
                unimplemented!();
            }
            0x4012 => {
                // APU DMC W
                unimplemented!();
            }
            0x4013 => {
                // APU DMC W
                unimplemented!();
            }
            0x4014 => {
                // Sprite DMA W
                unimplemented!();
            }
            0x4015 => {
                // Sound Status RW
                unimplemented!();
            }
            0x4016 => {
                // Input 1 RW
                unimplemented!();
            }
            0x4017 => {
                // Input 2, Frame Counter RW
                unimplemented!();
            }
            0x4018 => {
                // ??
                unimplemented!();
            }
            0x4019 => {
                // ??
                unimplemented!();
            }
            0x401a => {
                // ??
                unimplemented!();
            }
            0x401b => {
                // ??
                unimplemented!();
            }
            0x401c => {
                // ??
                unimplemented!();
            }
            0x401d => {
                // ??
                unimplemented!();
            }
            0x401e => {
                // ??
                unimplemented!();
            }
            0x401f => {
                // ??
                unimplemented!();
            }
            0x4020...0xffff => {
                // mapped to cartridge
                unimplemented!();
            }
            _ => {
                panic!("Should never get here.");
            }
        }
    }

    fn store16(&mut self, addr: u16, data: u16) {
        unimplemented!();
    }

    fn load(&self, addr: u16) -> u8 {
        unimplemented!();
    }

    fn load16(&self, addr: u16) -> u16 {
        unimplemented!();
    }

    fn inc(&mut self, addr: u16) -> u8 {
        unimplemented!();
    }

    fn dec(&mut self, addr: u16) -> u8 {
        unimplemented!();
    }

    fn dump(&self, file_loc: &'static str) {
        unimplemented!();
    }
}

pub struct SimpleMemory {
    addr: [u8; ADDRESSABLE_MEMORY],
}

impl SimpleMemory {
    pub fn new() -> Self {
        SimpleMemory { addr: [0; ADDRESSABLE_MEMORY] }
    }

    pub fn store_many(&mut self, addr: u16, data: &[u8]) {
        for i in 0..data.len() {
            self.store(addr + i as u16, data[i]);
        }
    }
}

impl Memory for SimpleMemory {
    fn store(&mut self, addr: u16, data: u8) {
        let addr = addr as usize;
        self.addr[addr] = data;
    }

    fn store16(&mut self, addr: u16, data: u16) {
        let lowb = (data & 0xff) as u8;
        let highb = ((data >> 8) & 0xff) as u8;
        self.store(addr, lowb);
        self.store(addr + 1, highb);
    }

    fn load(&self, addr: u16) -> u8 {
        let addr = addr as usize;
        self.addr[addr]
    }

    fn load16(&self, addr: u16) -> u16 {
        let addr = addr as usize;
        self.addr[addr] as u16 | (self.addr[addr + 1] as u16) << 8
    }

    fn inc(&mut self, addr: u16) -> u8 {
        let addr = addr as usize;
        self.addr[addr] = (self.addr[addr] as u16 + 1) as u8;
        self.addr[addr]
    }

    fn dec(&mut self, addr: u16) -> u8 {
        let addr = addr as usize;
        self.addr[addr] = (self.addr[addr] as i16 - 1) as u8;
        self.addr[addr]
    }

    fn dump(&self, file_loc: &'static str) {
        let mut f = File::create(file_loc).unwrap();
        f.write_all(&self.addr).unwrap();
    }
}
<|endoftext|>


<commit_before>use crate::any::Any;
use crate::error::Error as StdError;
use crate::ffi::{OsString, OsStr, CString, CStr};
use crate::fmt;
use crate::io;
use crate::marker::PhantomData;
use crate::os::wasi::prelude::*;
use crate::path::{self, PathBuf};
use crate::ptr;
use crate::str;
use crate::sys::memchr;
use crate::sys::{cvt, unsupported, Void};
use crate::vec;

#[cfg(not(target_feature = "atomics"))]
pub unsafe fn env_lock() -> impl Any {
    // No need for a lock if we're single-threaded, but this function will need
    // to get implemented for multi-threaded scenarios
}

pub fn errno() -> i32 {
    extern {
        #[thread_local]
        static errno: libc::c_int;
    }

    unsafe { errno as i32 }
}

pub fn error_string(_errno: i32) -> String {
    "operation failed".to_string()
}

pub fn getcwd() -> io::Result<PathBuf> {
    unsupported()
}

pub fn chdir(_: &path::Path) -> io::Result<()> {
    unsupported()
}

pub struct SplitPaths<'a>(&'a Void);

pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
    panic!("unsupported")
}

impl<'a> Iterator for SplitPaths<'a> {
    type Item = PathBuf;
    fn next(&mut self) -> Option<PathBuf> {
        match *self.0 {}
    }
}

#[derive(Debug)]
pub struct JoinPathsError;

pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
    where I: Iterator<Item=T>, T: AsRef<OsStr>
{
    Err(JoinPathsError)
}

impl fmt::Display for JoinPathsError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "not supported on wasm yet".fmt(f)
    }
}

impl StdError for JoinPathsError {
    fn description(&self) -> &str {
        "not supported on wasm yet"
    }
}

pub fn current_exe() -> io::Result<PathBuf> {
    unsupported()
}

pub struct Env {
    iter: vec::IntoIter<(OsString, OsString)>,
    _dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl Iterator for Env {
    type Item = (OsString, OsString);
    fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() }
    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

pub fn env() -> Env {
    unsafe {
        let _guard = env_lock();
        let mut environ = libc::environ;
        let mut result = Vec::new();
        while environ != ptr::null_mut() && *environ != ptr::null_mut() {
            if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
                result.push(key_value);
            }
            environ = environ.offset(1);
        }
        return Env {
            iter: result.into_iter(),
            _dont_send_or_sync_me: PhantomData,
        }
    }

    // See src/libstd/sys/unix/os.rs, same as that
    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
        if input.is_empty() {
            return None;
        }
        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
        pos.map(|p| (
            OsStringExt::from_vec(input[..p].to_vec()),
            OsStringExt::from_vec(input[p+1..].to_vec()),
        ))
    }
}

pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
    let k = CString::new(k.as_bytes())?;
    unsafe {
        let _guard = env_lock();
        let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
        let ret = if s.is_null() {
            None
        } else {
            Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
        };
        Ok(ret)
    }
}

pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
    let k = CString::new(k.as_bytes())?;
    let v = CString::new(v.as_bytes())?;

    unsafe {
        let _guard = env_lock();
        cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
    }
}

pub fn unsetenv(n: &OsStr) -> io::Result<()> {
    let nbuf = CString::new(n.as_bytes())?;

    unsafe {
        let _guard = env_lock();
        cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
    }
}

pub fn temp_dir() -> PathBuf {
    panic!("no filesystem on wasm")
}

pub fn home_dir() -> Option<PathBuf> {
    None
}

pub fn exit(code: i32) -> ! {
    unsafe {
        libc::exit(code)
    }
}

pub fn getpid() -> u32 {
    panic!("unsupported");
}
<commit_msg>wasi: Implement `error_string` to get readable errors<commit_after>use crate::any::Any;
use crate::error::Error as StdError;
use crate::ffi::{OsString, OsStr, CString, CStr};
use crate::fmt;
use crate::io;
use crate::marker::PhantomData;
use crate::os::wasi::prelude::*;
use crate::path::{self, PathBuf};
use crate::ptr;
use crate::str;
use crate::sys::memchr;
use crate::sys::{cvt, unsupported, Void};
use crate::vec;

#[cfg(not(target_feature = "atomics"))]
pub unsafe fn env_lock() -> impl Any {
    // No need for a lock if we're single-threaded, but this function will need
    // to get implemented for multi-threaded scenarios
}

pub fn errno() -> i32 {
    extern {
        #[thread_local]
        static errno: libc::c_int;
    }

    unsafe { errno as i32 }
}

pub fn error_string(errno: i32) -> String {
    extern {
        fn strerror_r(errnum: libc::c_int, buf: *mut libc::c_char,
                      buflen: libc::size_t) -> libc::c_int;
    }

    let mut buf = [0 as libc::c_char; 1024];

    let p = buf.as_mut_ptr();
    unsafe {
        if strerror_r(errno as libc::c_int, p, buf.len()) < 0 {
            panic!("strerror_r failure");
        }
        str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
    }
}

pub fn getcwd() -> io::Result<PathBuf> {
    unsupported()
}

pub fn chdir(_: &path::Path) -> io::Result<()> {
    unsupported()
}

pub struct SplitPaths<'a>(&'a Void);

pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
    panic!("unsupported")
}

impl<'a> Iterator for SplitPaths<'a> {
    type Item = PathBuf;
    fn next(&mut self) -> Option<PathBuf> {
        match *self.0 {}
    }
}

#[derive(Debug)]
pub struct JoinPathsError;

pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
    where I: Iterator<Item=T>, T: AsRef<OsStr>
{
    Err(JoinPathsError)
}

impl fmt::Display for JoinPathsError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        "not supported on wasm yet".fmt(f)
    }
}

impl StdError for JoinPathsError {
    fn description(&self) -> &str {
        "not supported on wasm yet"
    }
}

pub fn current_exe() -> io::Result<PathBuf> {
    unsupported()
}

pub struct Env {
    iter: vec::IntoIter<(OsString, OsString)>,
    _dont_send_or_sync_me: PhantomData<*mut ()>,
}

impl Iterator for Env {
    type Item = (OsString, OsString);
    fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() }
    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

pub fn env() -> Env {
    unsafe {
        let _guard = env_lock();
        let mut environ = libc::environ;
        let mut result = Vec::new();
        while environ != ptr::null_mut() && *environ != ptr::null_mut() {
            if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) {
                result.push(key_value);
            }
            environ = environ.offset(1);
        }
        return Env {
            iter: result.into_iter(),
            _dont_send_or_sync_me: PhantomData,
        }
    }

    // See src/libstd/sys/unix/os.rs, same as that
    fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
        if input.is_empty() {
            return None;
        }
        let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
        pos.map(|p| (
            OsStringExt::from_vec(input[..p].to_vec()),
            OsStringExt::from_vec(input[p+1..].to_vec()),
        ))
    }
}

pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
    let k = CString::new(k.as_bytes())?;
    unsafe {
        let _guard = env_lock();
        let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
        let ret = if s.is_null() {
            None
        } else {
            Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
        };
        Ok(ret)
    }
}

pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
    let k = CString::new(k.as_bytes())?;
    let v = CString::new(v.as_bytes())?;

    unsafe {
        let _guard = env_lock();
        cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ())
    }
}

pub fn unsetenv(n: &OsStr) -> io::Result<()> {
    let nbuf = CString::new(n.as_bytes())?;

    unsafe {
        let _guard = env_lock();
        cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ())
    }
}

pub fn temp_dir() -> PathBuf {
    panic!("no filesystem on wasm")
}

pub fn home_dir() -> Option<PathBuf> {
    None
}

pub fn exit(code: i32) -> ! {
    unsafe {
        libc::exit(code)
    }
}

pub fn getpid() -> u32 {
    panic!("unsupported");
}
<|endoftext|>


<commit_before>//! Filter primitive subregion computation.
use crate::bbox::BoundingBox;
use crate::drawing_ctx::DrawingCtx;
use crate::length::*;
use crate::rect::{IRect, Rect};

use super::context::{FilterContext, FilterInput};

/// A helper type for filter primitive subregion computation.
#[derive(Clone, Copy)]
pub struct BoundsBuilder<'a> {
    /// The filter context.
    ctx: &'a FilterContext,

    /// The current bounding box.
    bbox: BoundingBox,

    /// Whether one of the input nodes is standard input.
    standard_input_was_referenced: bool,

    /// Filter primitive properties.
    x: Option<Length<Horizontal>>,
    y: Option<Length<Vertical>>,
    width: Option<Length<Horizontal>>,
    height: Option<Length<Vertical>>,
}

impl<'a> BoundsBuilder<'a> {
    /// Constructs a new `BoundsBuilder`.
    #[inline]
    pub fn new(
        ctx: &'a FilterContext,
        x: Option<Length<Horizontal>>,
        y: Option<Length<Vertical>>,
        width: Option<Length<Horizontal>>,
        height: Option<Length<Vertical>>,
    ) -> Self {
        Self {
            ctx,
            // The matrix is paffine because we're using that fact in apply_properties().
            bbox: BoundingBox::new().with_affine(ctx.paffine()),
            standard_input_was_referenced: false,
            x,
            y,
            width,
            height,
        }
    }

    /// Adds a filter primitive input to the bounding box.
    #[inline]
    pub fn add_input(mut self, input: &FilterInput) -> Self {
        // If a standard input was referenced, the default value is the filter effects region
        // regardless of other referenced inputs. This means we can skip computing the bounding
        // box.
        if self.standard_input_was_referenced {
            return self;
        }

        match *input {
            FilterInput::StandardInput(_) => {
                self.standard_input_was_referenced = true;
            }
            FilterInput::PrimitiveOutput(ref output) => {
                let input_bbox = BoundingBox::new().with_rect(output.bounds.into());
                self.bbox.insert(&input_bbox);
            }
        }

        self
    }

    /// Returns the final exact bounds.
    pub fn into_rect(self, draw_ctx: &mut DrawingCtx) -> Rect {
        let mut bbox = self.apply_properties(draw_ctx);

        let effects_region = self.ctx.effects_region();
        bbox.clip(&effects_region);

        bbox.rect.unwrap().into()
    }

    /// Returns the final pixel bounds.
    pub fn into_irect(self, draw_ctx: &mut DrawingCtx) -> IRect {
        self.into_rect(draw_ctx).into()
    }

    /// Returns the final pixel bounds without clipping to the filter effects region.
    ///
    /// Used by feImage.
    pub fn into_rect_without_clipping(self, draw_ctx: &mut DrawingCtx) -> Rect {
        self.apply_properties(draw_ctx).rect.unwrap().into()
    }

    /// Applies the filter primitive properties.
    fn apply_properties(mut self, draw_ctx: &mut DrawingCtx) -> BoundingBox {
        if self.bbox.rect.is_none() || self.standard_input_was_referenced {
            // The default value is the filter effects region.
            let effects_region = self.ctx.effects_region();

            // Clear out the rect.
            self.bbox.clear();

            // Convert into the paffine coordinate system.
            self.bbox.insert(&effects_region);
        }

        // If any of the properties were specified, we need to respect them.
        if self.x.is_some() || self.y.is_some() || self.width.is_some() || self.height.is_some() {
            let params = self.ctx.get_view_params(draw_ctx);
            let values = self.ctx.get_computed_values_from_node_being_filtered();

            // These replacements are correct only because self.bbox is used with the paffine
            // matrix.
            let rect = self.bbox.rect.as_mut().unwrap();

            if let Some(x) = self.x {
                let w = rect.width();
                rect.x0 = x.normalize(values, &params);
                rect.x1 = rect.x0 + w;
            }
            if let Some(y) = self.y {
                let h = rect.height();
                rect.y0 = y.normalize(values, &params);
                rect.y1 = rect.y0 + h;
            }
            if let Some(width) = self.width {
                rect.x1 = rect.x0 + width.normalize(values, &params);
            }
            if let Some(height) = self.height {
                rect.y1 = rect.y0 + height.normalize(values, &params);
            }
        }

        // Convert into the surface coordinate system.
        let mut bbox = BoundingBox::new();
        bbox.insert(&self.bbox);
        bbox
    }
}
<commit_msg>bounds: remove unneeded into()<commit_after>//! Filter primitive subregion computation.
use crate::bbox::BoundingBox;
use crate::drawing_ctx::DrawingCtx;
use crate::length::*;
use crate::rect::{IRect, Rect};

use super::context::{FilterContext, FilterInput};

/// A helper type for filter primitive subregion computation.
#[derive(Clone, Copy)]
pub struct BoundsBuilder<'a> {
    /// The filter context.
    ctx: &'a FilterContext,

    /// The current bounding box.
    bbox: BoundingBox,

    /// Whether one of the input nodes is standard input.
    standard_input_was_referenced: bool,

    /// Filter primitive properties.
    x: Option<Length<Horizontal>>,
    y: Option<Length<Vertical>>,
    width: Option<Length<Horizontal>>,
    height: Option<Length<Vertical>>,
}

impl<'a> BoundsBuilder<'a> {
    /// Constructs a new `BoundsBuilder`.
    #[inline]
    pub fn new(
        ctx: &'a FilterContext,
        x: Option<Length<Horizontal>>,
        y: Option<Length<Vertical>>,
        width: Option<Length<Horizontal>>,
        height: Option<Length<Vertical>>,
    ) -> Self {
        Self {
            ctx,
            // The matrix is paffine because we're using that fact in apply_properties().
            bbox: BoundingBox::new().with_affine(ctx.paffine()),
            standard_input_was_referenced: false,
            x,
            y,
            width,
            height,
        }
    }

    /// Adds a filter primitive input to the bounding box.
    #[inline]
    pub fn add_input(mut self, input: &FilterInput) -> Self {
        // If a standard input was referenced, the default value is the filter effects region
        // regardless of other referenced inputs. This means we can skip computing the bounding
        // box.
        if self.standard_input_was_referenced {
            return self;
        }

        match *input {
            FilterInput::StandardInput(_) => {
                self.standard_input_was_referenced = true;
            }
            FilterInput::PrimitiveOutput(ref output) => {
                let input_bbox = BoundingBox::new().with_rect(output.bounds.into());
                self.bbox.insert(&input_bbox);
            }
        }

        self
    }

    /// Returns the final exact bounds.
    pub fn into_rect(self, draw_ctx: &mut DrawingCtx) -> Rect {
        let mut bbox = self.apply_properties(draw_ctx);

        let effects_region = self.ctx.effects_region();
        bbox.clip(&effects_region);

        bbox.rect.unwrap()
    }

    /// Returns the final pixel bounds.
    pub fn into_irect(self, draw_ctx: &mut DrawingCtx) -> IRect {
        self.into_rect(draw_ctx).into()
    }

    /// Returns the final pixel bounds without clipping to the filter effects region.
    ///
    /// Used by feImage.
    pub fn into_rect_without_clipping(self, draw_ctx: &mut DrawingCtx) -> Rect {
        self.apply_properties(draw_ctx).rect.unwrap()
    }

    /// Applies the filter primitive properties.
    fn apply_properties(mut self, draw_ctx: &mut DrawingCtx) -> BoundingBox {
        if self.bbox.rect.is_none() || self.standard_input_was_referenced {
            // The default value is the filter effects region.
            let effects_region = self.ctx.effects_region();

            // Clear out the rect.
            self.bbox.clear();

            // Convert into the paffine coordinate system.
            self.bbox.insert(&effects_region);
        }

        // If any of the properties were specified, we need to respect them.
        if self.x.is_some() || self.y.is_some() || self.width.is_some() || self.height.is_some() {
            let params = self.ctx.get_view_params(draw_ctx);
            let values = self.ctx.get_computed_values_from_node_being_filtered();

            // These replacements are correct only because self.bbox is used with the paffine
            // matrix.
            let rect = self.bbox.rect.as_mut().unwrap();

            if let Some(x) = self.x {
                let w = rect.width();
                rect.x0 = x.normalize(values, &params);
                rect.x1 = rect.x0 + w;
            }
            if let Some(y) = self.y {
                let h = rect.height();
                rect.y0 = y.normalize(values, &params);
                rect.y1 = rect.y0 + h;
            }
            if let Some(width) = self.width {
                rect.x1 = rect.x0 + width.normalize(values, &params);
            }
            if let Some(height) = self.height {
                rect.y1 = rect.y0 + height.normalize(values, &params);
            }
        }

        // Convert into the surface coordinate system.
        let mut bbox = BoundingBox::new();
        bbox.insert(&self.bbox);
        bbox
    }
}
<|endoftext|>


<commit_before>use std::io::Cursor;
use std::mem::{size_of, transmute};
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

use rust_ofp::openflow0x01::MsgCode;

pub struct OfpHeader {
    version: u8,
    typ: u8,
    length: u16,
    xid: u32,
}

impl OfpHeader {
    pub fn new(version: u8, typ: u8, length: u16, xid: u32) -> OfpHeader {
        OfpHeader {
            version: version,
            typ: typ,
            length: length,
            xid: xid,
        }
    }

    pub fn size() -> usize {
        size_of::<OfpHeader>()
    }

    pub fn marshal(bytes: &mut Vec<u8>, header: OfpHeader) {
        bytes.write_u8(header.version()).unwrap();
        bytes.write_u8(header.type_code() as u8).unwrap();
        bytes.write_u16::<BigEndian>(header.length() as u16).unwrap();
        bytes.write_u32::<BigEndian>(header.xid()).unwrap();
    }

    pub fn parse(buf: [u8; 8]) -> Self {
        let mut bytes = Cursor::new(buf.to_vec());
        OfpHeader {
            version: bytes.read_u8().unwrap(),
            typ: bytes.read_u8().unwrap(),
            length: bytes.read_u16::<BigEndian>().unwrap(),
            xid: bytes.read_u32::<BigEndian>().unwrap(),
        }
    }

    pub fn version(&self) -> u8 {
        self.version
    }
    pub fn type_code(&self) -> MsgCode {
        unsafe { transmute(self.typ) }
    }
    pub fn length(&self) -> usize {
        self.length as usize
    }
    pub fn xid(&self) -> u32 {
        self.xid
    }
}
<commit_msg>Document ofp_header module<commit_after>use std::io::Cursor;
use std::mem::{size_of, transmute};
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

use rust_ofp::openflow0x01::MsgCode;

/// OpenFlow Header
///
/// The first fields of every OpenFlow message, no matter the protocol version.
/// This is parsed to determine version and length of the remaining message, so that
/// it can be properly handled.
pub struct OfpHeader {
    version: u8,
    typ: u8,
    length: u16,
    xid: u32,
}

impl OfpHeader {
    /// Create an `OfpHeader` out of the arguments.
    pub fn new(version: u8, typ: u8, length: u16, xid: u32) -> OfpHeader {
        OfpHeader {
            version: version,
            typ: typ,
            length: length,
            xid: xid,
        }
    }

    /// Return the byte-size of an `OfpHeader`.
    pub fn size() -> usize {
        size_of::<OfpHeader>()
    }

    /// Fills a message buffer with the header fields of an `OfpHeader`.
    pub fn marshal(bytes: &mut Vec<u8>, header: OfpHeader) {
        bytes.write_u8(header.version()).unwrap();
        bytes.write_u8(header.type_code() as u8).unwrap();
        bytes.write_u16::<BigEndian>(header.length() as u16).unwrap();
        bytes.write_u32::<BigEndian>(header.xid()).unwrap();
    }

    /// Takes a message buffer (sized for an `OfpHeader`) and returns an `OfpHeader`.
    pub fn parse(buf: [u8; 8]) -> Self {
        let mut bytes = Cursor::new(buf.to_vec());
        OfpHeader {
            version: bytes.read_u8().unwrap(),
            typ: bytes.read_u8().unwrap(),
            length: bytes.read_u16::<BigEndian>().unwrap(),
            xid: bytes.read_u32::<BigEndian>().unwrap(),
        }
    }

    /// Return the `version` field of a header.
    pub fn version(&self) -> u8 {
        self.version
    }

    /// Return the OpenFlow message type code of a header.
    /// # Safety
    ///
    /// The `typ` field of the `self` header is expected to be a `u8` within the
    /// defined range of the `MsgCode` enum.
    pub fn type_code(&self) -> MsgCode {
        unsafe { transmute(self.typ) }
    }

    /// Return the `length` field of a header. Includes the length of the header itself.
    pub fn length(&self) -> usize {
        self.length as usize
    }

    /// Return the `xid` field of a header, the transaction id associated with this packet.
    ///  Replies use the same id to facilitate pairing.
    pub fn xid(&self) -> u32 {
        self.xid
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate chan;
extern crate crossbeam;

use chan::{Sender, Receiver};

const MESSAGES: usize = 5_000_000;
const THREADS: usize = 4;

type RxTx = (Sender<i32>, Receiver<i32>);

fn seq<F: Fn() -> RxTx>(make: F) {
    let (tx, rx) = make();

    for i in 0..MESSAGES {
        tx.send(i as i32);
    }
    for _ in 0..MESSAGES {
        rx.recv().unwrap();
    }
}

fn spsc<F: Fn() -> RxTx>(make: F) {
    let (tx, rx) = make();

    crossbeam::scope(|s| {
        s.spawn(|| {
            for i in 0..MESSAGES {
                tx.send(i as i32);
            }
        });
        s.spawn(|| {
            for _ in 0..MESSAGES {
                rx.recv().unwrap();
            }
        });
    });
}

fn mpsc<F: Fn() -> RxTx>(make: F) {
    let (tx, rx) = make();

    crossbeam::scope(|s| {
        for _ in 0..THREADS {
            s.spawn(|| {
                for i in 0..MESSAGES / THREADS {
                    tx.send(i as i32);
                }
            });
        }
        s.spawn(|| {
            for _ in 0..MESSAGES {
                rx.recv().unwrap();
            }
        });
    });
}

fn mpmc<F: Fn() -> RxTx>(make: F) {
    let (tx, rx) = make();

    crossbeam::scope(|s| {
        for _ in 0..THREADS {
            s.spawn(|| {
                for i in 0..MESSAGES / THREADS {
                    tx.send(i as i32);
                }
            });
        }
        for _ in 0..THREADS {
            s.spawn(|| {
                for _ in 0..MESSAGES / THREADS {
                    rx.recv().unwrap();
                }
            });
        }
    });
}

fn select_rx<F: Fn() -> RxTx>(make: F) {
    let chans = (0..THREADS).map(|_| make()).collect::<Vec<_>>();

    crossbeam::scope(|s| {
        for &(ref tx, _) in &chans {
            s.spawn(move || {
                for i in 0..MESSAGES / THREADS {
                    tx.send(i as i32);
                }
            });
        }

        s.spawn(|| {
            let rx0 = &chans[0].1;
            let rx1 = &chans[1].1;
            let rx2 = &chans[2].1;
            let rx3 = &chans[3].1;

            for _ in 0..MESSAGES {
                chan_select! {
                    rx0.recv() => {},
                    rx1.recv() => {},
                    rx2.recv() => {},
                    rx3.recv() => {},
                }
            }
        });
    });
}

fn select_both<F: Fn() -> RxTx>(make: F) {
    let chans = (0..THREADS).map(|_| make()).collect::<Vec<_>>();

    crossbeam::scope(|s| {
        for _ in 0..THREADS {
            let chans = chans.clone();
            s.spawn(move || {
                let rx0 = &chans[0].0;
                let rx1 = &chans[1].0;
                let rx2 = &chans[2].0;
                let rx3 = &chans[3].0;
                for i in 0..MESSAGES / THREADS {
                    chan_select! {
                        rx0.send(i as i32) => {},
                        rx1.send(i as i32) => {},
                        rx2.send(i as i32) => {},
                        rx3.send(i as i32) => {},
                    }
                }
            });
        }

        for _ in 0..THREADS {
            let chans = chans.clone();
            s.spawn(move || {
                let tx0 = &chans[0].1;
                let tx1 = &chans[1].1;
                let tx2 = &chans[2].1;
                let tx3 = &chans[3].1;
                for _ in 0..MESSAGES / THREADS {
                    chan_select! {
                        tx0.recv() => {},
                        tx1.recv() => {},
                        tx2.recv() => {},
                        tx3.recv() => {},
                    }
                }
            });
        }
    });
}

fn main() {
    macro_rules! run {
        ($name:expr, $f:expr) => {
            let now = ::std::time::Instant::now();
            $f;
            let elapsed = now.elapsed();
            println!(
                "{:25} {:15} {:7.3} sec",
                $name,
                "Rust chan",
                elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1e9
            );
        }
    }

    run!("bounded0_mpmc", mpmc(|| chan::sync(0)));
    run!("bounded0_mpsc", mpsc(|| chan::sync(0)));
    // run!("bounded0_select_both", select_both(|| chan::sync(0)));
    run!("bounded0_select_rx", select_rx(|| chan::sync(0)));
    run!("bounded0_spsc", spsc(|| chan::sync(0)));

    run!("bounded1_mpmc", mpmc(|| chan::sync(1)));
    run!("bounded1_mpsc", mpsc(|| chan::sync(1)));
    run!("bounded1_select_both", select_both(|| chan::sync(1)));
    run!("bounded1_select_rx", select_rx(|| chan::sync(1)));
    run!("bounded1_spsc", spsc(|| chan::sync(1)));

    run!("bounded_mpmc", mpmc(|| chan::sync(MESSAGES)));
    run!("bounded_mpsc", mpsc(|| chan::sync(MESSAGES)));
    run!("bounded_select_both", select_both(|| chan::sync(MESSAGES)));
    run!("bounded_select_rx", select_rx(|| chan::sync(MESSAGES)));
    run!("bounded_seq", seq(|| chan::sync(MESSAGES)));
    run!("bounded_spsc", spsc(|| chan::sync(MESSAGES)));

    run!("unbounded_mpmc", mpmc(|| chan::async()));
    run!("unbounded_mpsc", mpsc(|| chan::async()));
    run!("unbounded_select_rx", select_rx(|| chan::async()));
    run!("unbounded_seq", seq(|| chan::async()));
    run!("unbounded_spsc", spsc(|| chan::async()));
    run!("unbounded_select_both", select_both(|| chan::async()));
}
<commit_msg>Rename variables<commit_after>#[macro_use]
extern crate chan;
extern crate crossbeam;

use chan::{Sender, Receiver};

const MESSAGES: usize = 5_000_000;
const THREADS: usize = 4;

type RxTx = (Sender<i32>, Receiver<i32>);

fn seq<F: Fn() -> RxTx>(make: F) {
    let (tx, rx) = make();

    for i in 0..MESSAGES {
        tx.send(i as i32);
    }
    for _ in 0..MESSAGES {
        rx.recv().unwrap();
    }
}

fn spsc<F: Fn() -> RxTx>(make: F) {
    let (tx, rx) = make();

    crossbeam::scope(|s| {
        s.spawn(|| {
            for i in 0..MESSAGES {
                tx.send(i as i32);
            }
        });
        s.spawn(|| {
            for _ in 0..MESSAGES {
                rx.recv().unwrap();
            }
        });
    });
}

fn mpsc<F: Fn() -> RxTx>(make: F) {
    let (tx, rx) = make();

    crossbeam::scope(|s| {
        for _ in 0..THREADS {
            s.spawn(|| {
                for i in 0..MESSAGES / THREADS {
                    tx.send(i as i32);
                }
            });
        }
        s.spawn(|| {
            for _ in 0..MESSAGES {
                rx.recv().unwrap();
            }
        });
    });
}

fn mpmc<F: Fn() -> RxTx>(make: F) {
    let (tx, rx) = make();

    crossbeam::scope(|s| {
        for _ in 0..THREADS {
            s.spawn(|| {
                for i in 0..MESSAGES / THREADS {
                    tx.send(i as i32);
                }
            });
        }
        for _ in 0..THREADS {
            s.spawn(|| {
                for _ in 0..MESSAGES / THREADS {
                    rx.recv().unwrap();
                }
            });
        }
    });
}

fn select_rx<F: Fn() -> RxTx>(make: F) {
    let chans = (0..THREADS).map(|_| make()).collect::<Vec<_>>();

    crossbeam::scope(|s| {
        for &(ref tx, _) in &chans {
            s.spawn(move || {
                for i in 0..MESSAGES / THREADS {
                    tx.send(i as i32);
                }
            });
        }

        s.spawn(|| {
            let rx0 = &chans[0].1;
            let rx1 = &chans[1].1;
            let rx2 = &chans[2].1;
            let rx3 = &chans[3].1;

            for _ in 0..MESSAGES {
                chan_select! {
                    rx0.recv() => {},
                    rx1.recv() => {},
                    rx2.recv() => {},
                    rx3.recv() => {},
                }
            }
        });
    });
}

fn select_both<F: Fn() -> RxTx>(make: F) {
    let chans = (0..THREADS).map(|_| make()).collect::<Vec<_>>();

    crossbeam::scope(|s| {
        for _ in 0..THREADS {
            let chans = chans.clone();
            s.spawn(move || {
                let tx0 = &chans[0].0;
                let tx1 = &chans[1].0;
                let tx2 = &chans[2].0;
                let tx3 = &chans[3].0;
                for i in 0..MESSAGES / THREADS {
                    chan_select! {
                        tx0.send(i as i32) => {},
                        tx1.send(i as i32) => {},
                        tx2.send(i as i32) => {},
                        tx3.send(i as i32) => {},
                    }
                }
            });
        }

        for _ in 0..THREADS {
            let chans = chans.clone();
            s.spawn(move || {
                let rx0 = &chans[0].1;
                let rx1 = &chans[1].1;
                let rx2 = &chans[2].1;
                let rx3 = &chans[3].1;
                for _ in 0..MESSAGES / THREADS {
                    chan_select! {
                        rx0.recv() => {},
                        rx1.recv() => {},
                        rx2.recv() => {},
                        rx3.recv() => {},
                    }
                }
            });
        }
    });
}

fn main() {
    macro_rules! run {
        ($name:expr, $f:expr) => {
            let now = ::std::time::Instant::now();
            $f;
            let elapsed = now.elapsed();
            println!(
                "{:25} {:15} {:7.3} sec",
                $name,
                "Rust chan",
                elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1e9
            );
        }
    }

    run!("bounded0_mpmc", mpmc(|| chan::sync(0)));
    run!("bounded0_mpsc", mpsc(|| chan::sync(0)));
    // run!("bounded0_select_both", select_both(|| chan::sync(0)));
    run!("bounded0_select_rx", select_rx(|| chan::sync(0)));
    run!("bounded0_spsc", spsc(|| chan::sync(0)));

    run!("bounded1_mpmc", mpmc(|| chan::sync(1)));
    run!("bounded1_mpsc", mpsc(|| chan::sync(1)));
    run!("bounded1_select_both", select_both(|| chan::sync(1)));
    run!("bounded1_select_rx", select_rx(|| chan::sync(1)));
    run!("bounded1_spsc", spsc(|| chan::sync(1)));

    run!("bounded_mpmc", mpmc(|| chan::sync(MESSAGES)));
    run!("bounded_mpsc", mpsc(|| chan::sync(MESSAGES)));
    run!("bounded_select_both", select_both(|| chan::sync(MESSAGES)));
    run!("bounded_select_rx", select_rx(|| chan::sync(MESSAGES)));
    run!("bounded_seq", seq(|| chan::sync(MESSAGES)));
    run!("bounded_spsc", spsc(|| chan::sync(MESSAGES)));

    run!("unbounded_mpmc", mpmc(|| chan::async()));
    run!("unbounded_mpsc", mpsc(|| chan::async()));
    run!("unbounded_select_rx", select_rx(|| chan::async()));
    run!("unbounded_seq", seq(|| chan::async()));
    run!("unbounded_spsc", spsc(|| chan::async()));
    run!("unbounded_select_both", select_both(|| chan::async()));
}
<|endoftext|>


<commit_before>//! The parser module is responsible for parsing FITS files.

use std::str;
use std::str::FromStr;
use super::types::{Fits, PrimaryHeader, KeywordRecord, Keyword, Value, BlankRecord};

named!(#[doc = "Will parse data from a FITS file into a `Fits` structure"], pub fits<&[u8], Fits>,
       do_parse!(
           ph: primary_header >>
               many0!(take!(2880)) >>
               (Fits::new(ph))
       ));

named!(primary_header<&[u8], PrimaryHeader>,
       do_parse!(
           records: many0!(keyword_record) >>
               end_record >>
               many0!(blank_record) >>
               (PrimaryHeader::new(records))
       ));

named!(keyword_record<&[u8], KeywordRecord>,
       do_parse!(
           key: keyword  >>
               tag!("= ") >>
           vc: valuecomment >>
               (KeywordRecord::new(key, vc.0, vc.1))
       ));

named!(keyword<&[u8], Keyword>,
       map_res!(
           map_res!(
               take!(8),
               str::from_utf8),
           Keyword::from_str
       ));

named!(valuecomment<&[u8], (&str, Option<&str>)>,
       flat_map!(
           take!(70),
           pair!(
               value,
               opt!(comment)
           )));

named!(value<&[u8], &str>,
       map_res!(
           is_not!("/"), // TODO Differentiate on the possible value types
           str::from_utf8
       )
);

named!(character_string<&[u8], Value>,
       map!(
           map_res!(
               delimited!(
                   tag!("'"),
                   take_while!(is_character_string_character),
                   tag!("'")
               ),
               str::from_utf8
           ),
           Value::CharacterString
       ));

fn is_character_string_character(chr: u8) -> bool {
    is_restricted_ascii(chr) && chr != 39
}

named!(comment<&[u8], &str>,
       map_res!(
           do_parse!(
               tag!("/") >>
                   comment: take_while!(is_comment_character) >>
                   (comment)
           ),
           str::from_utf8
       ));

fn is_comment_character(chr: u8) -> bool {
    is_restricted_ascii(chr)
}

fn is_restricted_ascii(chr: u8) -> bool {
    32u8 <= chr && chr <= 126u8
}

named!(end_record<&[u8], Keyword>,
       map!(
           flat_map!(
               take!(80),
               pair!(tag!("END"), many0!(tag!(" ")))
           ),
           |_| { Keyword::END }
       ));

named!(blank_record<&[u8], BlankRecord>,
       map!(
           count!(tag!(" "), 80),
           |_| { BlankRecord }
       ));

#[cfg(test)]
mod tests {
    use nom::{IResult};
    use super::super::types::{Fits, PrimaryHeader, KeywordRecord, Keyword, Value, BlankRecord};
    use super::{fits, primary_header, keyword_record, keyword, valuecomment, character_string, end_record, blank_record};

    #[test]
    fn it_should_parse_a_fits_file(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = fits(data);

        match result {
            IResult::Done(_, f) => {
                assert_eq!(f, Fits::new(long_cadence_header()));
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn primary_header_should_parse_a_primary_header(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = primary_header(&data[0..(2*2880)]);

        match result {
            IResult::Done(_, h) => assert_eq!(h, long_cadence_header()),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    fn long_cadence_header<'a>() -> PrimaryHeader<'a> {
        PrimaryHeader::new(vec!(
            KeywordRecord::new(Keyword::SIMPLE, "                   T ",
                               Option::Some(" conforms to FITS standards                     ")),
            KeywordRecord::new(Keyword::BITPIX, "                   8 ",
                               Option::Some(" array data type                                ")),
            KeywordRecord::new(Keyword::NAXIS, "                   0 ",
                               Option::Some(" number of array dimensions                     ")),
            KeywordRecord::new(Keyword::EXTEND, "                   T ",
                               Option::Some(" file contains extensions                       ")),
            KeywordRecord::new(Keyword::NEXTEND, "                   2 ",
                               Option::Some(" number of standard extensions                  ")),
            KeywordRecord::new(Keyword::EXTNAME, "'PRIMARY '           ",
                               Option::Some(" name of extension                              ")),
            KeywordRecord::new(Keyword::EXTVER, "                   1 ",
                               Option::Some(" extension version number (not format version)  ")),
            KeywordRecord::new(Keyword::ORIGIN, "'Unofficial data product' ",
                               Option::Some(" institution responsible for creating this ")),
            KeywordRecord::new(Keyword::DATE, "'2017-03-08'         ",
                               Option::Some(" file creation date.                            ")),
            KeywordRecord::new(Keyword::CREATOR, "'kadenza '           ",
                               Option::Some(" pipeline job and program u                     ")),
            KeywordRecord::new(Keyword::PROCVER, "'2.1.dev '           ",
                               Option::Some(" SW version                                     ")),
            KeywordRecord::new(Keyword::FILEVER, "'0.0     '           ",
                               Option::Some(" file format version                            ")),
            KeywordRecord::new(Keyword::TIMVERSN, "'' ",
                               Option::Some(" OGIP memo number for file format                                 ")),
            KeywordRecord::new(Keyword::TELESCOP, "'Kepler  '           ",
                               Option::Some(" telescope                                      ")),
            KeywordRecord::new(Keyword::INSTRUME, "'Kepler Photometer'  ",
                               Option::Some(" detector type                                  ")),
            KeywordRecord::new(Keyword::OBJECT, "'EPIC 200164267'     ",
                               Option::Some(" string version of target id                    ")),
            KeywordRecord::new(Keyword::KEPLERID, "           200164267 ",
                               Option::Some(" unique Kepler target identifier                ")),
            KeywordRecord::new(Keyword::CHANNEL, "                  68 ",
                               Option::Some(" CCD channel                                    ")),
            KeywordRecord::new(Keyword::MODULE, "                  19 ",
                               Option::Some(" CCD module                                     ")),
            KeywordRecord::new(Keyword::OUTPUT, "                   4 ",
                               Option::Some(" CCD output                                     ")),
            KeywordRecord::new(Keyword::CAMPAIGN, "'' ",
                               Option::Some(" Observing campaign number                                        ")),
            KeywordRecord::new(Keyword::DATA_REL, "'' ",
                               Option::Some(" data release version number                                      ")),
            KeywordRecord::new(Keyword::OBSMODE, "'long cadence'       ",
                               Option::Some(" observing mode                                 ")),
            KeywordRecord::new(Keyword::MISSION, "'K2      '           ",
                               Option::Some(" Mission name                                   ")),
            KeywordRecord::new(Keyword::TTABLEID, "'' ",
                               Option::Some(" target table id                                                  ")),
            KeywordRecord::new(Keyword::RADESYS, "'ICRS    '           ",
                               Option::Some(" reference frame of celestial coordinates       ")),
            KeywordRecord::new(Keyword::RA_OBJ, "'' ",
                               Option::Some(" [deg] right ascension                                            ")),
            KeywordRecord::new(Keyword::DEC_OBJ, "'' ",
                               Option::Some(" [deg] declination                                                ")),
            KeywordRecord::new(Keyword::EQUINOX, "              2000.0 ",
                               Option::Some(" equinox of celestial coordinate system         ")),
            KeywordRecord::new(Keyword::PMRA, " ",
                               Option::Some(" [arcsec/yr] RA proper motion                                       ")),
            KeywordRecord::new(Keyword::PMDEC, " ",
                               Option::Some(" [arcsec/yr] Dec proper motion                                      ")),
            KeywordRecord::new(Keyword::PMTOTAL, " ",
                               Option::Some(" [arcsec/yr] total proper motion                                    ")),
            KeywordRecord::new(Keyword::PARALLAX, " ",
                               Option::Some(" [arcsec] parallax                                                  ")),
            KeywordRecord::new(Keyword::GLON, " ",
                               Option::Some(" [deg] galactic longitude                                           ")),
            KeywordRecord::new(Keyword::GLAT, " ",
                               Option::Some(" [deg] galactic latitude                                            ")),
            KeywordRecord::new(Keyword::GMAG, " ",
                               Option::Some(" [mag] SDSS g band magnitude                                        ")),
            KeywordRecord::new(Keyword::RMAG, " ",
                               Option::Some(" [mag] SDSS r band magnitude                                        ")),
            KeywordRecord::new(Keyword::IMAG, " ",
                               Option::Some(" [mag] SDSS i band magnitude                                        ")),
            KeywordRecord::new(Keyword::ZMAG, " ",
                               Option::Some(" [mag] SDSS z band magnitude                                        ")),
            KeywordRecord::new(Keyword::JMAG, " ",
                               Option::Some(" [mag] J band magnitude from 2MASS                                  ")),
            KeywordRecord::new(Keyword::HMAG, " ",
                               Option::Some(" [mag] H band magnitude from 2MASS                                  ")),
            KeywordRecord::new(Keyword::KMAG, " ",
                               Option::Some(" [mag] K band magnitude from 2MASS                                  ")),
            KeywordRecord::new(Keyword::KEPMAG, " ",
                               Option::Some(" [mag] Kepler magnitude (Kp)                                        ")),
            KeywordRecord::new(Keyword::GRCOLOR, " ",
                               Option::Some(" [mag] (g-r) color, SDSS bands                                      ")),
            KeywordRecord::new(Keyword::JKCOLOR, " ",
                               Option::Some(" [mag] (J-K) color, 2MASS bands                                     ")),
            KeywordRecord::new(Keyword::GKCOLOR, " ",
                               Option::Some(" [mag] (g-K) color, SDSS g - 2MASS K                                ")),
            KeywordRecord::new(Keyword::TEFF, " ",
                               Option::Some(" [K] Effective temperature                                          ")),
            KeywordRecord::new(Keyword::LOGG, " ",
                               Option::Some(" [cm/s2] log10 surface gravity                                      ")),
            KeywordRecord::new(Keyword::FEH, " ",
                               Option::Some(" [log10([Fe/H])]  metallicity                                       ")),
            KeywordRecord::new(Keyword::EBMINUSV, " ",
                               Option::Some(" [mag] E(B-V) reddening                                             ")),
            KeywordRecord::new(Keyword::AV, " ",
                               Option::Some(" [mag] A_v extinction                                               ")),
            KeywordRecord::new(Keyword::RADIUS, " ",
                               Option::Some(" [solar radii] stellar radius                                       ")),
            KeywordRecord::new(Keyword::TMINDEX, " ",
                               Option::Some(" unique 2MASS catalog ID                                            ")),
            KeywordRecord::new(Keyword::CHECKSUM, "'7k7A7h637h697h69'   ",
                               Option::Some(" HDU checksum updated 2017-03-08T02:47:56       ")),
            KeywordRecord::new(Keyword::DATASUM, "'0       '           ",
                               Option::Some(" data unit checksum updated 2017-03-08T02:47:56 ")),
        ))
    }

    #[test]
    fn keyword_record_should_parse_a_keyword_record(){
        let data = "OBJECT  = 'EPIC 200164267'     / string version of target id                    "
            .as_bytes();

        let result = keyword_record(data);

        match result {
            IResult::Done(_,k) => {
                assert_eq!(k, KeywordRecord::new(
                    Keyword::OBJECT,
                    "'EPIC 200164267'     ",
                    Option::Some(" string version of target id                    ")
                ))
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn valuecomment_should_parse_a_valuecomment(){
        let data = "'EPIC 200164267'     / string version of target id                    "
            .as_bytes();

        let result = valuecomment(data);

        match result {
            IResult::Done(_, (value, comment)) => {
                assert_eq!(value, "'EPIC 200164267'     ");
                assert_eq!(comment, Option::Some(" string version of target id                    "));
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn character_string_should_parse_an_quote_delimited_string(){
        let data = "'EPIC 200164267'"
            .as_bytes();

        let result = character_string(data);

        match result {
            IResult::Done(_, value) => {
                assert_eq!(value, Value::CharacterString("EPIC 200164267"));
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn keyword_should_parse_a_keyword(){
        let data = "OBJECT  "
            .as_bytes();

        let result = keyword(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::OBJECT),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    #[allow(non_snake_case)]
    fn end_record_should_parse_an_END_record(){
        let data = "END                                                                             "
            .as_bytes();

        let result = end_record(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::END),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    #[allow(non_snake_case)]
    fn blank_record_should_parse_a_BLANK_record(){
        let data = "                                                                                "
            .as_bytes();

        let result = blank_record(data);

        match result {
            IResult::Done(_, record) => assert_eq!(record, BlankRecord),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }
}
<commit_msg>Refactor: Rename is_character_string_character<commit_after>//! The parser module is responsible for parsing FITS files.

use std::str;
use std::str::FromStr;
use super::types::{Fits, PrimaryHeader, KeywordRecord, Keyword, Value, BlankRecord};

named!(#[doc = "Will parse data from a FITS file into a `Fits` structure"], pub fits<&[u8], Fits>,
       do_parse!(
           ph: primary_header >>
               many0!(take!(2880)) >>
               (Fits::new(ph))
       ));

named!(primary_header<&[u8], PrimaryHeader>,
       do_parse!(
           records: many0!(keyword_record) >>
               end_record >>
               many0!(blank_record) >>
               (PrimaryHeader::new(records))
       ));

named!(keyword_record<&[u8], KeywordRecord>,
       do_parse!(
           key: keyword  >>
               tag!("= ") >>
           vc: valuecomment >>
               (KeywordRecord::new(key, vc.0, vc.1))
       ));

named!(keyword<&[u8], Keyword>,
       map_res!(
           map_res!(
               take!(8),
               str::from_utf8),
           Keyword::from_str
       ));

named!(valuecomment<&[u8], (&str, Option<&str>)>,
       flat_map!(
           take!(70),
           pair!(
               value,
               opt!(comment)
           )));

named!(value<&[u8], &str>,
       map_res!(
           is_not!("/"), // TODO Differentiate on the possible value types
           str::from_utf8
       )
);

named!(character_string<&[u8], Value>,
       map!(
           map_res!(
               delimited!(
                   tag!("'"),
                   take_while!(is_allowed_in_character_string),
                   tag!("'")
               ),
               str::from_utf8
           ),
           Value::CharacterString
       ));

fn is_allowed_in_character_string(chr: u8) -> bool {
    is_restricted_ascii(chr) && chr != 39
}

named!(comment<&[u8], &str>,
       map_res!(
           do_parse!(
               tag!("/") >>
                   comment: take_while!(is_comment_character) >>
                   (comment)
           ),
           str::from_utf8
       ));

fn is_comment_character(chr: u8) -> bool {
    is_restricted_ascii(chr)
}

fn is_restricted_ascii(chr: u8) -> bool {
    32u8 <= chr && chr <= 126u8
}

named!(end_record<&[u8], Keyword>,
       map!(
           flat_map!(
               take!(80),
               pair!(tag!("END"), many0!(tag!(" ")))
           ),
           |_| { Keyword::END }
       ));

named!(blank_record<&[u8], BlankRecord>,
       map!(
           count!(tag!(" "), 80),
           |_| { BlankRecord }
       ));

#[cfg(test)]
mod tests {
    use nom::{IResult};
    use super::super::types::{Fits, PrimaryHeader, KeywordRecord, Keyword, Value, BlankRecord};
    use super::{fits, primary_header, keyword_record, keyword, valuecomment, character_string, end_record, blank_record};

    #[test]
    fn it_should_parse_a_fits_file(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = fits(data);

        match result {
            IResult::Done(_, f) => {
                assert_eq!(f, Fits::new(long_cadence_header()));
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn primary_header_should_parse_a_primary_header(){
        let data = include_bytes!("../../assets/images/k2-trappist1-unofficial-tpf-long-cadence.fits");

        let result = primary_header(&data[0..(2*2880)]);

        match result {
            IResult::Done(_, h) => assert_eq!(h, long_cadence_header()),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    fn long_cadence_header<'a>() -> PrimaryHeader<'a> {
        PrimaryHeader::new(vec!(
            KeywordRecord::new(Keyword::SIMPLE, "                   T ",
                               Option::Some(" conforms to FITS standards                     ")),
            KeywordRecord::new(Keyword::BITPIX, "                   8 ",
                               Option::Some(" array data type                                ")),
            KeywordRecord::new(Keyword::NAXIS, "                   0 ",
                               Option::Some(" number of array dimensions                     ")),
            KeywordRecord::new(Keyword::EXTEND, "                   T ",
                               Option::Some(" file contains extensions                       ")),
            KeywordRecord::new(Keyword::NEXTEND, "                   2 ",
                               Option::Some(" number of standard extensions                  ")),
            KeywordRecord::new(Keyword::EXTNAME, "'PRIMARY '           ",
                               Option::Some(" name of extension                              ")),
            KeywordRecord::new(Keyword::EXTVER, "                   1 ",
                               Option::Some(" extension version number (not format version)  ")),
            KeywordRecord::new(Keyword::ORIGIN, "'Unofficial data product' ",
                               Option::Some(" institution responsible for creating this ")),
            KeywordRecord::new(Keyword::DATE, "'2017-03-08'         ",
                               Option::Some(" file creation date.                            ")),
            KeywordRecord::new(Keyword::CREATOR, "'kadenza '           ",
                               Option::Some(" pipeline job and program u                     ")),
            KeywordRecord::new(Keyword::PROCVER, "'2.1.dev '           ",
                               Option::Some(" SW version                                     ")),
            KeywordRecord::new(Keyword::FILEVER, "'0.0     '           ",
                               Option::Some(" file format version                            ")),
            KeywordRecord::new(Keyword::TIMVERSN, "'' ",
                               Option::Some(" OGIP memo number for file format                                 ")),
            KeywordRecord::new(Keyword::TELESCOP, "'Kepler  '           ",
                               Option::Some(" telescope                                      ")),
            KeywordRecord::new(Keyword::INSTRUME, "'Kepler Photometer'  ",
                               Option::Some(" detector type                                  ")),
            KeywordRecord::new(Keyword::OBJECT, "'EPIC 200164267'     ",
                               Option::Some(" string version of target id                    ")),
            KeywordRecord::new(Keyword::KEPLERID, "           200164267 ",
                               Option::Some(" unique Kepler target identifier                ")),
            KeywordRecord::new(Keyword::CHANNEL, "                  68 ",
                               Option::Some(" CCD channel                                    ")),
            KeywordRecord::new(Keyword::MODULE, "                  19 ",
                               Option::Some(" CCD module                                     ")),
            KeywordRecord::new(Keyword::OUTPUT, "                   4 ",
                               Option::Some(" CCD output                                     ")),
            KeywordRecord::new(Keyword::CAMPAIGN, "'' ",
                               Option::Some(" Observing campaign number                                        ")),
            KeywordRecord::new(Keyword::DATA_REL, "'' ",
                               Option::Some(" data release version number                                      ")),
            KeywordRecord::new(Keyword::OBSMODE, "'long cadence'       ",
                               Option::Some(" observing mode                                 ")),
            KeywordRecord::new(Keyword::MISSION, "'K2      '           ",
                               Option::Some(" Mission name                                   ")),
            KeywordRecord::new(Keyword::TTABLEID, "'' ",
                               Option::Some(" target table id                                                  ")),
            KeywordRecord::new(Keyword::RADESYS, "'ICRS    '           ",
                               Option::Some(" reference frame of celestial coordinates       ")),
            KeywordRecord::new(Keyword::RA_OBJ, "'' ",
                               Option::Some(" [deg] right ascension                                            ")),
            KeywordRecord::new(Keyword::DEC_OBJ, "'' ",
                               Option::Some(" [deg] declination                                                ")),
            KeywordRecord::new(Keyword::EQUINOX, "              2000.0 ",
                               Option::Some(" equinox of celestial coordinate system         ")),
            KeywordRecord::new(Keyword::PMRA, " ",
                               Option::Some(" [arcsec/yr] RA proper motion                                       ")),
            KeywordRecord::new(Keyword::PMDEC, " ",
                               Option::Some(" [arcsec/yr] Dec proper motion                                      ")),
            KeywordRecord::new(Keyword::PMTOTAL, " ",
                               Option::Some(" [arcsec/yr] total proper motion                                    ")),
            KeywordRecord::new(Keyword::PARALLAX, " ",
                               Option::Some(" [arcsec] parallax                                                  ")),
            KeywordRecord::new(Keyword::GLON, " ",
                               Option::Some(" [deg] galactic longitude                                           ")),
            KeywordRecord::new(Keyword::GLAT, " ",
                               Option::Some(" [deg] galactic latitude                                            ")),
            KeywordRecord::new(Keyword::GMAG, " ",
                               Option::Some(" [mag] SDSS g band magnitude                                        ")),
            KeywordRecord::new(Keyword::RMAG, " ",
                               Option::Some(" [mag] SDSS r band magnitude                                        ")),
            KeywordRecord::new(Keyword::IMAG, " ",
                               Option::Some(" [mag] SDSS i band magnitude                                        ")),
            KeywordRecord::new(Keyword::ZMAG, " ",
                               Option::Some(" [mag] SDSS z band magnitude                                        ")),
            KeywordRecord::new(Keyword::JMAG, " ",
                               Option::Some(" [mag] J band magnitude from 2MASS                                  ")),
            KeywordRecord::new(Keyword::HMAG, " ",
                               Option::Some(" [mag] H band magnitude from 2MASS                                  ")),
            KeywordRecord::new(Keyword::KMAG, " ",
                               Option::Some(" [mag] K band magnitude from 2MASS                                  ")),
            KeywordRecord::new(Keyword::KEPMAG, " ",
                               Option::Some(" [mag] Kepler magnitude (Kp)                                        ")),
            KeywordRecord::new(Keyword::GRCOLOR, " ",
                               Option::Some(" [mag] (g-r) color, SDSS bands                                      ")),
            KeywordRecord::new(Keyword::JKCOLOR, " ",
                               Option::Some(" [mag] (J-K) color, 2MASS bands                                     ")),
            KeywordRecord::new(Keyword::GKCOLOR, " ",
                               Option::Some(" [mag] (g-K) color, SDSS g - 2MASS K                                ")),
            KeywordRecord::new(Keyword::TEFF, " ",
                               Option::Some(" [K] Effective temperature                                          ")),
            KeywordRecord::new(Keyword::LOGG, " ",
                               Option::Some(" [cm/s2] log10 surface gravity                                      ")),
            KeywordRecord::new(Keyword::FEH, " ",
                               Option::Some(" [log10([Fe/H])]  metallicity                                       ")),
            KeywordRecord::new(Keyword::EBMINUSV, " ",
                               Option::Some(" [mag] E(B-V) reddening                                             ")),
            KeywordRecord::new(Keyword::AV, " ",
                               Option::Some(" [mag] A_v extinction                                               ")),
            KeywordRecord::new(Keyword::RADIUS, " ",
                               Option::Some(" [solar radii] stellar radius                                       ")),
            KeywordRecord::new(Keyword::TMINDEX, " ",
                               Option::Some(" unique 2MASS catalog ID                                            ")),
            KeywordRecord::new(Keyword::CHECKSUM, "'7k7A7h637h697h69'   ",
                               Option::Some(" HDU checksum updated 2017-03-08T02:47:56       ")),
            KeywordRecord::new(Keyword::DATASUM, "'0       '           ",
                               Option::Some(" data unit checksum updated 2017-03-08T02:47:56 ")),
        ))
    }

    #[test]
    fn keyword_record_should_parse_a_keyword_record(){
        let data = "OBJECT  = 'EPIC 200164267'     / string version of target id                    "
            .as_bytes();

        let result = keyword_record(data);

        match result {
            IResult::Done(_,k) => {
                assert_eq!(k, KeywordRecord::new(
                    Keyword::OBJECT,
                    "'EPIC 200164267'     ",
                    Option::Some(" string version of target id                    ")
                ))
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn valuecomment_should_parse_a_valuecomment(){
        let data = "'EPIC 200164267'     / string version of target id                    "
            .as_bytes();

        let result = valuecomment(data);

        match result {
            IResult::Done(_, (value, comment)) => {
                assert_eq!(value, "'EPIC 200164267'     ");
                assert_eq!(comment, Option::Some(" string version of target id                    "));
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn character_string_should_parse_an_quote_delimited_string(){
        let data = "'EPIC 200164267'"
            .as_bytes();

        let result = character_string(data);

        match result {
            IResult::Done(_, value) => {
                assert_eq!(value, Value::CharacterString("EPIC 200164267"));
            },
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    fn keyword_should_parse_a_keyword(){
        let data = "OBJECT  "
            .as_bytes();

        let result = keyword(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::OBJECT),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    #[allow(non_snake_case)]
    fn end_record_should_parse_an_END_record(){
        let data = "END                                                                             "
            .as_bytes();

        let result = end_record(data);

        match result {
            IResult::Done(_, keyword) => assert_eq!(keyword, Keyword::END),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }

    #[test]
    #[allow(non_snake_case)]
    fn blank_record_should_parse_a_BLANK_record(){
        let data = "                                                                                "
            .as_bytes();

        let result = blank_record(data);

        match result {
            IResult::Done(_, record) => assert_eq!(record, BlankRecord),
            IResult::Error(_) => panic!("Did not expect an error"),
            IResult::Incomplete(_) => panic!("Did not expect to be incomplete")
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::{create_dir_all, File};
use std::io::Write;

use clap::ArgMatches;

use error::KawsResult;

pub struct Repository<'a> {
    name: &'a str,
    terraform_source: &'a str,
}

impl<'a> Repository<'a> {
    pub fn new(matches: &'a ArgMatches) -> Self {
        Repository {
            name: matches.value_of("name").expect("clap should have required name"),
            terraform_source: matches.value_of("terraform-source").unwrap_or(
                concat!("github.com/InQuicker/kaws//terraform?ref=v", env!("CARGO_PKG_VERSION")),
            ),
        }
    }

    pub fn create(&self) -> KawsResult {
        create_dir_all(format!("{}/clusters", self.name))?;
        create_dir_all(format!("{}/terraform", self.name))?;

        let mut gitignore = File::create(format!("{}/.gitignore", self.name))?;
        writeln!(&mut gitignore, ".terraform")?;

        let mut main_tf = File::create(format!("{}/terraform/kaws.tf", self.name))?;
        write!(
            &mut main_tf,
r#"module "kaws" {{
    source = "{}"

    account_id = "${{var.kaws_account_id}}"
    availability_zone = "${{var.kaws_availability_zone}}"
    cluster = "${{var.kaws_cluster}}"
    coreos_ami = "${{var.kaws_coreos_ami}}"
    domain = "${{var.kaws_domain}}"
    iam_users = ["${{var.kaws_iam_users}}"]
    instance_size = "${{var.kaws_instance_size}}"
    masters_max_size = "${{var.kaws_masters_max_size}}"
    masters_min_size = "${{var.kaws_masters_min_size}}"
    nodes_max_size = "${{var.kaws_nodes_max_size}}"
    nodes_min_size = "${{var.kaws_nodes_min_size}}"
    propagating_vgws = ["${{var.kaws_propagating_vgws}}"]
    rbac_super_user = "${{var.kaws_rbac_super_user}}"
    region = "${{var.kaws_region}}"
    ssh_keys = ["${{var.kaws_ssh_keys}}"]
    version = "${{var.kaws_version}}"
    zone_id = "${{var.kaws_zone_id}}"
}}

variable "kaws_account_id" {{
  description = "Numerical account ID of the AWS account to use, e.g. `12345678`"
}}

variable "kaws_availability_zone" {{
  description = "Availability Zone for etcd instances and EBS volumes, e.g. `us-east-1a`"
}}

variable "kaws_cluster" {{
  description = "The target cluster's name, e.g. `production`"
}}

variable "kaws_coreos_ami" {{
  description = "The AMI ID for the CoreOS image to use for servers, e.g. `ami-1234abcd`"
}}

variable "kaws_domain" {{
  description = "The domain name for the cluster, e.g. `example.com`"
}}

variable "kaws_iam_users" {{
  description = "A list of IAM user names who will have access to cluster PKI secrets"
  type = "list"
}}

variable "kaws_instance_size" {{
  description = "The EC2 instance size, e.g. `m3.medium`"
}}

variable "kaws_masters_max_size" {{
  description = "The maximum number of EC2 instances the Kubernetes masters may autoscale to"
}}

variable "kaws_masters_min_size" {{
  description = "The minimum number of EC2 instances the Kubernetes masters may autoscale to"
}}

variable "kaws_nodes_max_size" {{
  description = "The maximum number of EC2 instances the Kubernetes nodes may autoscale to"
}}

variable "kaws_nodes_min_size" {{
  description = "The minimum number of EC2 instances the Kubernetes nodes may autoscale to"
}}

variable "kaws_propagating_vgws" {{
  description = "A list of virtual gateways that should propagate routes to the route table"
  type = "list"
}}

variable "kaws_rbac_super_user" {{
  description = "The Kubernetes username of an administrator who will set up initial RBAC policies."
}}

variable "kaws_region" {{
  description = "The AWS Region where the cluster will live, e.g. `us-east-1`"
}}

variable "kaws_ssh_keys" {{
  description = "SSH public keys to add to ~/.ssh/authorized_keys on each server"
  type = "list"
}}

variable "kaws_version" {{
  description = "Version of Kubernetes to use, e.g. `1.0.0`"
}}

variable "kaws_zone_id" {{
  description = "Zone ID of the Route 53 hosted zone, e.g. `Z111111QQQQQQQ`"
}}
"#,
            self.terraform_source,
        )?;

        Ok(Some(format!("New repository \"{}\" created!", self.name)))
    }
}
<commit_msg>Remove "v" from the beginning of the Git tag referenced in the TF module source.<commit_after>use std::fs::{create_dir_all, File};
use std::io::Write;

use clap::ArgMatches;

use error::KawsResult;

pub struct Repository<'a> {
    name: &'a str,
    terraform_source: &'a str,
}

impl<'a> Repository<'a> {
    pub fn new(matches: &'a ArgMatches) -> Self {
        Repository {
            name: matches.value_of("name").expect("clap should have required name"),
            terraform_source: matches.value_of("terraform-source").unwrap_or(
                concat!("github.com/InQuicker/kaws//terraform?ref=", env!("CARGO_PKG_VERSION")),
            ),
        }
    }

    pub fn create(&self) -> KawsResult {
        create_dir_all(format!("{}/clusters", self.name))?;
        create_dir_all(format!("{}/terraform", self.name))?;

        let mut gitignore = File::create(format!("{}/.gitignore", self.name))?;
        writeln!(&mut gitignore, ".terraform")?;

        let mut main_tf = File::create(format!("{}/terraform/kaws.tf", self.name))?;
        write!(
            &mut main_tf,
r#"module "kaws" {{
    source = "{}"

    account_id = "${{var.kaws_account_id}}"
    availability_zone = "${{var.kaws_availability_zone}}"
    cluster = "${{var.kaws_cluster}}"
    coreos_ami = "${{var.kaws_coreos_ami}}"
    domain = "${{var.kaws_domain}}"
    iam_users = ["${{var.kaws_iam_users}}"]
    instance_size = "${{var.kaws_instance_size}}"
    masters_max_size = "${{var.kaws_masters_max_size}}"
    masters_min_size = "${{var.kaws_masters_min_size}}"
    nodes_max_size = "${{var.kaws_nodes_max_size}}"
    nodes_min_size = "${{var.kaws_nodes_min_size}}"
    propagating_vgws = ["${{var.kaws_propagating_vgws}}"]
    rbac_super_user = "${{var.kaws_rbac_super_user}}"
    region = "${{var.kaws_region}}"
    ssh_keys = ["${{var.kaws_ssh_keys}}"]
    version = "${{var.kaws_version}}"
    zone_id = "${{var.kaws_zone_id}}"
}}

variable "kaws_account_id" {{
  description = "Numerical account ID of the AWS account to use, e.g. `12345678`"
}}

variable "kaws_availability_zone" {{
  description = "Availability Zone for etcd instances and EBS volumes, e.g. `us-east-1a`"
}}

variable "kaws_cluster" {{
  description = "The target cluster's name, e.g. `production`"
}}

variable "kaws_coreos_ami" {{
  description = "The AMI ID for the CoreOS image to use for servers, e.g. `ami-1234abcd`"
}}

variable "kaws_domain" {{
  description = "The domain name for the cluster, e.g. `example.com`"
}}

variable "kaws_iam_users" {{
  description = "A list of IAM user names who will have access to cluster PKI secrets"
  type = "list"
}}

variable "kaws_instance_size" {{
  description = "The EC2 instance size, e.g. `m3.medium`"
}}

variable "kaws_masters_max_size" {{
  description = "The maximum number of EC2 instances the Kubernetes masters may autoscale to"
}}

variable "kaws_masters_min_size" {{
  description = "The minimum number of EC2 instances the Kubernetes masters may autoscale to"
}}

variable "kaws_nodes_max_size" {{
  description = "The maximum number of EC2 instances the Kubernetes nodes may autoscale to"
}}

variable "kaws_nodes_min_size" {{
  description = "The minimum number of EC2 instances the Kubernetes nodes may autoscale to"
}}

variable "kaws_propagating_vgws" {{
  description = "A list of virtual gateways that should propagate routes to the route table"
  type = "list"
}}

variable "kaws_rbac_super_user" {{
  description = "The Kubernetes username of an administrator who will set up initial RBAC policies."
}}

variable "kaws_region" {{
  description = "The AWS Region where the cluster will live, e.g. `us-east-1`"
}}

variable "kaws_ssh_keys" {{
  description = "SSH public keys to add to ~/.ssh/authorized_keys on each server"
  type = "list"
}}

variable "kaws_version" {{
  description = "Version of Kubernetes to use, e.g. `1.0.0`"
}}

variable "kaws_zone_id" {{
  description = "Zone ID of the Route 53 hosted zone, e.g. `Z111111QQQQQQQ`"
}}
"#,
            self.terraform_source,
        )?;

        Ok(Some(format!("New repository \"{}\" created!", self.name)))
    }
}
<|endoftext|>