<commit_before>/// Convert a base 256 (byte) to a hexadecimal representation
#[inline]
pub fn to_hex(from: u8) -> (u8, u8) {
    (from >> 4, from & 0b1111)
}

/// Convert two hexadecimal digits to a byte
#[inline]
pub fn from_hex((a, b): (u8, u8)) -> u8 {
    (a << 4) + b
}

#[test]
fn test_from_hex() {
    for i in 0..255 {
        assert_eq!(from_hex(to_hex(i)), i);
    }
}

/// Convert hex to ascii
#[inline]
pub fn hex_to_ascii(b: u8) -> u8 {
    match b {
        0...9 => b'0' + b,
        _ => b'a' - 10 + b,
    }
}

#[test]
fn test_hex2ascii() {
    assert_eq!(hex_to_ascii(0x0), b'0');
    assert_eq!(hex_to_ascii(0x1), b'1');
    assert_eq!(hex_to_ascii(0x2), b'2');
    assert_eq!(hex_to_ascii(0x3), b'3');
    assert_eq!(hex_to_ascii(0x4), b'4');

    assert_eq!(hex_to_ascii(0xa), b'a');
    assert_eq!(hex_to_ascii(0xb), b'b');
    assert_eq!(hex_to_ascii(0xc), b'c');
}

/// Convert ascii to hex
#[inline]
pub fn ascii_to_hex(b: u8) -> u8 {
    match b {
        b'0'...b'9' => b - b'0',
        _ => b - b'a' + 10,
    }
}

#[test]
fn ascii2hex() {
    for i in 0..16 {
        assert_eq!(ascii_to_hex(hex_to_ascii(i)), i);
    }
}

/// Convert a base 256 (byte) to an octal representation
#[inline]
pub fn to_oct(from: u8) -> (u8, u8, u8) {
    (from >> 6, (from >> 3) & 0b111, from & 0b111)
}

#[test]
fn test_hex() {
    for i in 0..16 {
        assert_eq!(to_hex(i), (0, i));
    }

    assert_eq!(to_hex(0xDE), (0xD, 0xE));
    assert_eq!(to_hex(0xAD), (0xA, 0xD));
    assert_eq!(to_hex(0xBE), (0xB, 0xE));
    assert_eq!(to_hex(0xAF), (0xA, 0xF));

    assert_eq!(to_hex(0x12), (1, 2));
    assert_eq!(to_hex(0xA5), (0xA, 5));
    assert_eq!(to_hex(0x42), (4, 2));
}

#[test]
fn test_oct() {
    assert_eq!(to_oct(0o102), (1, 0, 2));
    assert_eq!(to_oct(0o002), (0, 0, 2));
    assert_eq!(to_oct(0o000), (0, 0, 0));
    assert_eq!(to_oct(0o111), (1, 1, 1));
    assert_eq!(to_oct(0o277), (2, 7, 7));
}
<commit_msg>Move tests to seperate module<commit_after>/// Convert a base 256 (byte) to a hexadecimal representation
#[inline]
pub fn to_hex(from: u8) -> (u8, u8) {
    (from >> 4, from & 0b1111)
}

/// Convert two hexadecimal digits to a byte
#[inline]
pub fn from_hex((a, b): (u8, u8)) -> u8 {
    (a << 4) + b
}

/// Convert hex to ascii
#[inline]
pub fn hex_to_ascii(b: u8) -> u8 {
    match b {
        0...9 => b'0' + b,
        _ => b'a' - 10 + b,
    }
}

/// Convert ascii to hex
#[inline]
pub fn ascii_to_hex(b: u8) -> u8 {
    match b {
        b'0'...b'9' => b - b'0',
        _ => b - b'a' + 10,
    }
}

/// Convert a base 256 (byte) to an octal representation
#[inline]
pub fn to_oct(from: u8) -> (u8, u8, u8) {
    (from >> 6, (from >> 3) & 0b111, from & 0b111)
}

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

    #[test]
    fn test_from_hex() {
        for i in 0..255 {
            assert_eq!(from_hex(to_hex(i)), i);
        }
    }

    #[test]
    fn test_hex2ascii() {
        assert_eq!(hex_to_ascii(0x0), b'0');
        assert_eq!(hex_to_ascii(0x1), b'1');
        assert_eq!(hex_to_ascii(0x2), b'2');
        assert_eq!(hex_to_ascii(0x3), b'3');
        assert_eq!(hex_to_ascii(0x4), b'4');

        assert_eq!(hex_to_ascii(0xa), b'a');
        assert_eq!(hex_to_ascii(0xb), b'b');
        assert_eq!(hex_to_ascii(0xc), b'c');
    }

    #[test]
    fn ascii2hex() {
        for i in 0..16 {
            assert_eq!(ascii_to_hex(hex_to_ascii(i)), i);
        }
    }

    #[test]
    fn test_hex() {
        for i in 0..16 {
            assert_eq!(to_hex(i), (0, i));
        }

        assert_eq!(to_hex(0xDE), (0xD, 0xE));
        assert_eq!(to_hex(0xAD), (0xA, 0xD));
        assert_eq!(to_hex(0xBE), (0xB, 0xE));
        assert_eq!(to_hex(0xAF), (0xA, 0xF));

        assert_eq!(to_hex(0x12), (1, 2));
        assert_eq!(to_hex(0xA5), (0xA, 5));
        assert_eq!(to_hex(0x42), (4, 2));
    }

    #[test]
    fn test_oct() {
        assert_eq!(to_oct(0o102), (1, 0, 2));
        assert_eq!(to_oct(0o002), (0, 0, 2));
        assert_eq!(to_oct(0o000), (0, 0, 0));
        assert_eq!(to_oct(0o111), (1, 1, 1));
        assert_eq!(to_oct(0o277), (2, 7, 7));
    }
}
<|endoftext|>


<commit_before>enum Register8 {
    A, F,
    B, C,
    D, E,
    H, L
}

enum Register16 {
    AF, BC,
    DE, HL,
    SP, PC
}

enum Flag {
    Z, N,
    H, C
}

struct Cpu {

    /// Accumulator register
    a: u8,
    /// Flags register
    f: u8,
    b: u8,
    c: u8,
    d: u8,
    e: u8,
    h: u8,
    l: u8,
    sp: u16,
    pc: u16

}

macro_rules! high_byte {
    ($x:expr) => { ($x >> 8) as u8 };
}

macro_rules! low_byte {
    ($x:expr) => { $x as u8 };
}

macro_rules! join_bytes {
    ($a:expr, $b:expr) => ({
        let mut join: u16 = $b as u16;
        join |= ($a as u16) << 8;
        join
    })
}

impl Cpu {

    /// Init a new Cpu instance
    fn new() -> Cpu {
        Cpu {
            a: 0x0,
            f: 0x0,
            b: 0x0,
            c: 0x0,
            d: 0x0,
            e: 0x0,
            h: 0x0,
            l: 0x0,
            sp: 0x00,
            pc: 0x00
        }
    }

    /// Get a 8bit value from register
    fn get_8(&self, reg: Register8) -> u8 {
        match reg {
            Register8::A => self.a,
            Register8::F => self.f,
            Register8::B => self.b,
            Register8::C => self.c,
            Register8::D => self.d,
            Register8::E => self.e,
            Register8::H => self.h,
            Register8::L => self.l,
        }
    }

    /// Set a 8bit value to a register
    fn set_8(&mut self, reg: Register8, v: u8) {
        match reg {
            Register8::A => self.a = v,
            Register8::F => self.f = v,
            Register8::B => self.b = v,
            Register8::C => self.c = v,
            Register8::D => self.d = v,
            Register8::E => self.e = v,
            Register8::H => self.h = v,
            Register8::L => self.l = v,
        };
    }

    /// Get a 16bit value from a register
    fn get_16(&self, reg: Register16) -> u16 {
        match reg {
            Register16::AF => { join_bytes!(self.a, self.f) }
            Register16::BC => { join_bytes!(self.b, self.c) }
            Register16::DE => { join_bytes!(self.d, self.e) }
            Register16::HL => { join_bytes!(self.h, self.l) }
            Register16::SP => self.sp,
            Register16::PC => self.pc
        }
    }

    /// Set a 16bit value to a register
    fn set_16(&mut self, reg: Register16, v: u16) {
        match reg {
            Register16::AF => {
                self.a = high_byte!(v);
                self.f = low_byte!(v);
            }
            Register16::BC => {
                self.b = high_byte!(v);
                self.c = low_byte!(v);
            }
            Register16::DE => {
                self.d = high_byte!(v);
                self.e = low_byte!(v);
            }
            Register16::HL => {
                self.h = high_byte!(v);
                self.l = low_byte!(v);
            }
            Register16::SP => self.sp = v,
            Register16::PC => self.pc = v
        }
    }

    /// Set a flags
    fn set_flag(&mut self, flag: Flag, set: bool) {
        let f = self.get_8(Register8::F);
        match (flag, set) {
            (Flag::Z, true) => { self.set_8(Register8::F, (f | 0b10000000)) }
            (Flag::N, true) => { self.set_8(Register8::F, (f | 0b01000000)) }
            (Flag::H, true) => { self.set_8(Register8::F, (f | 0b00100000)) }
            (Flag::C, true) => { self.set_8(Register8::F, (f | 0b00010000)) }
            (Flag::Z, false) => { self.set_8(Register8::F, (f & 0b01111111)) }
            (Flag::N, false) => { self.set_8(Register8::F, (f & 0b10111111)) }
            (Flag::H, false) => { self.set_8(Register8::F, (f & 0b11011111)) }
            (Flag::C, false) => { self.set_8(Register8::F, (f & 0b11101111)) }
        }
    }

}

#[test]
fn set_get() {
    let mut cpu = Cpu::new();

    cpu.set_8(Register8::A, 50);
    cpu.set_8(Register8::F, 51);
    cpu.set_8(Register8::B, 52);
    cpu.set_8(Register8::C, 53);
    cpu.set_8(Register8::D, 54);
    cpu.set_8(Register8::E, 55);
    cpu.set_8(Register8::H, 56);
    cpu.set_8(Register8::L, 57);
    assert_eq!(cpu.get_8(Register8::A), 50);
    assert_eq!(cpu.get_8(Register8::F), 51);
    assert_eq!(cpu.get_8(Register8::B), 52);
    assert_eq!(cpu.get_8(Register8::C), 53);
    assert_eq!(cpu.get_8(Register8::D), 54);
    assert_eq!(cpu.get_8(Register8::E), 55);
    assert_eq!(cpu.get_8(Register8::H), 56);
    assert_eq!(cpu.get_8(Register8::L), 57);

    cpu.set_16(Register16::AF, 50_000);
    cpu.set_16(Register16::BC, 51_000);
    cpu.set_16(Register16::DE, 52_000);
    cpu.set_16(Register16::HL, 53_000);
    cpu.set_16(Register16::SP, 54_000);
    cpu.set_16(Register16::PC, 55_000);
    assert_eq!(cpu.get_16(Register16::AF), 50_000);
    assert_eq!(cpu.get_16(Register16::BC), 51_000);
    assert_eq!(cpu.get_16(Register16::DE), 52_000);
    assert_eq!(cpu.get_16(Register16::HL), 53_000);
    assert_eq!(cpu.get_16(Register16::SP), 54_000);
    assert_eq!(cpu.get_16(Register16::PC), 55_000);
}

#[test]
fn flags() {
    let mut cpu = Cpu::new();

    cpu.set_flag(Flag::Z, true);
    assert_eq!(cpu.get_8(Register8::F), 0b10000000);
    cpu.set_flag(Flag::N, true);
    assert_eq!(cpu.get_8(Register8::F), 0b11000000);
    cpu.set_flag(Flag::H, true);
    assert_eq!(cpu.get_8(Register8::F), 0b11100000);
    cpu.set_flag(Flag::C, true);
    assert_eq!(cpu.get_8(Register8::F), 0b11110000);

    cpu.set_flag(Flag::Z, false);
    assert_eq!(cpu.get_8(Register8::F), 0b01110000);
    cpu.set_flag(Flag::N, false);
    assert_eq!(cpu.get_8(Register8::F), 0b00110000);
    cpu.set_flag(Flag::H, false);
    assert_eq!(cpu.get_8(Register8::F), 0b00010000);
    cpu.set_flag(Flag::C, false);
    assert_eq!(cpu.get_8(Register8::F), 0b00000000);
}
<commit_msg>set functions to public and impl debug<commit_after>use std::fmt;

pub enum Register8 {
    A, F,
    B, C,
    D, E,
    H, L
}

pub enum Register16 {
    AF, BC,
    DE, HL,
    SP, PC
}

pub enum Flag {
    Z, N,
    H, C
}

pub struct Cpu {

    /// Accumulator register
    a: u8,
    /// Flags register
    f: u8,
    b: u8,
    c: u8,
    d: u8,
    e: u8,
    h: u8,
    l: u8,
    sp: u16,
    pc: u16

}

macro_rules! high_byte {
    ($x:expr) => { ($x >> 8) as u8 };
}

macro_rules! low_byte {
    ($x:expr) => { $x as u8 };
}

macro_rules! join_bytes {
    ($a:expr, $b:expr) => ({
        let mut join: u16 = $b as u16;
        join |= ($a as u16) << 8;
        join
    })
}

impl Cpu {

    /// Init a new Cpu instance
    pub fn new() -> Cpu {
        Cpu {
            a: 0x0,
            f: 0x0,
            b: 0x0,
            c: 0x0,
            d: 0x0,
            e: 0x0,
            h: 0x0,
            l: 0x0,
            sp: 0x00,
            pc: 0x00
        }
    }

    /// Get a 8bit value from register
    pub fn get_8(&self, reg: Register8) -> u8 {
        match reg {
            Register8::A => self.a,
            Register8::F => self.f,
            Register8::B => self.b,
            Register8::C => self.c,
            Register8::D => self.d,
            Register8::E => self.e,
            Register8::H => self.h,
            Register8::L => self.l,
        }
    }

    /// Set a 8bit value to a register
    pub fn set_8(&mut self, reg: Register8, v: u8) {
        match reg {
            Register8::A => self.a = v,
            Register8::F => self.f = v,
            Register8::B => self.b = v,
            Register8::C => self.c = v,
            Register8::D => self.d = v,
            Register8::E => self.e = v,
            Register8::H => self.h = v,
            Register8::L => self.l = v,
        };
    }

    /// Get a 16bit value from a register
    pub fn get_16(&self, reg: Register16) -> u16 {
        match reg {
            Register16::AF => { join_bytes!(self.a, self.f) }
            Register16::BC => { join_bytes!(self.b, self.c) }
            Register16::DE => { join_bytes!(self.d, self.e) }
            Register16::HL => { join_bytes!(self.h, self.l) }
            Register16::SP => self.sp,
            Register16::PC => self.pc
        }
    }

    /// Set a 16bit value to a register
    pub fn set_16(&mut self, reg: Register16, v: u16) {
        match reg {
            Register16::AF => {
                self.a = high_byte!(v);
                self.f = low_byte!(v);
            }
            Register16::BC => {
                self.b = high_byte!(v);
                self.c = low_byte!(v);
            }
            Register16::DE => {
                self.d = high_byte!(v);
                self.e = low_byte!(v);
            }
            Register16::HL => {
                self.h = high_byte!(v);
                self.l = low_byte!(v);
            }
            Register16::SP => self.sp = v,
            Register16::PC => self.pc = v
        }
    }

    /// Set a flags
    pub fn set_flag(&mut self, flag: Flag, set: bool) {
        let f = self.get_8(Register8::F);
        match (flag, set) {
            (Flag::Z, true) => { self.set_8(Register8::F, (f | 0b10000000)) }
            (Flag::N, true) => { self.set_8(Register8::F, (f | 0b01000000)) }
            (Flag::H, true) => { self.set_8(Register8::F, (f | 0b00100000)) }
            (Flag::C, true) => { self.set_8(Register8::F, (f | 0b00010000)) }
            (Flag::Z, false) => { self.set_8(Register8::F, (f & 0b01111111)) }
            (Flag::N, false) => { self.set_8(Register8::F, (f & 0b10111111)) }
            (Flag::H, false) => { self.set_8(Register8::F, (f & 0b11011111)) }
            (Flag::C, false) => { self.set_8(Register8::F, (f & 0b11101111)) }
        }
    }

}

impl fmt::Debug for Cpu {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "=== CPU DEBUG ===\n\
            > A        <{:#x}> ({0})\n\
            > F (flag) <{:#x}> ({1})\n\
            > B        <{:#x}> ({2})\n\
            > C        <{:#x}> ({3})\n\
            > D        <{:#x}> ({4})\n\
            > E        <{:#x}> ({5})\n\
            > H        <{:#x}> ({6})\n\
            > L        <{:#x}> ({7})\n\
            > SP       <{:#x}> ({8})\n\
            > PC       <{:#x}> ({9})",
            self.get_8(Register8::A),
            self.get_8(Register8::F),
            self.get_8(Register8::B),
            self.get_8(Register8::C),
            self.get_8(Register8::D),
            self.get_8(Register8::E),
            self.get_8(Register8::H),
            self.get_8(Register8::L),
            self.get_16(Register16::SP),
            self.get_16(Register16::PC))
    }
}

#[test]
fn set_get() {
    let mut cpu = Cpu::new();

    cpu.set_8(Register8::A, 50);
    cpu.set_8(Register8::F, 51);
    cpu.set_8(Register8::B, 52);
    cpu.set_8(Register8::C, 53);
    cpu.set_8(Register8::D, 54);
    cpu.set_8(Register8::E, 55);
    cpu.set_8(Register8::H, 56);
    cpu.set_8(Register8::L, 57);
    assert_eq!(cpu.get_8(Register8::A), 50);
    assert_eq!(cpu.get_8(Register8::F), 51);
    assert_eq!(cpu.get_8(Register8::B), 52);
    assert_eq!(cpu.get_8(Register8::C), 53);
    assert_eq!(cpu.get_8(Register8::D), 54);
    assert_eq!(cpu.get_8(Register8::E), 55);
    assert_eq!(cpu.get_8(Register8::H), 56);
    assert_eq!(cpu.get_8(Register8::L), 57);

    cpu.set_16(Register16::AF, 50_000);
    cpu.set_16(Register16::BC, 51_000);
    cpu.set_16(Register16::DE, 52_000);
    cpu.set_16(Register16::HL, 53_000);
    cpu.set_16(Register16::SP, 54_000);
    cpu.set_16(Register16::PC, 55_000);
    assert_eq!(cpu.get_16(Register16::AF), 50_000);
    assert_eq!(cpu.get_16(Register16::BC), 51_000);
    assert_eq!(cpu.get_16(Register16::DE), 52_000);
    assert_eq!(cpu.get_16(Register16::HL), 53_000);
    assert_eq!(cpu.get_16(Register16::SP), 54_000);
    assert_eq!(cpu.get_16(Register16::PC), 55_000);
    println!("{:?}", cpu);
}

#[test]
fn flags() {
    let mut cpu = Cpu::new();

    cpu.set_flag(Flag::Z, true);
    assert_eq!(cpu.get_8(Register8::F), 0b10000000);
    cpu.set_flag(Flag::N, true);
    assert_eq!(cpu.get_8(Register8::F), 0b11000000);
    cpu.set_flag(Flag::H, true);
    assert_eq!(cpu.get_8(Register8::F), 0b11100000);
    cpu.set_flag(Flag::C, true);
    assert_eq!(cpu.get_8(Register8::F), 0b11110000);

    cpu.set_flag(Flag::Z, false);
    assert_eq!(cpu.get_8(Register8::F), 0b01110000);
    cpu.set_flag(Flag::N, false);
    assert_eq!(cpu.get_8(Register8::F), 0b00110000);
    cpu.set_flag(Flag::H, false);
    assert_eq!(cpu.get_8(Register8::F), 0b00010000);
    cpu.set_flag(Flag::C, false);
    assert_eq!(cpu.get_8(Register8::F), 0b00000000);
}
<|endoftext|>


<commit_before>#![allow(experimental)]

use std::io::{File,fs};
//use std::io::process::Command;
use std::path::posix::Path;
use std::os::{homedir};
#[cfg(test)] use std::rand::random;
#[cfg(test)] use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = if muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
      Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string()))
    } else {
      create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
      create_project_file(path)
    } else {
      println!("Project already exists.");
    }
}

fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(()) => (), // succeeded
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
//    Command::new("vim").arg(format!("{}", path.display())).detached();
}

fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (), // succeeded
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    path.clone()
}

fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

#[cfg(test)]
fn random_name() -> String {
  format!("test_{}", random::<f64>())
}

#[test]
fn muxed_dir_exists_returns_false() {
  assert!(!muxed_dir_exists(&random_name()));
}

#[test]
fn muxed_dir_exists_returns_true() {
  let dir = random_name();
  create_muxed_dir(&dir);
  assert!(muxed_dir_exists(&dir));

  let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
  fs::rmdir_recursive(muxed_path);
}

#[test]
fn creates_muxed_dir() {
    let dir = random_name();
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    fs::rmdir_recursive(muxed_path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    fs::unlink(path);
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        fs::unlink(path);
    })
}
<commit_msg>Handle file io with proper error handling.<commit_after>#![allow(experimental)]

use std::io::{File,fs};
//use std::io::process::Command;
use std::path::posix::Path;
use std::os::{homedir};
#[cfg(test)] use std::rand::random;
#[cfg(test)] use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = if muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
      Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string()))
    } else {
      create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
      create_project_file(path)
    } else {
      println!("Project already exists.");
    }
}

fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(()) => (), // succeeded
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
//    Command::new("vim").arg(format!("{}", path.display())).detached();
}

fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (), // succeeded
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    path.clone()
}

fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

#[cfg(test)]
fn random_name() -> String {
  format!("test_{}", random::<f64>())
}

#[test]
fn muxed_dir_exists_returns_false() {
  assert!(!muxed_dir_exists(&random_name()));
}

#[test]
fn muxed_dir_exists_returns_true() {
  let dir = random_name();
  create_muxed_dir(&dir);
  assert!(muxed_dir_exists(&dir));

  let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
  match fs::rmdir_recursive(muxed_path) {
      Ok(()) => (), // succeeded
      Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
  }
}

#[test]
fn creates_muxed_dir() {
    let dir = random_name();
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    match fs::rmdir_recursive(muxed_path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to remove the path {} with error {}", muxed_path.display(), e),
    }
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    match fs::unlink(path) {
        Ok(()) => (), // succeeded
        Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
    }
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = random_name();
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        match fs::unlink(path) {
            Ok(()) => (), // succeeded
            Err(e) => println!("Failed to unlink the path {} with error {}", path.display(), e),
        }
    })
}
<|endoftext|>


<commit_before>use super::{pointer::Pointer, Heap};
use crate::{
    builtin_functions::BuiltinFunction,
    compiler::{
        hir_to_lir::HirToLir,
        lir::{Instruction, Lir},
    },
    database::Database,
    module::Module,
};
use itertools::Itertools;
use num_bigint::BigInt;
use std::{
    collections::{hash_map::DefaultHasher, HashMap},
    hash::{Hash, Hasher},
    ops::Deref,
};

#[derive(Clone)]
pub struct Object {
    pub reference_count: usize,
    pub data: Data,
}
#[derive(Clone)]
pub enum Data {
    Int(Int),
    Text(Text),
    Symbol(Symbol),
    Struct(Struct),
    Closure(Closure),
    Builtin(Builtin),
}

#[derive(Clone)]
pub struct Int {
    pub value: BigInt,
}

#[derive(Clone)]
pub struct Text {
    pub value: String,
}

#[derive(Clone)]
pub struct Symbol {
    // TODO: For better memory efficiency, store the symbol as a null-terminated
    // string.
    pub value: String,
}

#[derive(Default, Clone)]
pub struct Struct {
    // TODO: Choose a more efficient representation.
    pub fields: Vec<(u64, Pointer, Pointer)>, // hash, key, and value
}

#[derive(Clone)]
pub struct Closure {
    pub captured: Vec<Pointer>,
    pub num_args: usize,
    pub body: Vec<Instruction>,
}

#[derive(Clone)]
pub struct Builtin {
    pub function: BuiltinFunction,
}

impl Struct {
    pub fn from_fields(heap: &Heap, fields: HashMap<Pointer, Pointer>) -> Self {
        let mut s = Self::default();
        for (key, value) in fields {
            s.insert(heap, key, value);
        }
        s
    }
    fn insert(&mut self, heap: &Heap, key: Pointer, value: Pointer) {
        let hash = key.hash(heap);
        for (existing_hash, existing_key, existing_value) in &mut self.fields {
            if hash != *existing_hash {
                continue;
            }
            if existing_key.equals(heap, key) {
                *existing_value = value;
                return;
            }
        }
        let entry = (hash, key, value);
        if let Some(index) = self
            .fields
            .iter()
            .position(|(the_hash, _, _)| *the_hash > hash)
        {
            self.fields.insert(index, entry);
        } else {
            self.fields.push(entry);
        }
    }
    pub fn get(&self, heap: &Heap, key: Pointer) -> Option<Pointer> {
        let hash = key.hash(heap);
        Some(
            self.fields
                .iter()
                .find(|(field_hash, field_key, _)| {
                    hash == *field_hash && key.equals(heap, *field_key)
                })?
                .2,
        )
    }
    fn len(&self) -> usize {
        self.fields.len()
    }
    pub fn iter(&self) -> impl Iterator<Item = (Pointer, Pointer)> {
        self.fields
            .clone()
            .into_iter()
            .map(|(_, key, value)| (key, value))
    }
    fn equals(&self, heap: &Heap, other: &Struct) -> bool {
        if self.len() != other.len() {
            return false;
        }
        for (key_a, value_a) in self.iter() {
            for (key_b, value_b) in other.iter() {
                if key_a.equals(heap, key_b) && !value_a.equals(heap, value_b) {
                    return false;
                }
            }
        }
        true
    }
}

impl Closure {
    pub fn of_lir(module: Module, lir: Lir) -> Self {
        Closure {
            captured: vec![],
            num_args: 0,
            body: vec![
                Instruction::TraceModuleStarts { module },
                Instruction::CreateClosure {
                    captured: vec![],
                    num_args: 0,
                    body: lir.instructions,
                },
                Instruction::Call { num_args: 0 },
                Instruction::TraceModuleEnds,
                Instruction::Return,
            ],
        }
    }
    pub fn of_module(db: &Database, module: Module) -> Option<Self> {
        let lir = db.lir(module.clone())?;
        Some(Self::of_lir(module, (*lir).clone()))
    }
}

impl Data {
    fn hash(&self, heap: &Heap) -> u64 {
        let mut state = DefaultHasher::new();
        self.hash_with_state(heap, &mut state);
        state.finish()
    }

    fn hash_with_state<H: Hasher>(&self, heap: &Heap, state: &mut H) {
        match self {
            Data::Int(int) => int.value.hash(state),
            Data::Text(text) => text.value.hash(state),
            Data::Symbol(symbol) => symbol.value.hash(state),
            Data::Struct(struct_) => {
                let mut s = 0;
                for (key, value) in struct_.iter() {
                    s ^= key.hash(heap);
                    s ^= value.hash(heap);
                }
                s.hash(state)
            }
            Data::Closure(closure) => {
                for captured in &closure.captured {
                    captured.hash_with_state(heap, state);
                }
                closure.num_args.hash(state);
                closure.body.hash(state);
            }
            Data::Builtin(builtin) => builtin.function.hash(state),
        }
    }

    pub fn equals(&self, heap: &Heap, other: &Self) -> bool {
        match (self, other) {
            (Data::Int(a), Data::Int(b)) => a.value == b.value,
            (Data::Text(a), Data::Text(b)) => a.value == b.value,
            (Data::Symbol(a), Data::Symbol(b)) => a.value == b.value,
            (Data::Struct(a), Data::Struct(b)) => a.equals(heap, b),
            (Data::Closure(_), Data::Closure(_)) => false,
            (Data::Builtin(a), Data::Builtin(b)) => a.function == b.function,
            _ => false,
        }
    }

    pub fn format(&self, heap: &Heap) -> String {
        match self {
            Data::Int(int) => format!("{}", int.value),
            Data::Text(text) => format!("\"{}\"", text.value),
            Data::Symbol(symbol) => symbol.value.to_string(),
            Data::Struct(struct_) => format!(
                "[{}]",
                struct_
                    .fields
                    .iter()
                    .map(|(_, key, value)| (key.format(heap), value.format(heap)))
                    .sorted_by(|(key_a, _), (key_b, _)| key_a.cmp(key_b))
                    .map(|(key, value)| format!("{}: {}", key, value))
                    .join(", ")
            ),
            Data::Closure(_) => "{...}".to_string(),
            Data::Builtin(builtin) => format!("builtin{:?}", builtin.function),
        }
    }

    pub fn children(&self) -> Vec<Pointer> {
        match self {
            Data::Int(_) | Data::Text(_) | Data::Symbol(_) | Data::Builtin(_) => vec![],
            Data::Struct(struct_) => struct_
                .iter()
                .flat_map(|(a, b)| vec![a, b].into_iter())
                .collect_vec(),
            Data::Closure(closure) => closure.captured.clone(),
        }
    }
}

impl Deref for Object {
    type Target = Data;

    fn deref(&self) -> &Self::Target {
        &self.data
    }
}

impl Pointer {
    fn hash(&self, heap: &Heap) -> u64 {
        heap.get(*self).hash(heap)
    }
    fn hash_with_state<H: Hasher>(&self, heap: &Heap, state: &mut H) {
        heap.get(*self).hash_with_state(heap, state)
    }
    pub fn equals(&self, heap: &Heap, other: Self) -> bool {
        if *self == other {
            return true;
        }
        heap.get(*self).equals(heap, heap.get(other))
    }
    pub fn format(&self, heap: &Heap) -> String {
        heap.get(*self).format(heap)
    }
}
<commit_msg>Don't settle on a memory representation yet<commit_after>use super::{pointer::Pointer, Heap};
use crate::{
    builtin_functions::BuiltinFunction,
    compiler::{
        hir_to_lir::HirToLir,
        lir::{Instruction, Lir},
    },
    database::Database,
    module::Module,
};
use itertools::Itertools;
use num_bigint::BigInt;
use std::{
    collections::{hash_map::DefaultHasher, HashMap},
    hash::{Hash, Hasher},
    ops::Deref,
};

#[derive(Clone)]
pub struct Object {
    pub reference_count: usize,
    pub data: Data,
}
#[derive(Clone)]
pub enum Data {
    Int(Int),
    Text(Text),
    Symbol(Symbol),
    Struct(Struct),
    Closure(Closure),
    Builtin(Builtin),
}

#[derive(Clone)]
pub struct Int {
    pub value: BigInt,
}

#[derive(Clone)]
pub struct Text {
    pub value: String,
}

#[derive(Clone)]
pub struct Symbol {
    // TODO: Choose a more efficient representation.
    pub value: String,
}

#[derive(Default, Clone)]
pub struct Struct {
    // TODO: Choose a more efficient representation.
    pub fields: Vec<(u64, Pointer, Pointer)>, // hash, key, and value
}

#[derive(Clone)]
pub struct Closure {
    pub captured: Vec<Pointer>,
    pub num_args: usize,
    pub body: Vec<Instruction>,
}

#[derive(Clone)]
pub struct Builtin {
    pub function: BuiltinFunction,
}

impl Struct {
    pub fn from_fields(heap: &Heap, fields: HashMap<Pointer, Pointer>) -> Self {
        let mut s = Self::default();
        for (key, value) in fields {
            s.insert(heap, key, value);
        }
        s
    }
    fn insert(&mut self, heap: &Heap, key: Pointer, value: Pointer) {
        let hash = key.hash(heap);
        for (existing_hash, existing_key, existing_value) in &mut self.fields {
            if hash != *existing_hash {
                continue;
            }
            if existing_key.equals(heap, key) {
                *existing_value = value;
                return;
            }
        }
        let entry = (hash, key, value);
        if let Some(index) = self
            .fields
            .iter()
            .position(|(the_hash, _, _)| *the_hash > hash)
        {
            self.fields.insert(index, entry);
        } else {
            self.fields.push(entry);
        }
    }
    pub fn get(&self, heap: &Heap, key: Pointer) -> Option<Pointer> {
        let hash = key.hash(heap);
        Some(
            self.fields
                .iter()
                .find(|(field_hash, field_key, _)| {
                    hash == *field_hash && key.equals(heap, *field_key)
                })?
                .2,
        )
    }
    fn len(&self) -> usize {
        self.fields.len()
    }
    pub fn iter(&self) -> impl Iterator<Item = (Pointer, Pointer)> {
        self.fields
            .clone()
            .into_iter()
            .map(|(_, key, value)| (key, value))
    }
    fn equals(&self, heap: &Heap, other: &Struct) -> bool {
        if self.len() != other.len() {
            return false;
        }
        for (key_a, value_a) in self.iter() {
            for (key_b, value_b) in other.iter() {
                if key_a.equals(heap, key_b) && !value_a.equals(heap, value_b) {
                    return false;
                }
            }
        }
        true
    }
}

impl Closure {
    pub fn of_lir(module: Module, lir: Lir) -> Self {
        Closure {
            captured: vec![],
            num_args: 0,
            body: vec![
                Instruction::TraceModuleStarts { module },
                Instruction::CreateClosure {
                    captured: vec![],
                    num_args: 0,
                    body: lir.instructions,
                },
                Instruction::Call { num_args: 0 },
                Instruction::TraceModuleEnds,
                Instruction::Return,
            ],
        }
    }
    pub fn of_module(db: &Database, module: Module) -> Option<Self> {
        let lir = db.lir(module.clone())?;
        Some(Self::of_lir(module, (*lir).clone()))
    }
}

impl Data {
    fn hash(&self, heap: &Heap) -> u64 {
        let mut state = DefaultHasher::new();
        self.hash_with_state(heap, &mut state);
        state.finish()
    }

    fn hash_with_state<H: Hasher>(&self, heap: &Heap, state: &mut H) {
        match self {
            Data::Int(int) => int.value.hash(state),
            Data::Text(text) => text.value.hash(state),
            Data::Symbol(symbol) => symbol.value.hash(state),
            Data::Struct(struct_) => {
                let mut s = 0;
                for (key, value) in struct_.iter() {
                    s ^= key.hash(heap);
                    s ^= value.hash(heap);
                }
                s.hash(state)
            }
            Data::Closure(closure) => {
                for captured in &closure.captured {
                    captured.hash_with_state(heap, state);
                }
                closure.num_args.hash(state);
                closure.body.hash(state);
            }
            Data::Builtin(builtin) => builtin.function.hash(state),
        }
    }

    pub fn equals(&self, heap: &Heap, other: &Self) -> bool {
        match (self, other) {
            (Data::Int(a), Data::Int(b)) => a.value == b.value,
            (Data::Text(a), Data::Text(b)) => a.value == b.value,
            (Data::Symbol(a), Data::Symbol(b)) => a.value == b.value,
            (Data::Struct(a), Data::Struct(b)) => a.equals(heap, b),
            (Data::Closure(_), Data::Closure(_)) => false,
            (Data::Builtin(a), Data::Builtin(b)) => a.function == b.function,
            _ => false,
        }
    }

    pub fn format(&self, heap: &Heap) -> String {
        match self {
            Data::Int(int) => format!("{}", int.value),
            Data::Text(text) => format!("\"{}\"", text.value),
            Data::Symbol(symbol) => symbol.value.to_string(),
            Data::Struct(struct_) => format!(
                "[{}]",
                struct_
                    .fields
                    .iter()
                    .map(|(_, key, value)| (key.format(heap), value.format(heap)))
                    .sorted_by(|(key_a, _), (key_b, _)| key_a.cmp(key_b))
                    .map(|(key, value)| format!("{}: {}", key, value))
                    .join(", ")
            ),
            Data::Closure(_) => "{...}".to_string(),
            Data::Builtin(builtin) => format!("builtin{:?}", builtin.function),
        }
    }

    pub fn children(&self) -> Vec<Pointer> {
        match self {
            Data::Int(_) | Data::Text(_) | Data::Symbol(_) | Data::Builtin(_) => vec![],
            Data::Struct(struct_) => struct_
                .iter()
                .flat_map(|(a, b)| vec![a, b].into_iter())
                .collect_vec(),
            Data::Closure(closure) => closure.captured.clone(),
        }
    }
}

impl Deref for Object {
    type Target = Data;

    fn deref(&self) -> &Self::Target {
        &self.data
    }
}

impl Pointer {
    fn hash(&self, heap: &Heap) -> u64 {
        heap.get(*self).hash(heap)
    }
    fn hash_with_state<H: Hasher>(&self, heap: &Heap, state: &mut H) {
        heap.get(*self).hash_with_state(heap, state)
    }
    pub fn equals(&self, heap: &Heap, other: Self) -> bool {
        if *self == other {
            return true;
        }
        heap.get(*self).equals(heap, heap.get(other))
    }
    pub fn format(&self, heap: &Heap) -> String {
        heap.get(*self).format(heap)
    }
}
<|endoftext|>


<commit_before>macro_rules! min_of {
    ( $d:ident, $s:expr, $i:expr, $ni:expr, $stride:expr ) => {
        if $i == 0 {
            $d[$s + $stride]
        } else if $i == $ni - 1 {
            $d[$s - $stride]
        } else {
            $d[$s - $stride].min($d[$s + $stride])
        };
    }
}

/// Computes the solution of the eikonal equation in 2D using the Fast sweeping algorithm.
///
/// `d` should be initialized to a large value at the unknown nodes.
pub fn fast_sweep_dist_3d(d: &mut [f64], dim: (usize, usize, usize)) {
    let (nx, ny, nz) = dim;
    assert_eq!(nx * ny * nz, d.len());
    let (sx, sy, sz) = (ny * nz, nz, 1);
    // sweep in 8 directions
    for m in 0..8 {
        for p in 0..nx {
            let i = if m & 0b001 == 0 {
                nx - 1 - p
            } else {
                p
            };
            for q in 0..ny {
                let j = if m & 0b010 == 0 {
                    ny - 1 - q
                } else {
                    q
                };
                for r in 0..nz {
                    let k = if m & 0b100 == 0 {
                        nz - 1 - r
                    } else {
                        r
                    };

                    let s = i * sx + j * sy + k * sz;

                    // get and order a, b, c
                    let (a, b, c) = {
                        use std::mem::swap;
                        let mut a = min_of!(d, s, i, nx, sx);
                        let mut b = min_of!(d, s, j, ny, sy);
                        let mut c = min_of!(d, s, k, nz, sz);

                        if a > b {
                            swap(&mut a, &mut b);
                        }
                        if b > c {
                            swap(&mut b, &mut c);
                        }
                        if a > b {
                            swap(&mut a, &mut b);
                        }

                        (a, b, c)
                    };

                    let x = if b >= a + 1. {
                        a + 1.
                    } else {
                        let x = 0.5 * (a + b + (2. - (a - b) * (a - b)).sqrt());
                        if x <= c {
                            x
                        } else {
                            let v = (1. / 3.) *
                            (a + b + c +
                             (3. + (a + b + c).powi(2) - 3. * (a * a + b * b + c * c)).sqrt());
                            v
                        }
                    };

                    d[s] = d[s].min(x);
                }
            }
        }
    }
}

/// Computes the solution of the eikonal equation in 2D using the Fast sweeping algorithm.
///
/// `d` should be initialized to a large value at the unknown nodes.
pub fn fast_sweep_dist_2d(d: &mut [f64], dim: (usize, usize)) {
    let (nx, ny) = dim;
    assert_eq!(nx * ny, d.len());
    // sweep in 4 directions
    for k in 1..5 {
        for q in 0..nx {
            let j = match k {
                3 | 4 => nx - 1 - q,
                _ => q,
            };
            for p in 0..ny {
                let i = match k {
                    2 | 3 => ny - 1 - p,
                    _ => p,
                };
                let s = j * ny + i;
                let a = if i == 0 {
                    d[s + 1]
                } else if i == ny - 1 {
                    d[s - 1]
                } else {
                    d[s - 1].min(d[s + 1])
                };
                let b = if j == 0 {
                    d[s + ny]
                } else if j == nx - 1 {
                    d[s - ny]
                } else {
                    d[s - ny].min(d[s + ny])
                };
                let x = if (a - b).abs() >= 1. {
                    a.min(b) + 1.
                } else {
                    0.5 * (a + b + (2. - (a - b) * (a - b)).sqrt())
                };

                d[s] = d[s].min(x);
            }
        }
    }
}
<commit_msg>Unify 2d and 3d fast_sweep<commit_after>macro_rules! min_of {
    ( $d:ident, $s:expr, $i:expr, $ni:expr, $stride:expr ) => {
        if $i == 0 {
            $d[$s + $stride]
        } else if $i == $ni - 1 {
            $d[$s - $stride]
        } else {
            $d[$s - $stride].min($d[$s + $stride])
        };
    }
}

/// Computes the solution of the eikonal equation in 2D using the Fast sweeping algorithm.
///
/// `d` should be initialized to a large value at the unknown nodes.
pub fn fast_sweep_dist_3d(d: &mut [f64], dim: (usize, usize, usize)) {
    let (nx, ny, nz) = dim;
    assert_eq!(nx * ny * nz, d.len());
    let (sx, sy, sz) = (ny * nz, nz, 1);
    // sweep in 8 directions
    for m in 0..8 {
        for p in 0..nx {
            let i = if m & 0b001 == 0 {
                nx - 1 - p
            } else {
                p
            };
            for q in 0..ny {
                let j = if m & 0b010 == 0 {
                    ny - 1 - q
                } else {
                    q
                };
                for r in 0..nz {
                    let k = if m & 0b100 == 0 {
                        nz - 1 - r
                    } else {
                        r
                    };

                    let s = i * sx + j * sy + k * sz;

                    // get and order a, b, c
                    let (a, b, c) = {
                        use std::mem::swap;
                        let mut a = min_of!(d, s, i, nx, sx);
                        let mut b = min_of!(d, s, j, ny, sy);
                        let mut c = min_of!(d, s, k, nz, sz);

                        if a > b {
                            swap(&mut a, &mut b);
                        }
                        if b > c {
                            swap(&mut b, &mut c);
                        }
                        if a > b {
                            swap(&mut a, &mut b);
                        }

                        (a, b, c)
                    };

                    let x = if b >= a + 1. {
                        a + 1.
                    } else {
                        let x = 0.5 * (a + b + (2. - (a - b) * (a - b)).sqrt());
                        if x <= c {
                            x
                        } else {
                            let v = (1. / 3.) *
                            (a + b + c +
                             (3. + (a + b + c).powi(2) - 3. * (a * a + b * b + c * c)).sqrt());
                            v
                        }
                    };

                    d[s] = d[s].min(x);
                }
            }
        }
    }
}

/// Computes the solution of the eikonal equation in 2D using the Fast sweeping algorithm.
///
/// `d` should be initialized to a large value at the unknown nodes.
pub fn fast_sweep_dist_2d(d: &mut [f64], dim: (usize, usize)) {
    let (nx, ny) = dim;
    let (sx, sy) = (ny, 1);
    assert_eq!(nx * ny, d.len());
    // sweep in 4 directions
    for m in 0..4 {
        for p in 0..nx {
            let i = if m & 0b001 == 0 {
                nx - 1 - p
            } else {
                p
            };
            for q in 0..ny {
                let j = if m & 0b010 == 0 {
                    ny - 1 - q
                } else {
                    q
                };

                let s = i * sx + j * sy;
                let a = min_of!(d, s, i, nx, sx);
                let b = min_of!(d, s, j, ny, sy);

                let x = if (a - b).abs() >= 1. {
                    a.min(b) + 1.
                } else {
                    0.5 * (a + b + (2. - (a - b) * (a - b)).sqrt())
                };

                d[s] = d[s].min(x);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::{Mul,Add,Sub};
use num::traits::{Zero,One,Float};

#[derive(PartialEq,Debug)]
pub struct Vec3<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    pub x: T,
    pub y: T,
    pub z: T,
}

impl <T> Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    pub fn new(xx: T, yy: T, zz: T) -> Vec3<T> {
        Vec3 { x: xx, y: yy, z: zz }
    }

    pub fn zero() -> Vec3<T> {
        Vec3::new(T::zero(), T::zero(), T::zero())
    }

    pub fn diagonal(xx: T) -> Vec3<T> {
        Vec3::new(xx, xx, xx)
    }

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

    pub fn cross(self, rhs: Vec3<T>) -> Vec3<T> {
        Vec3::new(
            self.y * rhs.z - self.z * rhs.y,
            self.z * rhs.x - self.x * rhs.z,
            self.x * rhs.y - self.y * rhs.x,
            )
    }
}

impl <T> Add<Vec3<T>> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

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

impl <T> Sub<Vec3<T>> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

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

impl <T> Mul<T> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

    fn mul(self, rhs: T) -> Vec3<T> {
        Vec3::new(
            self.x * rhs,
            self.y * rhs,
            self.z * rhs,
            )
    }
}

impl <T> Vec3<T> where T: Mul<T, Output=T> + One + Zero + Float + Clone + Copy {
    #[allow(non_snake_case)]
    pub fn sphericalToCartesian(theta: T, phi: T) -> Vec3<T> {
        Vec3::new(phi.cos() * theta.sin(), phi.sin() * theta.sin(), theta.cos())
    }

    fn clamp(value: T, low: T, high: T) -> T {
        if value < low {
            return low
        }
        if value > high {
            return high
        }
        value
    }

    #[allow(non_snake_case)]
    pub fn sphericalTheta(v: &Vec3<T>) -> T {
       Vec3::clamp(v.z, -T::one(), T::one()).acos()
    }

    #[allow(non_snake_case)]
    pub fn sphericalPhi(v: &Vec3<T>) -> T {
        v.y.atan2(v.x) // TODO should be in range [0..2PI)
    }

    #[allow(non_snake_case)]
    pub fn cosTheta(v: &Vec3<T>) -> T {
        v.z
    }

    #[allow(non_snake_case)]
    pub fn sinTheta2(v: &Vec3<T>) -> T {
        let positive_result = T::one() - Vec3::cosTheta(&v) * Vec3::cosTheta(&v);
        if positive_result >= T::zero() {
            positive_result
        } else {
            T::zero()
        }
    }

    #[allow(non_snake_case)]
    pub fn sinTheta(v: &Vec3<T>) -> T {
        Vec3::sinTheta2(v).sqrt()
    }

    #[allow(non_snake_case)]
    pub fn cosPhi(v: &Vec3<T>) -> T {
        let sinTheta: T = Vec3::sinTheta(v);
        if sinTheta == T::zero() {
            T::one()
        } else {
            Vec3::clamp(v.x / sinTheta, -T::one(), T::one())
        }
    }

    #[allow(non_snake_case)]
    pub fn sinPhi(v: &Vec3<T>) -> T {
        let sinTheta: T = Vec3::sinTheta(v);
        if sinTheta == T::zero() {
            T::zero()
        } else {
            Vec3::clamp(v.y / sinTheta, -T::one(), T::one())
        }
    }

    pub fn length(& self) -> T {
        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
    }

    pub fn normalize(&mut self) {
        let length: T = self.length();
        if length > T::zero() {
            let inverse_length = T::one() / length;

            self.x = self.x * inverse_length;
            self.y = self.y * inverse_length;
            self.z = self.z * inverse_length;
        }
    }
}

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

    #[test]
    fn should_be_created_with_constructor() {
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        assert_eq!(v, Vec3 { x: 0.0, y: 1.0, z: 2.0 });
    }

    #[test]
    fn should_initialize_to_zero_vector() {
        let v: Vec3<f64> = Vec3::zero();

        assert_eq!(v, Vec3::<f64>{ x: 0.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_initialize_to_diagonal_vector() {
        let v: Vec3<f64> = Vec3::diagonal(1.0);

        assert_eq!(v, Vec3::<f64>{ x: 1.0, y: 1.0, z: 1.0 });
    }

    #[test]
    fn should_know_dot_product() {
        let u: Vec3<f64> = Vec3::diagonal(1.0);
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        let dot_product: f64 = u.dot(v);

        assert_eq!(dot_product, 3.0);
    }

    #[test]
    fn should_know_its_length() {
        let v: Vec3<f64> = Vec3 { x: 0.0, y: 0.0, z: 0.0 };

        assert_eq!(v.length(), 0.0);
    }

    #[test]
    fn should_be_able_to_normalize() {
        let mut v: Vec3<f64> = Vec3::new(3.0, 0.0, 0.0);
        v.normalize();

        assert_eq!(v, Vec3 { x: 1.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_know_cross_product() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let product = v.cross(w);

        assert_eq!(product, Vec3 { x: 0.0, y: 0.0, z: 1.0 });
    }

    #[test]
    fn should_form_vector_sum() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let sum = v + w;

        assert_eq!(sum, Vec3 { x: 1.0, y: 1.0, z: 0.0 });
    }

    #[test]
    fn should_form_vector_difference() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let sum = v - w;

        assert_eq!(sum, Vec3 { x: 1.0, y: -1.0, z: 0.0 });
    }

    #[test]
    fn should_form_scalar_multiplication() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let c: f64 = 2.0;

        let scalar = v * c;

        assert_eq!(scalar, Vec3 { x: 2.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_know_how_to_convert_from_polar_coordinates() {
        let v: Vec3<f64> = Vec3::sphericalToCartesian(0.0, 0.0);

        assert_eq!(v, Vec3 { x: 0.0, y: 0.0, z: 1.0 });
    }
}
<commit_msg>Bring implementation in agreement<commit_after>use std::ops::{Mul,Add,Sub};
use num::traits::{Zero,One,Float};

#[derive(PartialEq,Debug)]
pub struct Vec3<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    pub x: T,
    pub y: T,
    pub z: T,
}

impl <T> Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    pub fn new(xx: T, yy: T, zz: T) -> Vec3<T> {
        Vec3 { x: xx, y: yy, z: zz }
    }

    pub fn zero() -> Vec3<T> {
        Vec3::new(T::zero(), T::zero(), T::zero())
    }

    pub fn diagonal(xx: T) -> Vec3<T> {
        Vec3::new(xx, xx, xx)
    }

    #[allow(non_snake_case)]
    pub fn dotProduct(self, rhs: Vec3<T>) -> T {
         self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }

    #[allow(non_snake_case)]
    pub fn crossProduct(self, rhs: Vec3<T>) -> Vec3<T> {
        Vec3::new(
            self.y * rhs.z - self.z * rhs.y,
            self.z * rhs.x - self.x * rhs.z,
            self.x * rhs.y - self.y * rhs.x,
            )
    }

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

}

impl <T> Add<Vec3<T>> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

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

impl <T> Sub<Vec3<T>> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

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

impl <T> Mul<T> for Vec3<T> where T : Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Zero + Copy + Clone {
    type Output = Vec3<T>;

    fn mul(self, rhs: T) -> Vec3<T> {
        Vec3::new(
            self.x * rhs,
            self.y * rhs,
            self.z * rhs,
            )
    }
}

impl <T> Vec3<T> where T: Mul<T, Output=T> + One + Zero + Float + Clone + Copy {
    #[allow(non_snake_case)]
    pub fn sphericalToCartesian(theta: T, phi: T) -> Vec3<T> {
        Vec3::new(phi.cos() * theta.sin(), phi.sin() * theta.sin(), theta.cos())
    }

    fn clamp(value: T, low: T, high: T) -> T {
        if value < low {
            return low
        }
        if value > high {
            return high
        }
        value
    }

    #[allow(non_snake_case)]
    pub fn sphericalTheta(v: &Vec3<T>) -> T {
       Vec3::clamp(v.z, -T::one(), T::one()).acos()
    }

    #[allow(non_snake_case)]
    pub fn sphericalPhi(v: &Vec3<T>) -> T {
        v.y.atan2(v.x) // TODO should be in range [0..2PI)
    }

    #[allow(non_snake_case)]
    pub fn cosTheta(v: &Vec3<T>) -> T {
        v.z
    }

    #[allow(non_snake_case)]
    pub fn sinTheta2(v: &Vec3<T>) -> T {
        let positive_result = T::one() - Vec3::cosTheta(&v) * Vec3::cosTheta(&v);
        if positive_result >= T::zero() {
            positive_result
        } else {
            T::zero()
        }
    }

    #[allow(non_snake_case)]
    pub fn sinTheta(v: &Vec3<T>) -> T {
        Vec3::sinTheta2(v).sqrt()
    }

    #[allow(non_snake_case)]
    pub fn cosPhi(v: &Vec3<T>) -> T {
        let sinTheta: T = Vec3::sinTheta(v);
        if sinTheta == T::zero() {
            T::one()
        } else {
            Vec3::clamp(v.x / sinTheta, -T::one(), T::one())
        }
    }

    #[allow(non_snake_case)]
    pub fn sinPhi(v: &Vec3<T>) -> T {
        let sinTheta: T = Vec3::sinTheta(v);
        if sinTheta == T::zero() {
            T::zero()
        } else {
            Vec3::clamp(v.y / sinTheta, -T::one(), T::one())
        }
    }

    pub fn length(& self) -> T {
        self.norm().sqrt()
    }

    pub fn normalize(&mut self) {
        let length: T = self.length();
        if length > T::zero() {
            let inverse_length = T::one() / length;

            self.x = self.x * inverse_length;
            self.y = self.y * inverse_length;
            self.z = self.z * inverse_length;
        }
    }
}

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

    #[test]
    fn should_be_created_with_constructor() {
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        assert_eq!(v, Vec3 { x: 0.0, y: 1.0, z: 2.0 });
    }

    #[test]
    fn should_initialize_to_zero_vector() {
        let v: Vec3<f64> = Vec3::zero();

        assert_eq!(v, Vec3::<f64>{ x: 0.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_initialize_to_diagonal_vector() {
        let v: Vec3<f64> = Vec3::diagonal(1.0);

        assert_eq!(v, Vec3::<f64>{ x: 1.0, y: 1.0, z: 1.0 });
    }

    #[test]
    fn should_know_dot_product() {
        let u: Vec3<f64> = Vec3::diagonal(1.0);
        let v: Vec3<f64> = Vec3::new(0.0, 1.0, 2.0);

        let dot_product: f64 = u.dotProduct(v);

        assert_eq!(dot_product, 3.0);
    }

    #[test]
    fn should_know_its_length() {
        let v: Vec3<f64> = Vec3 { x: 0.0, y: 0.0, z: 0.0 };

        assert_eq!(v.length(), 0.0);
    }

    #[test]
    fn should_be_able_to_normalize() {
        let mut v: Vec3<f64> = Vec3::new(3.0, 0.0, 0.0);
        v.normalize();

        assert_eq!(v, Vec3 { x: 1.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_know_cross_product() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let product = v.crossProduct(w);

        assert_eq!(product, Vec3 { x: 0.0, y: 0.0, z: 1.0 });
    }

    #[test]
    fn should_form_vector_sum() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let sum = v + w;

        assert_eq!(sum, Vec3 { x: 1.0, y: 1.0, z: 0.0 });
    }

    #[test]
    fn should_form_vector_difference() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let w: Vec3<f64> = Vec3::new(0.0, 1.0, 0.0);

        let sum = v - w;

        assert_eq!(sum, Vec3 { x: 1.0, y: -1.0, z: 0.0 });
    }

    #[test]
    fn should_form_scalar_multiplication() {
        let v: Vec3<f64> = Vec3::new(1.0, 0.0, 0.0);
        let c: f64 = 2.0;

        let scalar = v * c;

        assert_eq!(scalar, Vec3 { x: 2.0, y: 0.0, z: 0.0 });
    }

    #[test]
    fn should_know_how_to_convert_from_polar_coordinates() {
        let v: Vec3<f64> = Vec3::sphericalToCartesian(0.0, 0.0);

        assert_eq!(v, Vec3 { x: 0.0, y: 0.0, z: 1.0 });
    }
}
<|endoftext|>


<commit_before>#[allow(non_camel_case_types)]
pub mod bindgen;

#[derive(Debug)]
pub struct Cif(bindgen::ffi_cif);

#[derive(Debug)]
pub struct Arg(*mut ::std::os::raw::c_void);

#[derive(Copy, Clone, Debug)]
pub enum Type {
    Void,
    UInt8,
    SInt8,
    UInt16,
    SInt16,
    UInt32,
    SInt32,
    UInt64,
    SInt64,
    Float,
    Double,
    Pointer,
    LongDouble,
    ComplexFloat,
    ComplexDouble,
    ComplexLongDouble,
}

impl Type {
    fn as_ffi_type(self) -> *mut bindgen::ffi_type {
        unsafe {
            match self {
                Type::Void => &mut bindgen::ffi_type_void,
                Type::UInt8 => &mut bindgen::ffi_type_uint8,
                Type::SInt8 => &mut bindgen::ffi_type_sint8,
                Type::UInt16 => &mut bindgen::ffi_type_uint16,
                Type::SInt16 => &mut bindgen::ffi_type_sint16,
                Type::UInt32 => &mut bindgen::ffi_type_uint32,
                Type::SInt32 => &mut bindgen::ffi_type_sint32,
                Type::UInt64 => &mut bindgen::ffi_type_uint64,
                Type::SInt64 => &mut bindgen::ffi_type_sint64,
                Type::Float => &mut bindgen::ffi_type_float,
                Type::Double => &mut bindgen::ffi_type_double,
                Type::Pointer => &mut bindgen::ffi_type_pointer,
                Type::LongDouble => &mut bindgen::ffi_type_longdouble,
                Type::ComplexFloat => &mut bindgen::ffi_type_complex_float,
                Type::ComplexDouble => &mut bindgen::ffi_type_complex_double,
                Type::ComplexLongDouble =>
                    &mut bindgen::ffi_type_complex_double,
            }
        }
    }
}

pub fn arg<T>(r: &T) -> Arg {
    Arg(unsafe { ::std::mem::transmute(r as *const T) })
}

impl Cif {
    pub fn new(args: &[Type], result: Type) -> Self {
        let mut cif: bindgen::ffi_cif = Default::default();
        let mut real_args: Vec<_> =
            args.iter().map(|t| t.as_ffi_type()).collect();

        let result = unsafe {
            bindgen::ffi_prep_cif(&mut cif,
                                  bindgen::FFI_DEFAULT_ABI,
                                  args.len() as u32,
                                  result.as_ffi_type(),
                                  real_args.as_mut_ptr())
        };

        match result {
            bindgen::ffi_status::FFI_OK
                => (),
            bindgen::ffi_status::FFI_BAD_TYPEDEF
                => panic!("FFI_BAD_TYPEDEF"),
            bindgen::ffi_status::FFI_BAD_ABI
                => panic!("FFI_BAD_ABI"),
        }

        Cif(cif)
    }

    pub unsafe fn call<R>(&self, f: usize, values: &[Arg]) -> R {
        use std::mem;

        assert!(self.0.nargs as usize == values.len());

        let mut result: R = mem::zeroed();

        bindgen::ffi_call(
            mem::transmute(&self.0),
            mem::transmute(f),
            mem::transmute(&mut result),
            mem::transmute(values.as_ptr()));

        return result;
    }
}

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

    #[test]
    fn ffi_call() {
        let cif = Cif::new(&[Type::SInt64, Type::SInt64], Type::SInt64);
        let f   = |m: i64, n: i64| -> i64 {
            unsafe { cif.call(add_it as usize, &[arg(&m), arg(&n)]) }
        };

        assert_eq!(12, f(5, 7));
        assert_eq!(13, f(6, 7));
        assert_eq!(15, f(8, 7));
    }

    extern "C" fn add_it(n: i64, m: i64) -> i64 {
        return n + m;
    }
}
<commit_msg>Closure allocation<commit_after>#[allow(non_camel_case_types)]
pub mod bindgen;

use std::mem;

#[derive(Debug)]
pub struct Cif(bindgen::ffi_cif);

#[derive(Debug)]
pub struct Arg(*mut ::std::os::raw::c_void);

#[derive(Copy, Clone, Debug)]
pub enum Type {
    Void,
    UInt8,
    SInt8,
    UInt16,
    SInt16,
    UInt32,
    SInt32,
    UInt64,
    SInt64,
    Float,
    Double,
    Pointer,
    LongDouble,
    ComplexFloat,
    ComplexDouble,
    ComplexLongDouble,
}

impl Type {
    fn as_ffi_type(self) -> *mut bindgen::ffi_type {
        unsafe {
            match self {
                Type::Void => &mut bindgen::ffi_type_void,
                Type::UInt8 => &mut bindgen::ffi_type_uint8,
                Type::SInt8 => &mut bindgen::ffi_type_sint8,
                Type::UInt16 => &mut bindgen::ffi_type_uint16,
                Type::SInt16 => &mut bindgen::ffi_type_sint16,
                Type::UInt32 => &mut bindgen::ffi_type_uint32,
                Type::SInt32 => &mut bindgen::ffi_type_sint32,
                Type::UInt64 => &mut bindgen::ffi_type_uint64,
                Type::SInt64 => &mut bindgen::ffi_type_sint64,
                Type::Float => &mut bindgen::ffi_type_float,
                Type::Double => &mut bindgen::ffi_type_double,
                Type::Pointer => &mut bindgen::ffi_type_pointer,
                Type::LongDouble => &mut bindgen::ffi_type_longdouble,
                Type::ComplexFloat => &mut bindgen::ffi_type_complex_float,
                Type::ComplexDouble => &mut bindgen::ffi_type_complex_double,
                Type::ComplexLongDouble =>
                    &mut bindgen::ffi_type_complex_double,
            }
        }
    }
}

pub fn arg<T>(r: &T) -> Arg {
    Arg(unsafe { mem::transmute(r as *const T) })
}

impl Cif {
    pub fn new(args: &[Type], result: Type) -> Self {
        let mut cif: bindgen::ffi_cif = Default::default();
        let mut real_args: Vec<_> =
            args.iter().map(|t| t.as_ffi_type()).collect();

        let result = unsafe {
            bindgen::ffi_prep_cif(&mut cif,
                                  bindgen::FFI_DEFAULT_ABI,
                                  args.len() as u32,
                                  result.as_ffi_type(),
                                  real_args.as_mut_ptr())
        };

        match result {
            bindgen::ffi_status::FFI_OK
                => (),
            bindgen::ffi_status::FFI_BAD_TYPEDEF
                => panic!("FFI_BAD_TYPEDEF"),
            bindgen::ffi_status::FFI_BAD_ABI
                => panic!("FFI_BAD_ABI"),
        }

        Cif(cif)
    }

    pub unsafe fn call<R>(&self, f: usize, values: &[Arg]) -> R {
        use std::mem;

        assert!(self.0.nargs as usize == values.len());

        let mut result: R = mem::zeroed();

        bindgen::ffi_call(
            mem::transmute(&self.0),
            mem::transmute(f),
            mem::transmute(&mut result),
            mem::transmute(values.as_ptr()));

        return result;
    }
}

pub struct Closure {
    alloc: *mut ::std::os::raw::c_void,
    code:  *mut ::std::os::raw::c_void,
}

impl Drop for Closure {
    fn drop(&mut self) {
        unsafe {
            bindgen::ffi_closure_free(self.alloc);
        }
    }
}

impl Closure {
    pub fn new() -> Self {
        let mut code: *mut ::std::os::raw::c_void =
            unsafe { mem::zeroed() };

        let alloc = unsafe {
            bindgen::ffi_closure_alloc(
                mem::size_of::<bindgen::ffi_closure>(),
                &mut code)
        };

        assert!(alloc as usize != 0);

        Closure {
            alloc: alloc,
            code:  code,
        }
    }
}

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

    #[test]
    fn ffi_call() {
        let cif = Cif::new(&[Type::SInt64, Type::SInt64], Type::SInt64);
        let f   = |m: i64, n: i64| -> i64 {
            unsafe { cif.call(add_it as usize, &[arg(&m), arg(&n)]) }
        };

        assert_eq!(12, f(5, 7));
        assert_eq!(13, f(6, 7));
        assert_eq!(15, f(8, 7));
    }

    extern "C" fn add_it(n: i64, m: i64) -> i64 {
        return n + m;
    }
}
<|endoftext|>


<commit_before>use stb_image::*;
use stb_image::bindgen::*;
use libc::types::os::arch::c95::c_int;
use ptr::{is_null, to_unsafe_ptr};
use str::as_c_str;
use vec::as_imm_buf;
use vec::raw::from_buf_raw;

pub struct Image {
    width: uint,
    height: uint,
    depth: uint,
    data: ~[u8],
}

pub fn new_image(width: uint, height: uint, depth: uint, data: ~[u8]) -> Image {
    Image {
        width : width,
        height : height,
        depth : depth,
        data : data,
    }
}

pub fn load(path: ~str) -> Option<Image> unsafe {
    do task::unkillable {
        let mut width = 0 as c_int;
        let mut height = 0 as c_int;
        let mut depth = 0 as c_int;
        let force_depth = 4 as c_int;
        let buffer = as_c_str(path, |bytes| {
            stbi_load(bytes, to_unsafe_ptr(&width), to_unsafe_ptr(&height), to_unsafe_ptr(&depth),
                      force_depth)
        });

        if is_null(buffer) {
            None
        } else {
            // FIXME: Shouldn't copy; instead we should use a sendable resource. They
            // aren't particularly safe yet though.
            let data = from_buf_raw(buffer, (width * height * force_depth) as uint);
            libc::free(buffer as *c_void);
            Some(new_image(width as uint, height as uint, force_depth as uint, data))
        }
    }
}

pub fn load_from_memory(buffer: &[u8]) -> Option<Image> unsafe {
    do task::unkillable {
        let mut width = 0 as c_int;
        let mut height = 0 as c_int;
        let mut depth = 0 as c_int;
        let force_depth = 4 as c_int;
        let buffer = as_imm_buf(buffer, |bytes, len| {
            stbi_load_from_memory(bytes, len as c_int, to_unsafe_ptr(&width),
                                  to_unsafe_ptr(&height), to_unsafe_ptr(&depth), force_depth)
        });

        if is_null(buffer) {
            None
        } else {
            // FIXME: Shouldn't copy; instead we should use a sendable resource. They
            // aren't particularly safe yet though.
            let data = from_buf_raw(buffer, (width * height * force_depth) as uint);
            libc::free(buffer as *c_void);
            Some(new_image(width as uint, height as uint, force_depth as uint, data))
        }
    }
}
<commit_msg>Eliminate copy warnings<commit_after>use stb_image::*;
use stb_image::bindgen::*;
use libc::types::os::arch::c95::c_int;
use ptr::{is_null, to_unsafe_ptr};
use str::as_c_str;
use vec::as_imm_buf;
use vec::raw::from_buf_raw;

pub struct Image {
    width: uint,
    height: uint,
    depth: uint,
    data: ~[u8],
}

pub fn new_image(width: uint, height: uint, depth: uint, data: ~[u8]) -> Image {
    Image {
        width : width,
        height : height,
        depth : depth,
        data : move data,
    }
}

pub fn load(path: ~str) -> Option<Image> unsafe {
    do task::unkillable {
        let mut width = 0 as c_int;
        let mut height = 0 as c_int;
        let mut depth = 0 as c_int;
        let force_depth = 4 as c_int;
        let buffer = as_c_str(path, |bytes| {
            stbi_load(bytes, to_unsafe_ptr(&width), to_unsafe_ptr(&height), to_unsafe_ptr(&depth),
                      force_depth)
        });

        if is_null(buffer) {
            None
        } else {
            // FIXME: Shouldn't copy; instead we should use a sendable resource. They
            // aren't particularly safe yet though.
            let data = from_buf_raw(buffer, (width * height * force_depth) as uint);
            libc::free(buffer as *c_void);
            Some(new_image(width as uint, height as uint, force_depth as uint, move data))
        }
    }
}

pub fn load_from_memory(buffer: &[u8]) -> Option<Image> unsafe {
    do task::unkillable {
        let mut width = 0 as c_int;
        let mut height = 0 as c_int;
        let mut depth = 0 as c_int;
        let force_depth = 4 as c_int;
        let buffer = as_imm_buf(buffer, |bytes, len| {
            stbi_load_from_memory(bytes, len as c_int, to_unsafe_ptr(&width),
                                  to_unsafe_ptr(&height), to_unsafe_ptr(&depth), force_depth)
        });

        if is_null(buffer) {
            None
        } else {
            // FIXME: Shouldn't copy; instead we should use a sendable resource. They
            // aren't particularly safe yet though.
            let data = from_buf_raw(buffer, (width * height * force_depth) as uint);
            libc::free(buffer as *c_void);
            Some(new_image(width as uint, height as uint, force_depth as uint, move data))
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{File};
use std::slice;
use std::fmt;
use std::num::FromPrimitive;

#[deriving(Show, FromPrimitive)]
enum OPCode {
    NOP = 0x00,
    PUSH,
    POP,
    LOAD,
    STORE,
    JMP,
    JZ,
    JNZ,
    ADD,
    SUB,
    MUL,
    DIV,
    PRINT,
    STOP
}

impl fmt::Show for VM {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "Stack Pointer: {}\nInstruction Pointer: {}\nRegisters: {}\nInstructions: {}",
               self.sp,
               self.ip,
               self.register.as_slice(),
               self.instructions.slice(self.ip,self.ip+10))
    }
}

fn new() -> VM {
    VM{sp:0, ip:0, register:[0, ..16], stack:[0, ..256], instructions:[0, ..65536]}
}

impl VM {
    fn push(&mut self) -> () {
        if self.sp >= 254 { fail!("Stack overflow at line {}", self.ip); }
        self.stack[self.sp] = 0;
        for i in range(0, 4) {
            self.stack[self.sp] += self.instructions[self.ip+1+i] as i32 << 8*i;
        }
        self.sp += 1;
        self.ip += 5;
    }

    fn bare_pop(&mut self) -> () {
        let _ = self.pop();
    }

    fn pop(&mut self) -> i32 {
        if self.sp > 0 {
            self.sp -= 1;
        } else {
            fail!("Attempted to pop empty stack at line {}", self.ip);
        }
        self.stack[self.sp]
    }

    fn load(&mut self) -> () {
        let r = self.instructions[self.ip+1];
        self.stack[self.sp] = self.register[r as uint];
        self.sp += 1;
        self.ip += 2;
    }

    fn store(&mut self) -> () {
        let r = self.instructions[self.ip + 1];
        self.register[r as uint] = self.pop();
        self.ip += 2;
    }

    fn jump(&mut self) -> () {
        let mut dest = self.instructions[self.ip+1] as uint;
        dest += self.instructions[self.ip+2] as uint << 8;
        self.ip = dest;
    }

    fn jz(&mut self) -> () {
        let tos = self.pop();
        if tos == 0 {
            self.jump();
        } else {
            self.ip += 3;
        }
    }

    fn jnz(&mut self) -> () {
        let tos = self.pop();
        if tos != 0 {
            self.jump();
        } else{
            self.ip += 3;
        }
    }

    fn add(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s1 + s2;
        self.sp += 1;
        self.ip += 1;
    }

    fn sub(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 - s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn mul(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 * s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn div(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 / s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn print(&mut self) -> () {
        let tos = self.pop();
        println!("{}", tos);
        self.ip += 1;
    }

    fn execute(&mut self) -> () {
        loop {
            println!("{}\nStack: {}\n", self, self.stack.slice(0,10));
            let op: Option<OPCode> = FromPrimitive::from_u8(self.instructions[self.ip]);
            match op {
                Some(code) => match code {
                    NOP => (),
                    PUSH => self.push(),
                    POP => self.bare_pop(),
                    LOAD => self.load(),
                    STORE => self.store(),
                    JMP => self.jump(),
                    JZ => self.jz(),
                    JNZ => self.jnz(),
                    ADD => self.add(),
                    SUB => self.sub(),
                    MUL => self.mul(),
                    DIV => self.div(),
                    PRINT => self.print(),
                    STOP => break,
                },
                None => println!("Invalid OPCode encountered at {}", self.ip)
            }
        }
    }
}

struct VM  {
    sp : uint,
    ip : uint,
    register : [i32, ..16],
    stack : [i32, ..256],
    instructions : [u8, ..65536],
}

fn main() {
    let mut x  = new();
    match File::open(&Path::new("factorial.bcm")).read_to_end() {
        Ok(contents) => slice::bytes::copy_memory(x.instructions, contents.as_slice()),
        Err(e) => println!("Failed to read factorial.bcm with error {}", e),
    }

    x.execute();

}
<commit_msg>Correct failure messages for popping/pushing empty/full stack<commit_after>use std::io::{File};
use std::slice;
use std::fmt;
use std::num::FromPrimitive;

#[deriving(Show, FromPrimitive)]
enum OPCode {
    NOP = 0x00,
    PUSH,
    POP,
    LOAD,
    STORE,
    JMP,
    JZ,
    JNZ,
    ADD,
    SUB,
    MUL,
    DIV,
    PRINT,
    STOP
}

impl fmt::Show for VM {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "Stack Pointer: {}\nInstruction Pointer: {}\nRegisters: {}\nInstructions: {}",
               self.sp,
               self.ip,
               self.register.as_slice(),
               self.instructions.slice(self.ip,self.ip+10))
    }
}

fn new() -> VM {
    VM{sp:0, ip:0, register:[0, ..16], stack:[0, ..256], instructions:[0, ..65536]}
}

impl VM {
    fn push(&mut self) -> () {
        if self.sp >= 254 { fail!("Stack overflow at byte {}", self.ip); }
        self.stack[self.sp] = 0;
        for i in range(0, 4) {
            self.stack[self.sp] += self.instructions[self.ip+1+i] as i32 << 8*i;
        }
        self.sp += 1;
        self.ip += 5;
    }

    fn bare_pop(&mut self) -> () {
        let _ = self.pop();
    }

    fn pop(&mut self) -> i32 {
        if self.sp > 0 {
            self.sp -= 1;
        } else {
            fail!("Attempted to pop empty stack at byte {}", self.ip);
        }
        self.stack[self.sp]
    }

    fn load(&mut self) -> () {
        let r = self.instructions[self.ip+1];
        self.stack[self.sp] = self.register[r as uint];
        self.sp += 1;
        self.ip += 2;
    }

    fn store(&mut self) -> () {
        let r = self.instructions[self.ip + 1];
        self.register[r as uint] = self.pop();
        self.ip += 2;
    }

    fn jump(&mut self) -> () {
        let mut dest = self.instructions[self.ip+1] as uint;
        dest += self.instructions[self.ip+2] as uint << 8;
        self.ip = dest;
    }

    fn jz(&mut self) -> () {
        let tos = self.pop();
        if tos == 0 {
            self.jump();
        } else {
            self.ip += 3;
        }
    }

    fn jnz(&mut self) -> () {
        let tos = self.pop();
        if tos != 0 {
            self.jump();
        } else{
            self.ip += 3;
        }
    }

    fn add(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s1 + s2;
        self.sp += 1;
        self.ip += 1;
    }

    fn sub(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 - s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn mul(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 * s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn div(&mut self) -> () {
        let s1 = self.pop();
        let s2 = self.pop();
        self.stack[self.sp] = s2 / s1;
        self.sp += 1;
        self.ip += 1;
    }

    fn print(&mut self) -> () {
        let tos = self.pop();
        println!("{}", tos);
        self.ip += 1;
    }

    fn execute(&mut self) -> () {
        loop {
            println!("{}\nStack: {}\n", self, self.stack.slice(0,10));
            let op: Option<OPCode> = FromPrimitive::from_u8(self.instructions[self.ip]);
            match op {
                Some(code) => match code {
                    NOP => (),
                    PUSH => self.push(),
                    POP => self.bare_pop(),
                    LOAD => self.load(),
                    STORE => self.store(),
                    JMP => self.jump(),
                    JZ => self.jz(),
                    JNZ => self.jnz(),
                    ADD => self.add(),
                    SUB => self.sub(),
                    MUL => self.mul(),
                    DIV => self.div(),
                    PRINT => self.print(),
                    STOP => break,
                },
                None => println!("Invalid OPCode encountered at {}", self.ip)
            }
        }
    }
}

struct VM  {
    sp : uint,
    ip : uint,
    register : [i32, ..16],
    stack : [i32, ..256],
    instructions : [u8, ..65536],
}

fn main() {
    let mut x  = new();
    match File::open(&Path::new("factorial.bcm")).read_to_end() {
        Ok(contents) => slice::bytes::copy_memory(x.instructions, contents.as_slice()),
        Err(e) => println!("Failed to read factorial.bcm with error {}", e),
    }

    x.execute();

}
<|endoftext|>


<commit_before>pub fn bit_length(number: u32) -> u8 {
    32 - number.leading_zeros() as u8
}

pub fn get_bite_mask(mask: u8) -> u32 {
    debug_assert!(mask <= 32);
    match mask {
        0 => 0,
        n => (!0 << (32 - n)),
    }
}

pub fn get_bite_mask_u128(mask: u8) -> u128 {
    debug_assert!(mask <= 128);
    match mask {
        0 => 0,
        n => (!0 << (128 - n)),
    }
}

pub fn split_ip_netmask(input: &str) -> Option<(&str, &str)> {
    let delimiter = match input.find('/') {
        Some(pos) => pos,
        None => return None,
    };
    let (ip, mask) = input.split_at(delimiter);
    let mask = &mask[1..];

    if ip.is_empty() || mask.is_empty() {
        None
    } else {
        Some((ip, mask))
    }
}

#[cfg(test)]
mod tests {
    use super::{get_bite_mask, get_bite_mask_u128, split_ip_netmask};
    use std;

    #[test]
    fn get_bite_mask_32() {
        assert_eq!(std::u32::MAX, get_bite_mask(32));
    }

    #[test]
    fn get_bite_mask_0() {
        assert_eq!(0, get_bite_mask(0));
    }

    #[test]
    fn get_bite_mask_u128_0() {
        assert_eq!(0, get_bite_mask_u128(0));
    }

    #[test]
    fn get_bite_mask_u128_128() {
        assert_eq!(std::u128::MAX, get_bite_mask_u128(128));
    }

    #[test]
    fn split_ip_netmask_normal() {
        let (ip, netmask) = split_ip_netmask("192.168.1.1/24").unwrap();
        assert_eq!("192.168.1.1", ip);
        assert_eq!("24", netmask);
    }

    #[test]
    fn split_ip_netmask_invalid_1() {
        let a = split_ip_netmask("ab");
        assert!(a.is_none());
    }

    #[test]
    fn split_ip_netmask_invalid_2() {
        let a = split_ip_netmask("/");
        assert!(a.is_none());
    }

    #[test]
    fn split_ip_netmask_invalid_3() {
        let a = split_ip_netmask("192.168.1.1/");
        assert!(a.is_none());
    }
}
<commit_msg>Simplified helpers test<commit_after>pub fn bit_length(number: u32) -> u8 {
    32 - number.leading_zeros() as u8
}

pub fn get_bite_mask(mask: u8) -> u32 {
    debug_assert!(mask <= 32);
    match mask {
        0 => 0,
        n => (!0 << (32 - n)),
    }
}

pub fn get_bite_mask_u128(mask: u8) -> u128 {
    debug_assert!(mask <= 128);
    match mask {
        0 => 0,
        n => (!0 << (128 - n)),
    }
}

pub fn split_ip_netmask(input: &str) -> Option<(&str, &str)> {
    let delimiter = match input.find('/') {
        Some(pos) => pos,
        None => return None,
    };
    let (ip, mask) = input.split_at(delimiter);
    let mask = &mask[1..];

    if ip.is_empty() || mask.is_empty() {
        None
    } else {
        Some((ip, mask))
    }
}

#[cfg(test)]
mod tests {
    use super::{get_bite_mask, get_bite_mask_u128, split_ip_netmask};

    #[test]
    fn get_bite_mask_32() {
        assert_eq!(u32::max_value(), get_bite_mask(32));
    }

    #[test]
    fn get_bite_mask_0() {
        assert_eq!(0, get_bite_mask(0));
    }

    #[test]
    fn get_bite_mask_u128_0() {
        assert_eq!(0, get_bite_mask_u128(0));
    }

    #[test]
    fn get_bite_mask_u128_128() {
        assert_eq!(u128::max_value(), get_bite_mask_u128(128));
    }

    #[test]
    fn split_ip_netmask_normal() {
        let (ip, netmask) = split_ip_netmask("192.168.1.1/24").unwrap();
        assert_eq!("192.168.1.1", ip);
        assert_eq!("24", netmask);
    }

    #[test]
    fn split_ip_netmask_invalid_1() {
        let a = split_ip_netmask("ab");
        assert!(a.is_none());
    }

    #[test]
    fn split_ip_netmask_invalid_2() {
        let a = split_ip_netmask("/");
        assert!(a.is_none());
    }

    #[test]
    fn split_ip_netmask_invalid_3() {
        let a = split_ip_netmask("192.168.1.1/");
        assert!(a.is_none());
    }
}
<|endoftext|>


<commit_before>use super::errors::*;

use fuse;
use fuse::{Filesystem, Request, ReplyAttr, ReplyDirectory, ReplyEntry, FileAttr};

use libc::{ENOSYS, ENOENT};

use time::Timespec;
use std;
use std::ffi::OsStr;
use std::fs;
use std::time::SystemTime;
use std::path::Path;

pub struct S3HierarchicalFilesystem<'a> {
    mountpath: &'a str,
    backingpath: &'a str,
}

impl<'a> S3HierarchicalFilesystem<'a> {
    pub fn mount(mp: &str, bp: &str) -> Result<()> {
        let fs = S3HierarchicalFilesystem {
            mountpath: mp,
            backingpath: bp,
        };
        fuse::mount(fs, &mp, &[]).chain_err(|| "mounting filesystem")
    }
}

fn filetype_tryfrom(ft: &fs::FileType) -> Result<fuse::FileType> {
    if ft.is_file() {
        return Ok(fuse::FileType::RegularFile);
    }
    if ft.is_dir() {
        return Ok(fuse::FileType::Directory);
    }
    if ft.is_symlink() {
        return Ok(fuse::FileType::Symlink);
    }
    bail!("unknown filetype")
}

fn timespec_from(st: &SystemTime) -> Timespec {
    if let Ok(dur_since_epoch) = st.duration_since(std::time::UNIX_EPOCH) {
        Timespec::new(dur_since_epoch.as_secs() as i64,
                      dur_since_epoch.subsec_nanos() as i32)
    } else {
        Timespec::new(0, 0)
    }
}

fn fileattr_from(m: &std::fs::Metadata) -> FileAttr {
    use std::os::unix::fs::{MetadataExt, PermissionsExt};
    use std::time::SystemTime;

    let kind = filetype_tryfrom(&m.file_type()).unwrap();
    let mode = m.permissions().mode();
    FileAttr {
        ino: m.ino(),
        size: m.len(),
        blocks: m.blocks(),
        atime: timespec_from(&m.accessed().unwrap_or(SystemTime::now())),
        mtime: timespec_from(&m.modified().unwrap_or(SystemTime::now())),
        ctime: Timespec::new(m.ctime(), m.ctime_nsec() as i32),
        crtime: timespec_from(&m.created().unwrap_or(SystemTime::now())),
        kind: kind,
        perm: mode as u16,
        nlink: m.nlink() as u32,
        uid: m.uid(),
        gid: m.gid(),
        rdev: m.rdev() as u32,
        flags: 0,
    }
}

impl<'a> Filesystem for S3HierarchicalFilesystem<'a> {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        info!("getattr(ino={})", ino);
        match std::fs::metadata(self.backingpath) {
            Ok(metadata) => {
                debug!("{:?}", metadata);
                let attr = fileattr_from(&metadata);
                if ino == 1 {
                    let ttl = Timespec::new(1, 0);
                    reply.attr(&ttl, &attr);
                    debug!("{:?}", attr);
                } else {
                    reply.error(ENOSYS);
                }
            }
            Err(e) => {
                debug!("{:?}", e);
                reply.error(ENOENT);
            }
        };
    }

    fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) {
        info!("lookup(parent={}, name={:?})", parent, name);
        if parent == 1 {
            let name = match name.to_str() {
                Some(s) => s,
                None => {
                    error!("extracting name for lookup");
                    reply.error(ENOENT);
                    return;
                }
            };
            let path = vec![self.backingpath.to_string(), name.to_string()].join("/");
            match std::fs::metadata(path) {
                Ok(metadata) => {
                    debug!("{:?}", metadata);
                    let attr = fileattr_from(&metadata);
                    let ttl = Timespec::new(1, 0);
                    debug!("warning: generation assumed 0");
                    reply.entry(&ttl, &attr, 0);
                    debug!("{:?}", attr);
                }
                Err(e) => {
                    error!("{}: \"{}\"", e, name);
                    reply.error(ENOENT);
                }
            };
        } else {
            reply.error(ENOSYS)
        }
    }

    fn readdir(&mut self,
               _req: &Request,
               ino: u64,
               fh: u64,
               offset: u64,
               mut reply: ReplyDirectory) {
        use std::os::unix::fs::DirEntryExt;

        info!("readdir(ino={}, fh={}, offset={})", ino, fh, offset);
        trace!("{:?}", _req);

        if ino == 1 {
            if offset == 0 {
                reply.add(1, 0, fuse::FileType::Directory, ".");
                reply.add(1, 1, fuse::FileType::Directory, "..");
            }

            let rd = match fs::read_dir(self.backingpath) {
                Ok(rd) => rd,
                Err(e) => {
                    error!("{:?}", e);
                    reply.error(ENOENT);
                    return;
                }
            };

            for (i, entry_opt) in rd.enumerate() {
                debug!("Found entry {}: {:?}", i, entry_opt);
                if (i as u64) < offset {
                    continue;
                };
                if let Ok(entry) = entry_opt {
                    if let Ok(ft) = entry.file_type() {
                        if let Ok(filetype) = filetype_tryfrom(&ft) {
                            debug!("adding entry");
                            if reply.add(entry.ino(), (i + 2) as u64, filetype, entry.file_name()) {
                                break;
                            }
                        }
                    }
                };
            }
            reply.ok();
        } else {
            reply.error(ENOSYS);
        }
    }
}
<commit_msg>working through criteria to call getattr<commit_after>use super::errors::*;

use fuse;
use fuse::{Filesystem, Request, ReplyAttr, ReplyDirectory, ReplyEntry, FileAttr};

use libc::{ENOSYS, ENOENT};

use time::Timespec;
use std;
use std::ffi::OsStr;
use std::fs;
use std::time::SystemTime;
use std::path::Path;

pub struct S3HierarchicalFilesystem<'a> {
    mount_path: &'a str,
    backing_path: &'a str,
    ino_paths: std::collections::HashMap<u64, String>,
}

impl<'a> S3HierarchicalFilesystem<'a> {
    pub fn mount(mp: &str, bp: &str) -> Result<()> {
        let mut fs = S3HierarchicalFilesystem {
            mount_path: mp,
            backing_path: bp,
            ino_paths: std::collections::HashMap::new(),
        };
        fs.ino_paths.insert(1, bp.to_string());
        fuse::mount(fs, &mp, &[]).chain_err(|| "mounting filesystem")
    }
}

fn filetype_tryfrom(ft: &fs::FileType) -> Result<fuse::FileType> {
    if ft.is_file() {
        return Ok(fuse::FileType::RegularFile);
    }
    if ft.is_dir() {
        return Ok(fuse::FileType::Directory);
    }
    if ft.is_symlink() {
        return Ok(fuse::FileType::Symlink);
    }
    bail!("unknown filetype")
}

fn timespec_from(st: &SystemTime) -> Timespec {
    if let Ok(dur_since_epoch) = st.duration_since(std::time::UNIX_EPOCH) {
        Timespec::new(dur_since_epoch.as_secs() as i64,
                      dur_since_epoch.subsec_nanos() as i32)
    } else {
        Timespec::new(0, 0)
    }
}

fn fileattr_from(m: &std::fs::Metadata) -> FileAttr {
    use std::os::unix::fs::{MetadataExt, PermissionsExt};
    use std::time::SystemTime;

    let kind = filetype_tryfrom(&m.file_type()).unwrap();
    let mode = m.permissions().mode();
    FileAttr {
        ino: m.ino(),
        size: m.len(),
        blocks: m.blocks(),
        atime: timespec_from(&m.accessed().unwrap_or(SystemTime::now())),
        mtime: timespec_from(&m.modified().unwrap_or(SystemTime::now())),
        ctime: Timespec::new(m.ctime(), m.ctime_nsec() as i32),
        crtime: timespec_from(&m.created().unwrap_or(SystemTime::now())),
        kind: kind,
        perm: mode as u16,
        nlink: m.nlink() as u32,
        uid: m.uid(),
        gid: m.gid(),
        rdev: m.rdev() as u32,
        flags: 0,
    }
}

macro_rules! unwrap_or_return_error {
    ($v:expr, $log:expr, $err:expr, $reply:ident) => (
        match $v {
            Some(v) => v,
            None => {
                error!($log);
                $reply.error($err);
                return;
            }
        }
    )
}

macro_rules! ok_or_return_error {
    ($v:expr, $err:expr, $reply:ident) => (
        match $v {
            Ok(v) => v,
            Err(e) => {
                error!("{:?}", e);
                $reply.error($err);
                return;
            }
        }
    )
}

impl<'a> Filesystem for S3HierarchicalFilesystem<'a> {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        info!("getattr(ino={})", ino);
        debug!("req: {:?}", _req);

        let path = unwrap_or_return_error!(self.ino_paths.get(&ino),
                                           "ino not found in cache",
                                           ENOENT,
                                           reply);
        let metadata = ok_or_return_error!(std::fs::metadata(path), ENOENT, reply);

        debug!("{:?}", metadata);
        let attr = fileattr_from(&metadata);
        let ttl = Timespec::new(1, 0);
        reply.attr(&ttl, &attr);
    }

    fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) {
        info!("lookup(parent={}, name={:?})", parent, name);

        let parent_path = unwrap_or_return_error!(self.ino_paths.get(&parent),
                                                  "ino not found in cache",
                                                  ENOSYS,
                                                  reply);

        let file_name =
            unwrap_or_return_error!(name.to_str(), "unable to read name", ENOSYS, reply);

        let path = Path::new(&parent_path).join(file_name);
        debug!("Path: {:?}", path);
        match std::fs::metadata(path) {
            Ok(metadata) => {
                debug!("{:?}", metadata);
                let attr = fileattr_from(&metadata);
                let ttl = Timespec::new(1, 0);
                debug!("warning: generation assumed 0");
                reply.entry(&ttl, &attr, 0);
                debug!("{:?}", attr);
            }
            Err(e) => {
                error!("{}", e);
                reply.error(ENOENT);
            }
        };
    }

    fn readdir(&mut self,
               _req: &Request,
               ino: u64,
               fh: u64,
               offset: u64,
               mut reply: ReplyDirectory) {
        use std::os::unix::fs::DirEntryExt;

        info!("readdir(ino={}, fh={}, offset={})", ino, fh, offset);
        trace!("{:?}", _req);

        let path = unwrap_or_return_error!(self.ino_paths.get(&ino),
                                           "ino not found in cache",
                                           ENOSYS,
                                           reply)
            .to_string();

        if offset == 0 {
            reply.add(ino, 0, fuse::FileType::Directory, ".");
            reply.add(ino, 1, fuse::FileType::Directory, "..");
        }

        let rd = ok_or_return_error!(fs::read_dir(path), ENOENT, reply);

        for (i, entry_opt) in rd.enumerate() {
            debug!("Found entry {}: {:?}", i, entry_opt);
            if ((i + 2) as u64) < offset {
                continue;
            };
            if let Ok(entry) = entry_opt {
                if let Ok(ft) = entry.file_type() {
                    if let Ok(filetype) = filetype_tryfrom(&ft) {
                        debug!("adding entry: {}, {}, {:?}, {:?}",
                               entry.ino(),
                               (i + 2) as u64,
                               filetype,
                               entry.file_name());
                        if reply.add(entry.ino(), (i + 2) as u64, filetype, entry.file_name()) {
                            debug!("out of space");
                            break;
                        }
                    }
                }
            };
        }
        debug!("returning stuff");
        reply.ok();
    }
}
<|endoftext|>


<commit_before>#![crate_name = "hiredis"]
#![crate_type = "lib"]
#![feature(globs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

extern crate libc;

use std::mem::transmute;

pub mod api;

pub struct Reply {
    reply: *const api::Reply
}

impl Reply {
    unsafe fn new(reply: *const api::Reply) -> Reply {
        Reply {
            reply: reply
        }
    }
}

impl Drop for Reply {
    fn drop(&mut self) {
        unsafe {
            api::freeReplyObject(transmute(self.reply))
        }
    }
}

pub struct Redis {
    context: *const api::Context
}

impl Redis {
    pub fn new(ip: &str, port: i32) -> Redis {
        unsafe {
            Redis {
                context: api::redisConnect(
                    ip.to_c_str().as_ptr(),
                    port
                )
            }
        }
    }

    /* TODO: Move to IoResult using context.err */
    pub fn exec(&self, command: &str) -> Option<Reply> {
        command.with_c_str(|v| {
            unsafe {
                let result = api::redisCommand(self.context, v);

                /* Fail if the command errored for some reason. */
                if result == 0 as *const ::libc::c_void {
                    return None;
                }

                /* Otherwise transmute the void pointer memory into a pointer
                 * to a reply structure and return it. */
                Some(Reply::new(transmute(result)))
            }
        })
    }
}

impl Drop for Redis {
    fn drop(&mut self) {
        unsafe {
            api::redisFree(self.context)
        }
    }
}
<commit_msg>Reply Calls<commit_after>#![crate_name = "hiredis"]
#![crate_type = "lib"]
#![feature(globs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

extern crate libc;

use std::mem::transmute;

pub mod api;

pub struct Reply {
    reply: *const api::Reply
}

impl Reply {
    unsafe fn new(reply: *const api::Reply) -> Reply {
        Reply {
            reply: reply
        }
    }
}

impl Drop for Reply {
    fn drop(&mut self) {
        unsafe {
            api::freeReplyObject(transmute(self.reply))
        }
    }
}

pub struct Redis {
    context: *const api::Context
}

impl Redis {
    pub fn new(ip: &str, port: i32) -> Redis {
        unsafe {
            Redis {
                context: api::redisConnect(
                    ip.to_c_str().as_ptr(),
                    port
                )
            }
        }
    }

    /* TODO: Move to IoResult using context.err */
    pub fn exec(&self, command: &str) -> Option<Reply> {
        command.with_c_str(|v| {
            unsafe {
                let result = api::redisCommand(self.context, v);

                /* Fail if the command errored for some reason. */
                if result == 0 as *const ::libc::c_void {
                    return None;
                }

                /* Otherwise transmute the void pointer memory into a pointer
                 * to a reply structure and return it. */
                Some(Reply::new(transmute(result)))
            }
        })
    }

    pub fn receive(&self) -> Option<Reply> {
        unsafe {
            let reply: Reply = std::mem::uninitialized();
            let result       = api::redisGetReply(self.context, transmute(&reply));

            Some(reply)
        }
    }
}

impl Drop for Redis {
    fn drop(&mut self) {
        unsafe {
            api::redisFree(self.context)
        }
    }
}
<|endoftext|>