<commit_before>//! #Introduction
//! This crate focuses on geting system information.
//!
//! For now it supports Linux, Mac OS X and Windows.
//! And now it can get information of kernel/cpu/memory/disk/load/hostname and so on.
//!

extern crate libc;

use std::ffi;
use std::fmt;
use std::io::{self, Read};
use std::fs::File;
use std::os::raw::c_char;

use libc::sysctl;
use libc::timeval;
use std::mem::size_of_val;
use std::ptr::null_mut;

static MAC_CTL_KERN: libc::c_int = 1;
static MAC_KERN_BOOTTIME: libc::c_int = 21;

/// System load average value.
#[repr(C)]
#[derive(Debug)]
pub struct LoadAvg {
    /// Average load within one minite.
    pub one: f64,
    /// Average load within five minites.
    pub five: f64,
    /// Average load within fifteen minites.
    pub fifteen: f64,
}

/// System memory information.
#[repr(C)]
#[derive(Debug)]
pub struct MemInfo {
    /// Total physical memory.
    pub total: u64,
    pub free: u64,
    pub avail: u64,

    pub buffers: u64,
    pub cached: u64,

    /// Total swap memory.
    pub swap_total: u64,
    pub swap_free: u64,
}

/// Disk information.
#[repr(C)]
#[derive(Debug)]
pub struct DiskInfo {
    pub total: u64,
    pub free: u64,
}

/// Error types
#[derive(Debug)]
pub enum Error {
    UnsupportedSystem,
    ExecFailed(io::Error),
    IO(io::Error),
    Unknown,
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;
        match *self {
            UnsupportedSystem => write!(fmt, "System is not supported"),
            ExecFailed(ref e) => write!(fmt, "Execution failed: {}", e),
            IO(ref e) => write!(fmt, "IO error: {}", e),
            Unknown => write!(fmt, "An unknown error occurred"),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        use self::Error::*;
        match *self {
            UnsupportedSystem => "unsupported system",
            ExecFailed(_) => "execution failed",
            IO(_) => "io error",
            Unknown => "unknown error",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        use self::Error::*;
        match *self {
            UnsupportedSystem => None,
            ExecFailed(ref e) => Some(e),
            IO(ref e) => Some(e),
            Unknown => None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Error {
        Error::IO(e)
    }
}

extern "C" {
    fn get_os_type() -> *const i8;
    fn get_os_release() -> *const i8;

    fn get_cpu_num() -> u32;
    fn get_cpu_speed() -> u64;

    fn get_loadavg() -> LoadAvg;
    fn get_proc_total() -> u64;

    fn get_mem_info() -> MemInfo;
    fn get_disk_info() -> DiskInfo;
}

/// Get operation system type.
///
/// Such as "Linux", "Darwin", "Windows".
pub fn os_type() -> Result<String, Error> {
    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/sys/kernel/ostype")?.read_to_string(&mut s)?;
        s.pop(); // pop '\n'
        Ok(s)
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        let typ = unsafe { ffi::CStr::from_ptr(get_os_type() as *const c_char).to_bytes() };
        Ok(String::from_utf8_lossy(typ).into_owned())
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get operation system release version.
///
/// Such as "3.19.0-gentoo"
pub fn os_release() -> Result<String, Error> {
    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/sys/kernel/osrelease")?.read_to_string(&mut s)?;
        s.pop(); // pop '\n'
        Ok(s)
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        let typ = unsafe { ffi::CStr::from_ptr(get_os_release() as *const c_char).to_bytes() };
        Ok(String::from_utf8_lossy(typ).into_owned())
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get cpu num quantity.
///
/// Notice, it returns the logical cpu quantity.
pub fn cpu_num() -> Result<u32, Error> {
    if cfg!(unix) || cfg!(windows) {
        unsafe { Ok(get_cpu_num()) }
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get cpu speed.
///
/// Such as 2500, that is 2500 MHz.
pub fn cpu_speed() -> Result<u64, Error> {
    if cfg!(target_os = "linux") {
        // /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
        let mut s = String::new();
        File::open("/proc/cpuinfo")?.read_to_string(&mut s)?;

        s.split('\n')
            .find(|line| line.starts_with("cpu MHz"))
            .and_then(|line| line.split(':').last())
            .and_then(|val| val.trim().parse::<f64>().ok())
            .map(|speed| speed as u64)
            .ok_or(Error::Unknown)
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        unsafe { Ok(get_cpu_speed()) }
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get system load average value.
///
/// Notice, on windows, one/five/fifteen of the LoadAvg returned are the current load.
pub fn loadavg() -> Result<LoadAvg, Error> {
    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/loadavg")?.read_to_string(&mut s)?;
        let loads = s.trim().split(' ')
            .take(3)
            .map(|val| val.parse::<f64>().unwrap())
            .collect::<Vec<f64>>();
        Ok(LoadAvg {
            one: loads[0],
            five: loads[1],
            fifteen: loads[2],
        })
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        Ok(unsafe { get_loadavg() })
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get current processes quantity.
///
/// Notice, it temporarily does not support Windows.
pub fn proc_total() -> Result<u64, Error> {
    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/loadavg")?.read_to_string(&mut s)?;
        s.split(' ')
            .nth(3)
            .and_then(|val| val.split('/').last())
            .and_then(|val| val.parse::<u64>().ok())
            .ok_or(Error::Unknown)
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        Ok(unsafe { get_proc_total() })
    } else {
        Err(Error::UnsupportedSystem)
    }
}

// Analyse number from line.
fn get_mem_num(line: &str) -> u64 {
    line.split_whitespace()
        .nth(1)
        .and_then(|val| val.parse::<u64>().ok())
        .unwrap()
}

/// Get memory information.
///
/// On Mac OS X and Windows, the buffers and cached variables of the MemInfo returned are zero.
pub fn mem_info() -> Result<MemInfo, Error> {
    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/meminfo")?.read_to_string(&mut s)?;
        let info = s.lines()
            .map(get_mem_num)
            .collect::<Vec<u64>>();
        Ok(MemInfo {
            total: info[0],
            free: info[1],
            avail: info[2],
            buffers: info[3],
            cached: info[4],
            swap_total: info[14],
            swap_free: info[15],
        })
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        Ok(unsafe { get_mem_info() })
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get disk information.
///
/// Notice, it just calculate current disk on Windows.
pub fn disk_info() -> Result<DiskInfo, Error> {
    if cfg!(target_os = "linux") || cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        Ok(unsafe { get_disk_info() })
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get hostname.
pub fn hostname() -> Result<String, Error> {
    use std::process::Command;
    if cfg!(unix) {
        Command::new("hostname")
            .output()
            .map_err(|e| Error::ExecFailed(e))
            .map(|output| String::from_utf8(output.stdout).unwrap().trim().to_string())
    } else if cfg!(windows) {
        Command::new("hostname")
            .output()
            .map_err(|e| Error::ExecFailed(e))
            .map(|output| String::from_utf8(output.stdout).unwrap().trim().to_string())
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get system boottime
pub fn boottime() -> Result<timeval, Error> {
    let mut bt = timeval {
        tv_sec: 0,
        tv_usec: 0
    };

    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/uptime")?.read_to_string(&mut s)?;
        let secs = s.trim().split(' ')
            .take(2)
            .map(|val| val.parse::<f64>().unwrap())
            .collect::<Vec<f64>>();
        bt.tv_sec = secs[0]  as libc::time_t;
        bt.tv_usec = secs[1] as libc::suseconds_t;
    } else if cfg!(target_os = "macos") {
        let mut mib = [MAC_CTL_KERN, MAC_KERN_BOOTTIME];
        let mut size: libc::size_t = size_of_val(&bt) as libc::size_t;
        unsafe {
            sysctl(&mut mib[0], 2,
                    &mut bt as *mut timeval as *mut libc::c_void,
                    &mut size, null_mut(), 0);
        }
    }

    Ok(bt)
}

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

    #[test]
    pub fn test_os_type() {
        let typ = os_type().unwrap();
        assert!(typ.len() > 0);
        println!("os_type(): {}", typ);
    }

    #[test]
    pub fn test_os_release() {
        let release = os_release().unwrap();
        assert!(release.len() > 0);
        println!("os_release(): {}", release);
    }

    #[test]
    pub fn test_cpu_num() {
        let num = cpu_num().unwrap();
        assert!(num > 0);
        println!("cpu_num(): {}", num);
    }

    #[test]
    pub fn test_cpu_speed() {
        let speed = cpu_speed().unwrap();
        assert!(speed > 0);
        println!("cpu_speed(): {}", speed);
    }

    #[test]
    pub fn test_loadavg() {
        let load = loadavg().unwrap();
        println!("loadavg(): {:?}", load);
    }

    #[test]
    pub fn test_proc_total() {
        let procs = proc_total().unwrap();
        assert!(procs > 0);
        println!("proc_total(): {}", procs);
    }

    #[test]
    pub fn test_mem_info() {
        let mem = mem_info().unwrap();
        assert!(mem.total > 0);
        println!("mem_info(): {:?}", mem);
    }

    #[test]
    pub fn test_disk_info() {
        let info = disk_info().unwrap();
        println!("disk_info(): {:?}", info);
    }

    #[test]
    pub fn test_hostname() {
        let host = hostname().unwrap();
        assert!(host.len() > 0);
        println!("hostname(): {}", host);
    }

    #[test]
    pub fn test_boottime() {
        let bt = boottime().unwrap();
        println!("boottime(): {} {}", bt.tv_sec, bt.tv_usec);
        assert!(bt.tv_sec > 0 || bt.tv_usec > 0);
    }
}
<commit_msg>Fix libc::sysctl missing on Windows builds (#18)<commit_after>//! #Introduction
//! This crate focuses on geting system information.
//!
//! For now it supports Linux, Mac OS X and Windows.
//! And now it can get information of kernel/cpu/memory/disk/load/hostname and so on.
//!

extern crate libc;

use std::ffi;
use std::fmt;
use std::io::{self, Read};
use std::fs::File;
use std::os::raw::c_char;

#[cfg(not(windows))]
use libc::sysctl;
use libc::timeval;
use std::mem::size_of_val;
use std::ptr::null_mut;

static MAC_CTL_KERN: libc::c_int = 1;
static MAC_KERN_BOOTTIME: libc::c_int = 21;

/// System load average value.
#[repr(C)]
#[derive(Debug)]
pub struct LoadAvg {
    /// Average load within one minite.
    pub one: f64,
    /// Average load within five minites.
    pub five: f64,
    /// Average load within fifteen minites.
    pub fifteen: f64,
}

/// System memory information.
#[repr(C)]
#[derive(Debug)]
pub struct MemInfo {
    /// Total physical memory.
    pub total: u64,
    pub free: u64,
    pub avail: u64,

    pub buffers: u64,
    pub cached: u64,

    /// Total swap memory.
    pub swap_total: u64,
    pub swap_free: u64,
}

/// Disk information.
#[repr(C)]
#[derive(Debug)]
pub struct DiskInfo {
    pub total: u64,
    pub free: u64,
}

/// Error types
#[derive(Debug)]
pub enum Error {
    UnsupportedSystem,
    ExecFailed(io::Error),
    IO(io::Error),
    Unknown,
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;
        match *self {
            UnsupportedSystem => write!(fmt, "System is not supported"),
            ExecFailed(ref e) => write!(fmt, "Execution failed: {}", e),
            IO(ref e) => write!(fmt, "IO error: {}", e),
            Unknown => write!(fmt, "An unknown error occurred"),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        use self::Error::*;
        match *self {
            UnsupportedSystem => "unsupported system",
            ExecFailed(_) => "execution failed",
            IO(_) => "io error",
            Unknown => "unknown error",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        use self::Error::*;
        match *self {
            UnsupportedSystem => None,
            ExecFailed(ref e) => Some(e),
            IO(ref e) => Some(e),
            Unknown => None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Error {
        Error::IO(e)
    }
}

extern "C" {
    fn get_os_type() -> *const i8;
    fn get_os_release() -> *const i8;

    fn get_cpu_num() -> u32;
    fn get_cpu_speed() -> u64;

    fn get_loadavg() -> LoadAvg;
    fn get_proc_total() -> u64;

    fn get_mem_info() -> MemInfo;
    fn get_disk_info() -> DiskInfo;
}

/// Get operation system type.
///
/// Such as "Linux", "Darwin", "Windows".
pub fn os_type() -> Result<String, Error> {
    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/sys/kernel/ostype")?.read_to_string(&mut s)?;
        s.pop(); // pop '\n'
        Ok(s)
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        let typ = unsafe { ffi::CStr::from_ptr(get_os_type() as *const c_char).to_bytes() };
        Ok(String::from_utf8_lossy(typ).into_owned())
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get operation system release version.
///
/// Such as "3.19.0-gentoo"
pub fn os_release() -> Result<String, Error> {
    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/sys/kernel/osrelease")?.read_to_string(&mut s)?;
        s.pop(); // pop '\n'
        Ok(s)
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        let typ = unsafe { ffi::CStr::from_ptr(get_os_release() as *const c_char).to_bytes() };
        Ok(String::from_utf8_lossy(typ).into_owned())
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get cpu num quantity.
///
/// Notice, it returns the logical cpu quantity.
pub fn cpu_num() -> Result<u32, Error> {
    if cfg!(unix) || cfg!(windows) {
        unsafe { Ok(get_cpu_num()) }
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get cpu speed.
///
/// Such as 2500, that is 2500 MHz.
pub fn cpu_speed() -> Result<u64, Error> {
    if cfg!(target_os = "linux") {
        // /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
        let mut s = String::new();
        File::open("/proc/cpuinfo")?.read_to_string(&mut s)?;

        s.split('\n')
            .find(|line| line.starts_with("cpu MHz"))
            .and_then(|line| line.split(':').last())
            .and_then(|val| val.trim().parse::<f64>().ok())
            .map(|speed| speed as u64)
            .ok_or(Error::Unknown)
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        unsafe { Ok(get_cpu_speed()) }
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get system load average value.
///
/// Notice, on windows, one/five/fifteen of the LoadAvg returned are the current load.
pub fn loadavg() -> Result<LoadAvg, Error> {
    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/loadavg")?.read_to_string(&mut s)?;
        let loads = s.trim().split(' ')
            .take(3)
            .map(|val| val.parse::<f64>().unwrap())
            .collect::<Vec<f64>>();
        Ok(LoadAvg {
            one: loads[0],
            five: loads[1],
            fifteen: loads[2],
        })
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        Ok(unsafe { get_loadavg() })
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get current processes quantity.
///
/// Notice, it temporarily does not support Windows.
pub fn proc_total() -> Result<u64, Error> {
    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/loadavg")?.read_to_string(&mut s)?;
        s.split(' ')
            .nth(3)
            .and_then(|val| val.split('/').last())
            .and_then(|val| val.parse::<u64>().ok())
            .ok_or(Error::Unknown)
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        Ok(unsafe { get_proc_total() })
    } else {
        Err(Error::UnsupportedSystem)
    }
}

// Analyse number from line.
fn get_mem_num(line: &str) -> u64 {
    line.split_whitespace()
        .nth(1)
        .and_then(|val| val.parse::<u64>().ok())
        .unwrap()
}

/// Get memory information.
///
/// On Mac OS X and Windows, the buffers and cached variables of the MemInfo returned are zero.
pub fn mem_info() -> Result<MemInfo, Error> {
    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/meminfo")?.read_to_string(&mut s)?;
        let info = s.lines()
            .map(get_mem_num)
            .collect::<Vec<u64>>();
        Ok(MemInfo {
            total: info[0],
            free: info[1],
            avail: info[2],
            buffers: info[3],
            cached: info[4],
            swap_total: info[14],
            swap_free: info[15],
        })
    } else if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        Ok(unsafe { get_mem_info() })
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get disk information.
///
/// Notice, it just calculate current disk on Windows.
pub fn disk_info() -> Result<DiskInfo, Error> {
    if cfg!(target_os = "linux") || cfg!(target_os = "macos") || cfg!(target_os = "windows") {
        Ok(unsafe { get_disk_info() })
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get hostname.
pub fn hostname() -> Result<String, Error> {
    use std::process::Command;
    if cfg!(unix) {
        Command::new("hostname")
            .output()
            .map_err(|e| Error::ExecFailed(e))
            .map(|output| String::from_utf8(output.stdout).unwrap().trim().to_string())
    } else if cfg!(windows) {
        Command::new("hostname")
            .output()
            .map_err(|e| Error::ExecFailed(e))
            .map(|output| String::from_utf8(output.stdout).unwrap().trim().to_string())
    } else {
        Err(Error::UnsupportedSystem)
    }
}

/// Get system boottime
#[cfg(not(windows))]
pub fn boottime() -> Result<timeval, Error> {
    let mut bt = timeval {
        tv_sec: 0,
        tv_usec: 0
    };

    if cfg!(target_os = "linux") {
        let mut s = String::new();
        File::open("/proc/uptime")?.read_to_string(&mut s)?;
        let secs = s.trim().split(' ')
            .take(2)
            .map(|val| val.parse::<f64>().unwrap())
            .collect::<Vec<f64>>();
        bt.tv_sec = secs[0]  as libc::time_t;
        bt.tv_usec = secs[1] as libc::suseconds_t;
    } else if cfg!(target_os = "macos") {
        let mut mib = [MAC_CTL_KERN, MAC_KERN_BOOTTIME];
        let mut size: libc::size_t = size_of_val(&bt) as libc::size_t;
        unsafe {
            sysctl(&mut mib[0], 2,
                    &mut bt as *mut timeval as *mut libc::c_void,
                    &mut size, null_mut(), 0);
        }
    }

    Ok(bt)
}

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

    #[test]
    pub fn test_os_type() {
        let typ = os_type().unwrap();
        assert!(typ.len() > 0);
        println!("os_type(): {}", typ);
    }

    #[test]
    pub fn test_os_release() {
        let release = os_release().unwrap();
        assert!(release.len() > 0);
        println!("os_release(): {}", release);
    }

    #[test]
    pub fn test_cpu_num() {
        let num = cpu_num().unwrap();
        assert!(num > 0);
        println!("cpu_num(): {}", num);
    }

    #[test]
    pub fn test_cpu_speed() {
        let speed = cpu_speed().unwrap();
        assert!(speed > 0);
        println!("cpu_speed(): {}", speed);
    }

    #[test]
    pub fn test_loadavg() {
        let load = loadavg().unwrap();
        println!("loadavg(): {:?}", load);
    }

    #[test]
    pub fn test_proc_total() {
        let procs = proc_total().unwrap();
        assert!(procs > 0);
        println!("proc_total(): {}", procs);
    }

    #[test]
    pub fn test_mem_info() {
        let mem = mem_info().unwrap();
        assert!(mem.total > 0);
        println!("mem_info(): {:?}", mem);
    }

    #[test]
    pub fn test_disk_info() {
        let info = disk_info().unwrap();
        println!("disk_info(): {:?}", info);
    }

    #[test]
    pub fn test_hostname() {
        let host = hostname().unwrap();
        assert!(host.len() > 0);
        println!("hostname(): {}", host);
    }

    #[test]
    pub fn test_boottime() {
        let bt = boottime().unwrap();
        println!("boottime(): {} {}", bt.tv_sec, bt.tv_usec);
        assert!(bt.tv_sec > 0 || bt.tv_usec > 0);
    }
}
<|endoftext|>


<commit_before>/**
Katy Williamson kcw4sn
Ben Terner bt3ze
@virginia.edu

Final Project for CS4414 - Operating Systems
A parallel MST implementation on images in Rust

*/

extern mod extra;
use std::{os, num,hashmap,str} ;
use extra::{arc,priority_queue};

struct Pixel{
    r: int,
    b: int,
    g: int,
    color: int,
    x: int,
    y: int
}

impl Pixel {
    fn new(red: int, blue: int, green: int) -> Pixel {
        Pixel{
            r: red,
            b: blue,
            g: green,
            color: 0,
            x: 0,
            y: 0
        }
    }
}

struct Edge {
    source: Pixel,
    dest: Pixel,
    cost: float
}

impl Edge {
    fn new(s: Pixel, d: Pixel) -> Edge {
        Edge { // these need to be references to pixels, not copies.
            // for standard prim, it's alright for now
            source: s,
            dest: d,
            cost: edgeCost(s,d)
        }
    }
}

impl Ord for Edge {
    fn lt(&self, other: &Edge) -> bool {
        self.cost < other.cost
    }
}

fn edgeCost(a: Pixel, b: Pixel) -> float {
    num::sqrt( (
            a.r*a.r-b.r*b.r + a.g*a.g-b.g*b.g + a.b*a.b-b.b*b.b ) as float)
}

fn readImage( filename: &~str) -> ~ [ ~[Pixel]] {
    ~[~[]]
}

fn main(){
    let argv =  os::args();
    println(argv.to_str());
    let length = match from_str::<int>(argv[2]) {
        Some(x) => x,
        None() => 0
    };
    let width = match from_str::<int>(argv[3]) {
        Some(x) => x,
        None() => 0
    };

    let pixels: ~[ ~[Pixel] ] = readImage(&argv[1]);
    let mut find_arcs: ~[ ~[arc::RWArc<Pixel>] ] =  ~[ ~[]];
    let mut len = 0;
    let mut wid = 0;
    loop {
        loop {
            find_arcs[len][wid] = arc::RWArc::new(pixels[len][wid]);
                wid+=1;
            if(wid == width) {
                wid = 0;
                break;
            }
        }
        len+=1;
        if(len == length) {
            break;
        }
    }

    let arcs = find_arcs; // now we have an immutable array that can be shared

    let mut x= 0;
    let mut y= 0;
    let mut queue: priority_queue::PriorityQueue<Edge> =  priority_queue::PriorityQueue::new();
    let mut visited: hashmap::HashMap<(int,int),bool> = hashmap::HashMap::new();
    loop { // iterate through items in the queue, which contains all of the edges/vertices

        let edge = queue.maybe_pop();
        match edge {
            Some(e) => {
                if e.dest.color == 0 {
                    // not in any tree
                    let coord = (e.dest.x,e.dest.y);
                    if *visited.get(&coord) == false { // use visited hashmap to figure out if we're at a new vertex
                        visited.insert(coord,true);
                        x = e.dest.x;
                        y = e.dest.y;
                        let neighbors = [ (x,y-1),(x+1,y), (x,y+1), (x,y-1)];
                        for &coord in neighbors.iter() {
                            let (w,z) = coord;
                            if w >=0 && w < width && z >=0 && z <= length { // bounds checking
                                // if neighbor at coord has not been or colored
                                if pixels[w][z].color != 0 { // then we have a new vertex
                                    queue.push( Edge::new(pixels[x][y],pixels[w][z]) );
                                }
                            }
                        }
                    }

                    // use an arc to write the following
                    // e.dest.color = e.source.color;
                }
            }
            None => { break; } // this should really never execute till the end
        }
    }

}
<commit_msg>using points now for indirection between edges and pixels. no managed pointers.<commit_after>/**
Katy Williamson kcw4sn
Ben Terner bt3ze
@virginia.edu

Final Project for CS4414 - Operating Systems
A parallel MST implementation on images in Rust

*/

/*
some documentation:
Pixel object is composed of r,g,b values, a color, and an x,y index that takes the place of its adjacency list
Point is just an (x,y) value to denote a pixel's location
Edge contains two points: source and dest, along with the edge cost between them

*/

extern mod extra;
use std::{os, num,hashmap,str} ;
use extra::{arc,priority_queue};

struct Pixel{
    r: int,
    b: int,
    g: int,
    color: int,
    x: int,
    y: int
}

impl Pixel {
    fn new(red: int, blue: int, green: int, x: int, y: int) -> Pixel {
        Pixel{
            r: red,
            b: blue,
            g: green,
            color: -1,
            x: x,
            y: y
        }
    }
}

struct Point {
    x: int,
    y: int
}

impl Point{
    fn new(x: int, y: int)-> Point {
        Point {
            x: x,
            y: y
        }
    }
}

struct Edge {
    source: Point,
    dest: Point,
    cost: float
}

impl Edge {
    fn new(s: Point, d: Point, cost: float) -> Edge {
        Edge { // these need to be references to pixels, not copies.
            // for standard prim, it's alright for now
            source: s,
            dest: d,
            cost: cost
        }
    }
}

impl Ord for Edge {
    fn lt(&self, other: &Edge) -> bool {
        self.cost < other.cost
    }
}

fn edgeCost(a: &Pixel, b: &Pixel) -> float {
    num::sqrt( (
            a.r*a.r-b.r*b.r + a.g*a.g-b.g*b.g + a.b*a.b-b.b*b.b ) as float)
}

fn readImage( filename: &~str) -> ~ [ ~[Pixel]] {
    ~[~[]]
}

fn main(){
    let argv =  os::args();
    println(argv.to_str());
    let length = match from_str::<int>(argv[2]) {
        Some(x) => x,
        None() => 0
    };
    let width = match from_str::<int>(argv[3]) {
        Some(x) => x,
        None() => 0
    };

    let pixels: ~[ ~[Pixel] ] = readImage(&argv[1]);
    let mut find_arcs: ~[ ~[arc::RWArc<Pixel>] ] =  ~[ ~[]];
    let mut len = 0;
    let mut wid = 0;
    loop {
        loop {
            find_arcs[len][wid] = arc::RWArc::new(pixels[len][wid]);
                wid+=1;
            if(wid == width) {
                wid = 0;
                break;
            }
        }
        len+=1;
        if(len == length) {
            break;
        }
    }

    let arcs = find_arcs; // now we have an immutable array that can be shared

    let mut x= 0;
    let mut y= 0;

    let mut queue: priority_queue::PriorityQueue<Edge> =  priority_queue::PriorityQueue::new();
    let mut visited: hashmap::HashMap<(int,int),bool> = hashmap::HashMap::new();

    loop { // iterate through items in the queue, which contains all of the edges/vertices

        let edge = queue.maybe_pop();
        match edge {
            Some(e) => {
                if e.dest.color < 0 {
                    // not in any tree
                    let coord = (e.dest.x,e.dest.y);
                    if *visited.get(&coord) == false { // use visited hashmap to figure out if we're at a new vertex
                        visited.insert(coord,true);
                        x = e.dest.x;
                        y = e.dest.y;
                        let neighbors = [ (x,y-1),(x+1,y), (x,y+1), (x,y-1)];
                        for &coord in neighbors.iter() {
                            let (w,z) = coord;
                            if w >=0 && w < width && z >=0 && z <= length { // bounds checking
                                // if neighbor at coord has not been or colored
                                if pixels[w][z].color < 0 { // then we have a new vertex
                                    queue.push( Edge::new(Point::new(x,y),Point::new(w,z),edgeCost(&pixels[x][y],&pixels[w][z])));
                                }
                            }
                        }
                    }

                    // use an arc to write the following
                    // e.dest.color = e.source.color;
                }
            }
            None => { break; } // this should really never execute till the end
        }
    }

}
<|endoftext|>


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

use quote::{Tokens, ToTokens};
use syn::{Ident, Lit, MetaItem, NestedMetaItem, MacroInput};
use case::CaseExt;

pub struct Command {
    ast: MacroInput,
}

impl Command {
    pub fn new(ast: MacroInput) -> Command {
        Command {
            ast: ast,
        }
    }

    pub fn derive(&self) -> Tokens {
        let typ = self.typ();
        let docs = self.docs();
        let sig = self.sig();
        let body = self.body();

        quote! {
            #docs
            pub trait #typ {
                fn #sig;
            }

            impl #typ for ::Command {
                fn #sig {
                    #body
                }
            }
        }
    }

    fn command(&self) -> &MetaItem {
        let mut commands = self.ast.attrs.iter().filter(|attr| {
                if let MetaItem::List(ref attr, _) = attr.value {
                    attr == "command"
                } else {
                    false
                }
            })
        .peekable();
        let command = commands.peek().expect("command attribute not defined");
        let mut meta_items = Vec::new();
        match command.value {
            MetaItem::List(_, ref items) => {
                if items.len() != 1 {
                    panic!("A command attribute must only carry one command.");
                }
                for item in items {
                    match *item {
                        NestedMetaItem::MetaItem(ref command) => { meta_items.push(command); },
                        NestedMetaItem::Literal(_) => { panic!("A command attribute should not define commands as literals"); },
                    }
                }
            }
            _ => { panic!("A command attribute must be defined as a list of items. That is `#[command(..)]`."); },
        };
        meta_items.iter().next().unwrap()
    }

    fn name(&self) -> &Ident {
        match *self.command() {
            MetaItem::Word(ref name) => name,
            MetaItem::List(ref name, _) => name,
            MetaItem::NameValue(..) => { panic!("A command must not be a name value pair"); },
        }
    }

    fn value(&self) -> Vec<&NestedMetaItem> {
        let mut value = Vec::new();
        match *self.command() {
            MetaItem::Word(_) => { },
            MetaItem::List(_, ref items) => {
                for item in items {
                    value.push(item);
                }
            }
            MetaItem::NameValue(..) => { panic!("A command must not be a name value pair"); },
        }
        value
    }

    fn args(&self) -> Vec<(Ident, Ident)> {
        let mut args = Vec::new();
        for item in self.value() {
            if let NestedMetaItem::MetaItem(MetaItem::List(ref name, ref value)) = *item {
                if name == "args" {
                    for item in value {
                        match *item {
                            NestedMetaItem::MetaItem(ref item) => {
                                if let MetaItem::NameValue(ref name, ref typ) = *item {
                                    match *typ {
                                        Lit::Str(ref typ, _) => {
                                            args.push((name.clone(), Ident::new(typ.as_str())));
                                        }
                                        _ => { panic!("An arg name must be defined as a string"); },
                                    };
                                } else {
                                    panic!("Args must be key value pairs");
                                }
                            },
                            NestedMetaItem::Literal(_) => { panic!("Args must not be literals"); },
                        }
                    }
                }
            }
        }
        args
    }

    fn typ(&self) -> Tokens {
        let name = self.name().to_string().to_camel();
        let typ = Ident::new(name);
        quote!(#typ)
    }

    fn docs(&self) -> Tokens {
        let mut docs = Tokens::new();
        for attr in self.ast.attrs.iter() {
            if let MetaItem::NameValue(ref name, _) = attr.value {
                if name == "doc" {
                    attr.to_tokens(&mut docs);
                }
            }
        }
        docs
    }

    fn sig(&self) -> Tokens {
        let mut types = HashMap::new();

        let func = self.name().clone();
        let mut generics = Tokens::new();
        let mut func_args = Tokens::new();
        let mut _where = Tokens::new();

        let args = self.args();
        if !args.is_empty() {
            let mut gen = Vec::new();
            let mut whe = Vec::new();

            gen.push(quote!(<));
            whe.push(quote!(where));

            for (arg, typ) in args {
                let typ_str = typ.to_string();
                if let None = types.get(&typ_str) {
                    gen.push(quote!(#typ));
                    gen.push(quote!(,));
                    whe.push(quote!(#typ: ::IntoArg));
                    whe.push(quote!(,));
                    types.insert(typ_str, ());
                }
                func_args.append_all(&[ quote!(, #arg: #typ) ]);
            }

            gen.pop();
            whe.pop();

            gen.push(quote!(>));

            generics.append_all(gen);
            _where.append_all(whe);
        }

        quote! {
            #func #generics (self #func_args) -> ::Command #_where
        }
    }

    fn body(&self) -> Tokens {
        let cmd = match self.name() {
            name if name == "match_" => "match".to_string(),
            name if name == "mod_" => "mod".to_string(),
            name if name == "do_" => "funcall".to_string(),
            name => name.to_string(),
        };
        let cmd_type = Ident::new(cmd.to_snake().to_uppercase());
        let mut args = Tokens::new();
        for (arg, _) in self.args() {
            let token = quote! {
                for arg in #arg.into_arg() {
                    term.mut_args().push(arg);
                }
            };
            token.to_tokens(&mut args);
        }

        quote! {
            let mut term = ::ql2::proto::Term::new();
            term.set_field_type(::ql2::proto::Term_TermType::#cmd_type);
            if let Some(cmd) = self.term {
                let args = ::protobuf::repeated::RepeatedField::from_vec(vec![cmd]);
                term.set_args(args);
            }
            #args
            ::Command {
                term: Some(term),
                idx: self.idx + 1,
            }
        }
    }
}
<commit_msg>Add a note about where to find more documentation where necessary<commit_after>use std::collections::HashMap;

use quote::{Tokens, ToTokens};
use syn::{Ident, Lit, MetaItem, NestedMetaItem, MacroInput};
use case::CaseExt;

pub struct Command {
    ast: MacroInput,
}

impl Command {
    pub fn new(ast: MacroInput) -> Command {
        Command {
            ast: ast,
        }
    }

    pub fn derive(&self) -> Tokens {
        let typ = self.typ();
        let docs = self.docs();
        let sig = self.sig();
        let body = self.body();

        let mut note = Tokens::new();
        if !docs.to_string().contains("```rust") {
            let msg = format!("**Note:** This command is not yet fully documented. For more information and examples, please see [the equivalent command](https://rethinkdb.com/api/java/{}/) in the official Java driver documentation.", self.name());
            note.append_all(&[quote!{
                ///
                #[doc=#msg]
            }]);
        }

        quote! {
            #docs
            #note
            pub trait #typ {
                fn #sig;
            }

            impl #typ for ::Command {
                fn #sig {
                    #body
                }
            }
        }
    }

    fn command(&self) -> &MetaItem {
        let mut commands = self.ast.attrs.iter().filter(|attr| {
                if let MetaItem::List(ref attr, _) = attr.value {
                    attr == "command"
                } else {
                    false
                }
            })
        .peekable();
        let command = commands.peek().expect("command attribute not defined");
        let mut meta_items = Vec::new();
        match command.value {
            MetaItem::List(_, ref items) => {
                if items.len() != 1 {
                    panic!("A command attribute must only carry one command.");
                }
                for item in items {
                    match *item {
                        NestedMetaItem::MetaItem(ref command) => { meta_items.push(command); },
                        NestedMetaItem::Literal(_) => { panic!("A command attribute should not define commands as literals"); },
                    }
                }
            }
            _ => { panic!("A command attribute must be defined as a list of items. That is `#[command(..)]`."); },
        };
        meta_items.iter().next().unwrap()
    }

    fn name(&self) -> &Ident {
        match *self.command() {
            MetaItem::Word(ref name) => name,
            MetaItem::List(ref name, _) => name,
            MetaItem::NameValue(..) => { panic!("A command must not be a name value pair"); },
        }
    }

    fn value(&self) -> Vec<&NestedMetaItem> {
        let mut value = Vec::new();
        match *self.command() {
            MetaItem::Word(_) => { },
            MetaItem::List(_, ref items) => {
                for item in items {
                    value.push(item);
                }
            }
            MetaItem::NameValue(..) => { panic!("A command must not be a name value pair"); },
        }
        value
    }

    fn args(&self) -> Vec<(Ident, Ident)> {
        let mut args = Vec::new();
        for item in self.value() {
            if let NestedMetaItem::MetaItem(MetaItem::List(ref name, ref value)) = *item {
                if name == "args" {
                    for item in value {
                        match *item {
                            NestedMetaItem::MetaItem(ref item) => {
                                if let MetaItem::NameValue(ref name, ref typ) = *item {
                                    match *typ {
                                        Lit::Str(ref typ, _) => {
                                            args.push((name.clone(), Ident::new(typ.as_str())));
                                        }
                                        _ => { panic!("An arg name must be defined as a string"); },
                                    };
                                } else {
                                    panic!("Args must be key value pairs");
                                }
                            },
                            NestedMetaItem::Literal(_) => { panic!("Args must not be literals"); },
                        }
                    }
                }
            }
        }
        args
    }

    fn typ(&self) -> Tokens {
        let name = self.name().to_string().to_camel();
        let typ = Ident::new(name);
        quote!(#typ)
    }

    fn docs(&self) -> Tokens {
        let mut docs = Tokens::new();
        for attr in self.ast.attrs.iter() {
            if let MetaItem::NameValue(ref name, _) = attr.value {
                if name == "doc" {
                    attr.to_tokens(&mut docs);
                }
            }
        }
        docs
    }

    fn sig(&self) -> Tokens {
        let mut types = HashMap::new();

        let func = self.name().clone();
        let mut generics = Tokens::new();
        let mut func_args = Tokens::new();
        let mut _where = Tokens::new();

        let args = self.args();
        if !args.is_empty() {
            let mut gen = Vec::new();
            let mut whe = Vec::new();

            gen.push(quote!(<));
            whe.push(quote!(where));

            for (arg, typ) in args {
                let typ_str = typ.to_string();
                if let None = types.get(&typ_str) {
                    gen.push(quote!(#typ));
                    gen.push(quote!(,));
                    whe.push(quote!(#typ: ::IntoArg));
                    whe.push(quote!(,));
                    types.insert(typ_str, ());
                }
                func_args.append_all(&[ quote!(, #arg: #typ) ]);
            }

            gen.pop();
            whe.pop();

            gen.push(quote!(>));

            generics.append_all(gen);
            _where.append_all(whe);
        }

        quote! {
            #func #generics (&self #func_args) -> ::Command #_where
        }
    }

    fn body(&self) -> Tokens {
        let cmd = match self.name() {
            name if name == "match_" => "match".to_string(),
            name if name == "mod_" => "mod".to_string(),
            name if name == "do_" => "funcall".to_string(),
            name => name.to_string(),
        };
        let cmd_type = Ident::new(cmd.to_snake().to_uppercase());
        let mut args = Tokens::new();
        for (arg, _) in self.args() {
            let token = quote! {
                for arg in #arg.into_arg() {
                    term.mut_args().push(arg);
                }
            };
            token.to_tokens(&mut args);
        }

        quote! {
            let mut term = ::ql2::proto::Term::new();
            term.set_field_type(::ql2::proto::Term_TermType::#cmd_type);
            if let Some(ref cmd) = self.term {
                let args = ::protobuf::repeated::RepeatedField::from_vec(vec![cmd.clone()]);
                term.set_args(args);
            }
            #args
            ::Command {
                term: Some(term),
                idx: self.idx + 1,
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use middle::typing::ast::*;
use back::code_printer::*;
use back::compiler::rule::*;
use rust;

pub struct GrammarCompiler<'a, 'b: 'a>
{
  grammar: TGrammar<'a, 'b>
}

impl<'a, 'b> GrammarCompiler<'a, 'b>
{
  pub fn compile(grammar: TGrammar<'a, 'b>) -> Box<rust::MacResult + 'a> {
    let compiler = GrammarCompiler::new(grammar);
    let mod_content = compiler.compile_mod_content();
    let module = compiler.compile_grammar_module(mod_content);
    print_code(&compiler.grammar, &module);
    let smvec = rust::SmallVec::<[rust::P<rust::Item>; 1]>::new();
    rust::MacEager::items(smvec)
  }

  fn new(grammar: TGrammar<'a, 'b>) -> GrammarCompiler<'a, 'b> {
    GrammarCompiler {
      grammar: grammar
    }
  }

  fn compile_grammar_module(&self, module_content: Vec<RItem>) -> RItem {
    let grammar_name = self.grammar.name;
    let module = quote_item!(self.cx(),
      pub mod $grammar_name
      {
        #![allow(unused_mut)]
        use oak_runtime::stream::*;
        #[allow(unused_imports)]
        use oak_runtime::str_stream::StrStream;
        #[allow(unused_imports)]
        use std::ops::Range;

        $module_content
      }
    ).expect("Quote the grammar module.");
    self.insert_runtime_crate(module)
  }

  // RUST BUG: We cannot quote `extern crate oak_runtime;` before the grammar module, so we use this workaround
  // for adding the external crate after the creation of the module.
  fn insert_runtime_crate(&self, module: RItem) -> RItem {
    let runtime_crate = quote_item!(self.cx(),
      extern crate oak_runtime;
    ).expect("Quote the extern PEG crate.");

    match &module.node {
      &rust::ItemKind::Mod(ref module_code) => {
        let mut items = vec![runtime_crate];
        items.extend_from_slice(module_code.items.clone().as_slice());
        rust::P(rust::Item {
          ident: module.ident,
          attrs: module.attrs.clone(),
          id: rust::DUMMY_NODE_ID,
          node: rust::ItemKind::Mod(rust::Mod{
            inner: rust::DUMMY_SP,
            items: items,
            inline: false
          }),
          vis: rust::Spanned { node: rust::VisibilityKind::Public, span: rust::DUMMY_SP },
          span: rust::DUMMY_SP,
          tokens: None
        })
      },
      _ => unreachable!()
    }
  }

  fn compile_mod_content(&self) -> Vec<RItem> {
    let mut mod_content = self.compile_rules();
    mod_content.extend(self.grammar.rust_items.clone().into_iter());
    mod_content.extend(self.grammar.rust_functions.values().cloned());
    mod_content
  }

  fn compile_rules(&self) -> Vec<RItem> {
    self.grammar.rules.iter()
      .flat_map(|&rule| RuleCompiler::compile(&self.grammar, rule).into_iter())
      .collect()
  }

  fn cx(&self) -> &'a ExtCtxt<'b> {
    &self.grammar.cx
  }
}

<commit_msg>Adding module to smvec<commit_after>// Copyright 2016 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use middle::typing::ast::*;
use back::code_printer::*;
use back::compiler::rule::*;
use rust;

pub struct GrammarCompiler<'a, 'b: 'a>
{
  grammar: TGrammar<'a, 'b>
}

impl<'a, 'b> GrammarCompiler<'a, 'b>
{
  pub fn compile(grammar: TGrammar<'a, 'b>) -> Box<rust::MacResult + 'a> {
    let compiler = GrammarCompiler::new(grammar);
    let mod_content = compiler.compile_mod_content();
    let module = compiler.compile_grammar_module(mod_content);
    print_code(&compiler.grammar, &module);
    let smvec = rust::SmallVec::<[rust::P<rust::Item>; 1]>::from_vec(vec![module]);
    rust::MacEager::items(smvec)
  }

  fn new(grammar: TGrammar<'a, 'b>) -> GrammarCompiler<'a, 'b> {
    GrammarCompiler {
      grammar: grammar
    }
  }

  fn compile_grammar_module(&self, module_content: Vec<RItem>) -> RItem {
    let grammar_name = self.grammar.name;
    let module = quote_item!(self.cx(),
      pub mod $grammar_name
      {
        #![allow(unused_mut)]
        use oak_runtime::stream::*;
        #[allow(unused_imports)]
        use oak_runtime::str_stream::StrStream;
        #[allow(unused_imports)]
        use std::ops::Range;

        $module_content
      }
    ).expect("Quote the grammar module.");
    self.insert_runtime_crate(module)
  }

  // RUST BUG: We cannot quote `extern crate oak_runtime;` before the grammar module, so we use this workaround
  // for adding the external crate after the creation of the module.
  fn insert_runtime_crate(&self, module: RItem) -> RItem {
    let runtime_crate = quote_item!(self.cx(),
      extern crate oak_runtime;
    ).expect("Quote the extern PEG crate.");

    match &module.node {
      &rust::ItemKind::Mod(ref module_code) => {
        let mut items = vec![runtime_crate];
        items.extend_from_slice(module_code.items.clone().as_slice());
        rust::P(rust::Item {
          ident: module.ident,
          attrs: module.attrs.clone(),
          id: rust::DUMMY_NODE_ID,
          node: rust::ItemKind::Mod(rust::Mod{
            inner: rust::DUMMY_SP,
            items: items,
            inline: false
          }),
          vis: rust::Spanned { node: rust::VisibilityKind::Public, span: rust::DUMMY_SP },
          span: rust::DUMMY_SP,
          tokens: None
        })
      },
      _ => unreachable!()
    }
  }

  fn compile_mod_content(&self) -> Vec<RItem> {
    let mut mod_content = self.compile_rules();
    mod_content.extend(self.grammar.rust_items.clone().into_iter());
    mod_content.extend(self.grammar.rust_functions.values().cloned());
    mod_content
  }

  fn compile_rules(&self) -> Vec<RItem> {
    self.grammar.rules.iter()
      .flat_map(|&rule| RuleCompiler::compile(&self.grammar, rule).into_iter())
      .collect()
  }

  fn cx(&self) -> &'a ExtCtxt<'b> {
    &self.grammar.cx
  }
}

<|endoftext|>


<commit_before>use serde::Deserialize;
use std::collections::BTreeMap;
use std::path::Path;

use std::collections::BTreeSet as Set;
use std::fs;

/// A lookup table from TypeName to Entry.
pub type NodeTypeMap = BTreeMap<TypeName, Entry>;

#[derive(Debug)]
pub struct Entry {
    pub dbscheme_name: String,
    pub ql_class_name: String,
    pub kind: EntryKind,
}

#[derive(Debug)]
pub enum EntryKind {
    Union { members: Set<TypeName> },
    Table { name: String, fields: Vec<Field> },
    Token { kind_id: usize },
}

#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
pub struct TypeName {
    pub kind: String,
    pub named: bool,
}

#[derive(Debug)]
pub enum FieldTypeInfo {
    /// The field has a single type.
    Single(TypeName),

    /// The field can take one of several types, so we also provide the name of
    /// the database union type that wraps them, and the corresponding QL class
    /// name.
    Multiple {
        types: Set<TypeName>,
        dbscheme_union: String,
        ql_class: String,
    },

    /// The field can be one of several tokens, so the db type will be an `int`
    /// with a `case @foo.kind` for each possiblity.
    ReservedWordInt(BTreeMap<String, (usize, String)>),
}

#[derive(Debug)]
pub struct Field {
    pub parent: TypeName,
    pub type_info: FieldTypeInfo,
    /// The name of the field or None for the anonymous 'children'
    /// entry from node_types.json
    pub name: Option<String>,
    /// The name of the predicate to get this field.
    pub getter_name: String,
    pub storage: Storage,
}

fn name_for_field_or_child(name: &Option<String>) -> String {
    match name {
        Some(name) => name.clone(),
        None => "child".to_owned(),
    }
}

#[derive(Debug)]
pub enum Storage {
    /// the field is stored as a column in the parent table
    Column { name: String },
    /// the field is stored in a link table, and may or may not have an
    /// associated index column
    Table { name: String, has_index: bool },
}

pub fn read_node_types(node_types_path: &Path) -> std::io::Result<NodeTypeMap> {
    let file = fs::File::open(node_types_path)?;
    let node_types = serde_json::from_reader(file)?;
    Ok(convert_nodes(&node_types))
}

pub fn read_node_types_str(node_types_json: &str) -> std::io::Result<NodeTypeMap> {
    let node_types = serde_json::from_str(node_types_json)?;
    Ok(convert_nodes(&node_types))
}

fn convert_type(node_type: &NodeType) -> TypeName {
    TypeName {
        kind: node_type.kind.to_string(),
        named: node_type.named,
    }
}

fn convert_types(node_types: &Vec<NodeType>) -> Set<TypeName> {
    let iter = node_types.iter().map(convert_type).collect();
    std::collections::BTreeSet::from(iter)
}

pub fn convert_nodes(nodes: &Vec<NodeInfo>) -> NodeTypeMap {
    let mut entries = NodeTypeMap::new();
    let mut token_kinds = Set::new();

    // First, find all the token kinds
    for node in nodes {
        if node.subtypes.is_none() {
            if node.fields.as_ref().map_or(0, |x| x.len()) == 0 && node.children.is_none() {
                let type_name = TypeName {
                    kind: node.kind.clone(),
                    named: node.named,
                };
                token_kinds.insert(type_name);
            }
        }
    }

    for node in nodes {
        let flattened_name = &node_type_name(&node.kind, node.named);
        let dbscheme_name = escape_name(&flattened_name);
        let ql_class_name = dbscheme_name_to_class_name(&dbscheme_name);
        if let Some(subtypes) = &node.subtypes {
            // It's a tree-sitter supertype node, for which we create a union
            // type.
            entries.insert(
                TypeName {
                    kind: node.kind.clone(),
                    named: node.named,
                },
                Entry {
                    dbscheme_name,
                    ql_class_name,
                    kind: EntryKind::Union {
                        members: convert_types(&subtypes),
                    },
                },
            );
        } else if node.fields.as_ref().map_or(0, |x| x.len()) == 0 && node.children.is_none() {
            // Token kind, handled above.
        } else {
            // It's a product type, defined by a table.
            let type_name = TypeName {
                kind: node.kind.clone(),
                named: node.named,
            };
            let table_name = escape_name(&(format!("{}_def", &flattened_name)));
            let mut fields = Vec::new();

            // If the type also has fields or children, then we create either
            // auxiliary tables or columns in the defining table for them.
            if let Some(node_fields) = &node.fields {
                for (field_name, field_info) in node_fields {
                    add_field(
                        &type_name,
                        Some(field_name.to_string()),
                        field_info,
                        &mut fields,
                        &token_kinds,
                    );
                }
            }
            if let Some(children) = &node.children {
                // Treat children as if they were a field called 'child'.
                add_field(&type_name, None, children, &mut fields, &token_kinds);
            }
            entries.insert(
                type_name,
                Entry {
                    dbscheme_name,
                    ql_class_name,
                    kind: EntryKind::Table {
                        name: table_name,
                        fields,
                    },
                },
            );
        }
    }
    let mut counter = 0;
    for type_name in token_kinds {
        let entry = if type_name.named {
            counter += 1;
            let unprefixed_name = node_type_name(&type_name.kind, true);
            Entry {
                dbscheme_name: escape_name(&format!("token_{}", &unprefixed_name)),
                ql_class_name: dbscheme_name_to_class_name(&escape_name(&unprefixed_name)),
                kind: EntryKind::Token { kind_id: counter },
            }
        } else {
            Entry {
                dbscheme_name: "reserved_word".to_owned(),
                ql_class_name: "ReservedWord".to_owned(),
                kind: EntryKind::Token { kind_id: 0 },
            }
        };
        entries.insert(type_name, entry);
    }
    entries
}

fn add_field(
    parent_type_name: &TypeName,
    field_name: Option<String>,
    field_info: &FieldInfo,
    fields: &mut Vec<Field>,
    token_kinds: &Set<TypeName>,
) {
    let parent_flattened_name = node_type_name(&parent_type_name.kind, parent_type_name.named);
    let storage = if !field_info.multiple && field_info.required {
        // This field must appear exactly once, so we add it as
        // a column to the main table for the node type.
        Storage::Column {
            name: escape_name(&name_for_field_or_child(&field_name)),
        }
    } else {
        // Put the field in an auxiliary table.
        let has_index = field_info.multiple;
        let field_table_name = escape_name(&format!(
            "{}_{}",
            parent_flattened_name,
            &name_for_field_or_child(&field_name)
        ));
        Storage::Table {
            has_index,
            name: field_table_name,
        }
    };
    let converted_types = convert_types(&field_info.types);
    let type_info = if field_info
        .types
        .iter()
        .all(|t| !t.named && token_kinds.contains(&convert_type(t)))
    {
        // All possible types for this field are reserved words. The db
        // representation will be an `int` with a `case @foo.field = ...` to
        // enumerate the possible values.
        let mut counter = 0;
        let mut field_token_ints: BTreeMap<String, (usize, String)> = BTreeMap::new();
        for t in converted_types {
            let dbscheme_variant_name =
                escape_name(&format!("{}_{}", parent_flattened_name, t.kind));
            field_token_ints.insert(t.kind.to_owned(), (counter, dbscheme_variant_name));
            counter += 1;
        }
        FieldTypeInfo::ReservedWordInt(field_token_ints)
    } else if field_info.types.len() == 1 {
        FieldTypeInfo::Single(converted_types.into_iter().next().unwrap())
    } else {
        // The dbscheme type for this field will be a union. In QL, it'll just be AstNode.
        FieldTypeInfo::Multiple {
            types: converted_types,
            dbscheme_union: format!(
                "{}_{}_type",
                &parent_flattened_name,
                &name_for_field_or_child(&field_name)
            ),
            ql_class: "AstNode".to_owned(),
        }
    };
    let getter_name = format!(
        "get{}",
        dbscheme_name_to_class_name(&escape_name(&name_for_field_or_child(&field_name)))
    );
    fields.push(Field {
        parent: TypeName {
            kind: parent_type_name.kind.to_string(),
            named: parent_type_name.named,
        },
        type_info,
        name: field_name.map(|name| escape_name(&name)),
        getter_name,
        storage,
    });
}
#[derive(Deserialize)]
pub struct NodeInfo {
    #[serde(rename = "type")]
    pub kind: String,
    pub named: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub fields: Option<BTreeMap<String, FieldInfo>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub children: Option<FieldInfo>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subtypes: Option<Vec<NodeType>>,
}

#[derive(Deserialize)]
pub struct NodeType {
    #[serde(rename = "type")]
    pub kind: String,
    pub named: bool,
}

#[derive(Deserialize)]
pub struct FieldInfo {
    pub multiple: bool,
    pub required: bool,
    pub types: Vec<NodeType>,
}

/// Given a tree-sitter node type's (kind, named) pair, returns a single string
/// representing the (unescaped) name we'll use to refer to corresponding QL
/// type.
fn node_type_name(kind: &str, named: bool) -> String {
    if named {
        kind.to_string()
    } else {
        format!("{}_unnamed", kind)
    }
}

const RESERVED_KEYWORDS: [&'static str; 14] = [
    "boolean", "case", "date", "float", "int", "key", "of", "order", "ref", "string", "subtype",
    "type", "unique", "varchar",
];

/// Returns a string that's a copy of `name` but suitably escaped to be a valid
/// QL identifier.
fn escape_name(name: &str) -> String {
    let mut result = String::new();

    // If there's a leading underscore, replace it with 'underscore_'.
    if let Some(c) = name.chars().next() {
        if c == '_' {
            result.push_str("underscore");
        }
    }
    for c in name.chars() {
        match c {
            '{' => result.push_str("lbrace"),
            '}' => result.push_str("rbrace"),
            '<' => result.push_str("langle"),
            '>' => result.push_str("rangle"),
            '[' => result.push_str("lbracket"),
            ']' => result.push_str("rbracket"),
            '(' => result.push_str("lparen"),
            ')' => result.push_str("rparen"),
            '|' => result.push_str("pipe"),
            '=' => result.push_str("equal"),
            '~' => result.push_str("tilde"),
            '?' => result.push_str("question"),
            '`' => result.push_str("backtick"),
            '^' => result.push_str("caret"),
            '!' => result.push_str("bang"),
            '#' => result.push_str("hash"),
            '%' => result.push_str("percent"),
            '&' => result.push_str("ampersand"),
            '.' => result.push_str("dot"),
            ',' => result.push_str("comma"),
            '/' => result.push_str("slash"),
            ':' => result.push_str("colon"),
            ';' => result.push_str("semicolon"),
            '"' => result.push_str("dquote"),
            '*' => result.push_str("star"),
            '+' => result.push_str("plus"),
            '-' => result.push_str("minus"),
            '@' => result.push_str("at"),
            _ if c.is_uppercase() => {
                result.push('_');
                result.push_str(&c.to_lowercase().to_string())
            }
            _ => result.push(c),
        }
    }

    for &keyword in &RESERVED_KEYWORDS {
        if result == keyword {
            result.push_str("__");
            break;
        }
    }

    result
}

/// Given a valid dbscheme name (i.e. in snake case), produces the equivalent QL
/// name (i.e. in CamelCase). For example, "foo_bar_baz" becomes "FooBarBaz".
fn dbscheme_name_to_class_name(dbscheme_name: &str) -> String {
    fn to_title_case(word: &str) -> String {
        let mut first = true;
        let mut result = String::new();
        for c in word.chars() {
            if first {
                first = false;
                result.push(c.to_ascii_uppercase());
            } else {
                result.push(c);
            }
        }
        result
    }
    dbscheme_name
        .split('_')
        .map(|word| to_title_case(word))
        .collect::<Vec<String>>()
        .join("")
}
<commit_msg>Undo field name escaping<commit_after>use serde::Deserialize;
use std::collections::BTreeMap;
use std::path::Path;

use std::collections::BTreeSet as Set;
use std::fs;

/// A lookup table from TypeName to Entry.
pub type NodeTypeMap = BTreeMap<TypeName, Entry>;

#[derive(Debug)]
pub struct Entry {
    pub dbscheme_name: String,
    pub ql_class_name: String,
    pub kind: EntryKind,
}

#[derive(Debug)]
pub enum EntryKind {
    Union { members: Set<TypeName> },
    Table { name: String, fields: Vec<Field> },
    Token { kind_id: usize },
}

#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
pub struct TypeName {
    pub kind: String,
    pub named: bool,
}

#[derive(Debug)]
pub enum FieldTypeInfo {
    /// The field has a single type.
    Single(TypeName),

    /// The field can take one of several types, so we also provide the name of
    /// the database union type that wraps them, and the corresponding QL class
    /// name.
    Multiple {
        types: Set<TypeName>,
        dbscheme_union: String,
        ql_class: String,
    },

    /// The field can be one of several tokens, so the db type will be an `int`
    /// with a `case @foo.kind` for each possiblity.
    ReservedWordInt(BTreeMap<String, (usize, String)>),
}

#[derive(Debug)]
pub struct Field {
    pub parent: TypeName,
    pub type_info: FieldTypeInfo,
    /// The name of the field or None for the anonymous 'children'
    /// entry from node_types.json
    pub name: Option<String>,
    /// The name of the predicate to get this field.
    pub getter_name: String,
    pub storage: Storage,
}

fn name_for_field_or_child(name: &Option<String>) -> String {
    match name {
        Some(name) => name.clone(),
        None => "child".to_owned(),
    }
}

#[derive(Debug)]
pub enum Storage {
    /// the field is stored as a column in the parent table
    Column { name: String },
    /// the field is stored in a link table, and may or may not have an
    /// associated index column
    Table { name: String, has_index: bool },
}

pub fn read_node_types(node_types_path: &Path) -> std::io::Result<NodeTypeMap> {
    let file = fs::File::open(node_types_path)?;
    let node_types = serde_json::from_reader(file)?;
    Ok(convert_nodes(&node_types))
}

pub fn read_node_types_str(node_types_json: &str) -> std::io::Result<NodeTypeMap> {
    let node_types = serde_json::from_str(node_types_json)?;
    Ok(convert_nodes(&node_types))
}

fn convert_type(node_type: &NodeType) -> TypeName {
    TypeName {
        kind: node_type.kind.to_string(),
        named: node_type.named,
    }
}

fn convert_types(node_types: &Vec<NodeType>) -> Set<TypeName> {
    let iter = node_types.iter().map(convert_type).collect();
    std::collections::BTreeSet::from(iter)
}

pub fn convert_nodes(nodes: &Vec<NodeInfo>) -> NodeTypeMap {
    let mut entries = NodeTypeMap::new();
    let mut token_kinds = Set::new();

    // First, find all the token kinds
    for node in nodes {
        if node.subtypes.is_none() {
            if node.fields.as_ref().map_or(0, |x| x.len()) == 0 && node.children.is_none() {
                let type_name = TypeName {
                    kind: node.kind.clone(),
                    named: node.named,
                };
                token_kinds.insert(type_name);
            }
        }
    }

    for node in nodes {
        let flattened_name = &node_type_name(&node.kind, node.named);
        let dbscheme_name = escape_name(&flattened_name);
        let ql_class_name = dbscheme_name_to_class_name(&dbscheme_name);
        if let Some(subtypes) = &node.subtypes {
            // It's a tree-sitter supertype node, for which we create a union
            // type.
            entries.insert(
                TypeName {
                    kind: node.kind.clone(),
                    named: node.named,
                },
                Entry {
                    dbscheme_name,
                    ql_class_name,
                    kind: EntryKind::Union {
                        members: convert_types(&subtypes),
                    },
                },
            );
        } else if node.fields.as_ref().map_or(0, |x| x.len()) == 0 && node.children.is_none() {
            // Token kind, handled above.
        } else {
            // It's a product type, defined by a table.
            let type_name = TypeName {
                kind: node.kind.clone(),
                named: node.named,
            };
            let table_name = escape_name(&(format!("{}_def", &flattened_name)));
            let mut fields = Vec::new();

            // If the type also has fields or children, then we create either
            // auxiliary tables or columns in the defining table for them.
            if let Some(node_fields) = &node.fields {
                for (field_name, field_info) in node_fields {
                    add_field(
                        &type_name,
                        Some(field_name.to_string()),
                        field_info,
                        &mut fields,
                        &token_kinds,
                    );
                }
            }
            if let Some(children) = &node.children {
                // Treat children as if they were a field called 'child'.
                add_field(&type_name, None, children, &mut fields, &token_kinds);
            }
            entries.insert(
                type_name,
                Entry {
                    dbscheme_name,
                    ql_class_name,
                    kind: EntryKind::Table {
                        name: table_name,
                        fields,
                    },
                },
            );
        }
    }
    let mut counter = 0;
    for type_name in token_kinds {
        let entry = if type_name.named {
            counter += 1;
            let unprefixed_name = node_type_name(&type_name.kind, true);
            Entry {
                dbscheme_name: escape_name(&format!("token_{}", &unprefixed_name)),
                ql_class_name: dbscheme_name_to_class_name(&escape_name(&unprefixed_name)),
                kind: EntryKind::Token { kind_id: counter },
            }
        } else {
            Entry {
                dbscheme_name: "reserved_word".to_owned(),
                ql_class_name: "ReservedWord".to_owned(),
                kind: EntryKind::Token { kind_id: 0 },
            }
        };
        entries.insert(type_name, entry);
    }
    entries
}

fn add_field(
    parent_type_name: &TypeName,
    field_name: Option<String>,
    field_info: &FieldInfo,
    fields: &mut Vec<Field>,
    token_kinds: &Set<TypeName>,
) {
    let parent_flattened_name = node_type_name(&parent_type_name.kind, parent_type_name.named);
    let storage = if !field_info.multiple && field_info.required {
        // This field must appear exactly once, so we add it as
        // a column to the main table for the node type.
        Storage::Column {
            name: escape_name(&name_for_field_or_child(&field_name)),
        }
    } else {
        // Put the field in an auxiliary table.
        let has_index = field_info.multiple;
        let field_table_name = escape_name(&format!(
            "{}_{}",
            parent_flattened_name,
            &name_for_field_or_child(&field_name)
        ));
        Storage::Table {
            has_index,
            name: field_table_name,
        }
    };
    let converted_types = convert_types(&field_info.types);
    let type_info = if field_info
        .types
        .iter()
        .all(|t| !t.named && token_kinds.contains(&convert_type(t)))
    {
        // All possible types for this field are reserved words. The db
        // representation will be an `int` with a `case @foo.field = ...` to
        // enumerate the possible values.
        let mut counter = 0;
        let mut field_token_ints: BTreeMap<String, (usize, String)> = BTreeMap::new();
        for t in converted_types {
            let dbscheme_variant_name =
                escape_name(&format!("{}_{}", parent_flattened_name, t.kind));
            field_token_ints.insert(t.kind.to_owned(), (counter, dbscheme_variant_name));
            counter += 1;
        }
        FieldTypeInfo::ReservedWordInt(field_token_ints)
    } else if field_info.types.len() == 1 {
        FieldTypeInfo::Single(converted_types.into_iter().next().unwrap())
    } else {
        // The dbscheme type for this field will be a union. In QL, it'll just be AstNode.
        FieldTypeInfo::Multiple {
            types: converted_types,
            dbscheme_union: format!(
                "{}_{}_type",
                &parent_flattened_name,
                &name_for_field_or_child(&field_name)
            ),
            ql_class: "AstNode".to_owned(),
        }
    };
    let getter_name = format!(
        "get{}",
        dbscheme_name_to_class_name(&escape_name(&name_for_field_or_child(&field_name)))
    );
    fields.push(Field {
        parent: TypeName {
            kind: parent_type_name.kind.to_string(),
            named: parent_type_name.named,
        },
        type_info,
        name: field_name,
        getter_name,
        storage,
    });
}
#[derive(Deserialize)]
pub struct NodeInfo {
    #[serde(rename = "type")]
    pub kind: String,
    pub named: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub fields: Option<BTreeMap<String, FieldInfo>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub children: Option<FieldInfo>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subtypes: Option<Vec<NodeType>>,
}

#[derive(Deserialize)]
pub struct NodeType {
    #[serde(rename = "type")]
    pub kind: String,
    pub named: bool,
}

#[derive(Deserialize)]
pub struct FieldInfo {
    pub multiple: bool,
    pub required: bool,
    pub types: Vec<NodeType>,
}

/// Given a tree-sitter node type's (kind, named) pair, returns a single string
/// representing the (unescaped) name we'll use to refer to corresponding QL
/// type.
fn node_type_name(kind: &str, named: bool) -> String {
    if named {
        kind.to_string()
    } else {
        format!("{}_unnamed", kind)
    }
}

const RESERVED_KEYWORDS: [&'static str; 14] = [
    "boolean", "case", "date", "float", "int", "key", "of", "order", "ref", "string", "subtype",
    "type", "unique", "varchar",
];

/// Returns a string that's a copy of `name` but suitably escaped to be a valid
/// QL identifier.
fn escape_name(name: &str) -> String {
    let mut result = String::new();

    // If there's a leading underscore, replace it with 'underscore_'.
    if let Some(c) = name.chars().next() {
        if c == '_' {
            result.push_str("underscore");
        }
    }
    for c in name.chars() {
        match c {
            '{' => result.push_str("lbrace"),
            '}' => result.push_str("rbrace"),
            '<' => result.push_str("langle"),
            '>' => result.push_str("rangle"),
            '[' => result.push_str("lbracket"),
            ']' => result.push_str("rbracket"),
            '(' => result.push_str("lparen"),
            ')' => result.push_str("rparen"),
            '|' => result.push_str("pipe"),
            '=' => result.push_str("equal"),
            '~' => result.push_str("tilde"),
            '?' => result.push_str("question"),
            '`' => result.push_str("backtick"),
            '^' => result.push_str("caret"),
            '!' => result.push_str("bang"),
            '#' => result.push_str("hash"),
            '%' => result.push_str("percent"),
            '&' => result.push_str("ampersand"),
            '.' => result.push_str("dot"),
            ',' => result.push_str("comma"),
            '/' => result.push_str("slash"),
            ':' => result.push_str("colon"),
            ';' => result.push_str("semicolon"),
            '"' => result.push_str("dquote"),
            '*' => result.push_str("star"),
            '+' => result.push_str("plus"),
            '-' => result.push_str("minus"),
            '@' => result.push_str("at"),
            _ if c.is_uppercase() => {
                result.push('_');
                result.push_str(&c.to_lowercase().to_string())
            }
            _ => result.push(c),
        }
    }

    for &keyword in &RESERVED_KEYWORDS {
        if result == keyword {
            result.push_str("__");
            break;
        }
    }

    result
}

/// Given a valid dbscheme name (i.e. in snake case), produces the equivalent QL
/// name (i.e. in CamelCase). For example, "foo_bar_baz" becomes "FooBarBaz".
fn dbscheme_name_to_class_name(dbscheme_name: &str) -> String {
    fn to_title_case(word: &str) -> String {
        let mut first = true;
        let mut result = String::new();
        for c in word.chars() {
            if first {
                first = false;
                result.push(c.to_ascii_uppercase());
            } else {
                result.push(c);
            }
        }
        result
    }
    dbscheme_name
        .split('_')
        .map(|word| to_title_case(word))
        .collect::<Vec<String>>()
        .join("")
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! GPU-visible memory allocation.
use std::mem;
use std::os::raw::c_void;
use std::slice;

use vk;

pub use self::device_memory::CpuAccess;
pub use self::device_memory::DeviceMemory;
pub use self::device_memory::MappedDeviceMemory;

mod device_memory;

#[derive(Debug, Copy, Clone)]
pub struct MemoryRequirements {
    pub size: usize,
    pub alignment: usize,
    pub memory_type_bits: u32,
}

#[doc(hidden)]
impl From<vk::MemoryRequirements> for MemoryRequirements {
    #[inline]
    fn from(reqs: vk::MemoryRequirements) -> MemoryRequirements {
        MemoryRequirements {
            size: reqs.size as usize,
            alignment: reqs.alignment as usize,
            memory_type_bits: reqs.memoryTypeBits,
        }
    }
}

/// Trait for types of data that can be mapped.
// TODO: move to `buffer` module
pub unsafe trait Content {
    /// Builds a pointer to this type from a raw pointer.
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut Self>;

    /// Returns true if the size is suitable to store a type like this.
    fn is_size_suitable(usize) -> bool;

    /// Returns the size of an individual element.
    fn indiv_size() -> usize;
}

unsafe impl<T> Content for T {
    #[inline]
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut T> {
        if size < mem::size_of::<T>() {
            return None;
        }

        Some(ptr as *mut T)
    }

    #[inline]
    fn is_size_suitable(size: usize) -> bool {
        size == mem::size_of::<T>()
    }

    #[inline]
    fn indiv_size() -> usize {
        mem::size_of::<T>()
    }
}

unsafe impl<T> Content for [T] {
    #[inline]
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut [T]> {
        let ptr = ptr as *mut T;
        let size = size / mem::size_of::<T>();
        Some(unsafe { slice::from_raw_parts_mut(&mut *ptr, size) as *mut [T] })
    }

    #[inline]
    fn is_size_suitable(size: usize) -> bool {
        size % mem::size_of::<T>() == 0
    }

    #[inline]
    fn indiv_size() -> usize {
        mem::size_of::<T>()
    }
}

/*
TODO: do this when it's possible
unsafe impl Content for .. {}
impl<'a, T> !Content for &'a T {}
impl<'a, T> !Content for &'a mut T {}
impl<T> !Content for *const T {}
impl<T> !Content for *mut T {}
impl<T> !Content for Box<T> {}
impl<T> !Content for UnsafeCell<T> {}

*/
<commit_msg>Minor documentation fixes for memory module<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! GPU-visible memory allocation.

use std::mem;
use std::os::raw::c_void;
use std::slice;

use vk;

pub use self::device_memory::CpuAccess;
pub use self::device_memory::DeviceMemory;
pub use self::device_memory::MappedDeviceMemory;

mod device_memory;

/// Represents requirements expressed by the Vulkan implementation.
#[derive(Debug, Copy, Clone)]
pub struct MemoryRequirements {
    /// Number of bytes of memory required.
    pub size: usize,

    /// Alignment of the requirement buffer. The base memory address must be a multiple
    /// of this value.
    pub alignment: usize,

    /// Indicates which memory types can be used. Each bit that is set to 1 means that the memory
    /// type whose index is the same as the position of the bit can be used.
    pub memory_type_bits: u32,
}

#[doc(hidden)]
impl From<vk::MemoryRequirements> for MemoryRequirements {
    #[inline]
    fn from(reqs: vk::MemoryRequirements) -> MemoryRequirements {
        MemoryRequirements {
            size: reqs.size as usize,
            alignment: reqs.alignment as usize,
            memory_type_bits: reqs.memoryTypeBits,
        }
    }
}

/// Trait for types of data that can be mapped.
// TODO: move to `buffer` module
pub unsafe trait Content {
    /// Builds a pointer to this type from a raw pointer.
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut Self>;

    /// Returns true if the size is suitable to store a type like this.
    fn is_size_suitable(usize) -> bool;

    /// Returns the size of an individual element.
    fn indiv_size() -> usize;
}

unsafe impl<T> Content for T {
    #[inline]
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut T> {
        if size < mem::size_of::<T>() {
            return None;
        }

        Some(ptr as *mut T)
    }

    #[inline]
    fn is_size_suitable(size: usize) -> bool {
        size == mem::size_of::<T>()
    }

    #[inline]
    fn indiv_size() -> usize {
        mem::size_of::<T>()
    }
}

unsafe impl<T> Content for [T] {
    #[inline]
    fn ref_from_ptr<'a>(ptr: *mut c_void, size: usize) -> Option<*mut [T]> {
        let ptr = ptr as *mut T;
        let size = size / mem::size_of::<T>();
        Some(unsafe { slice::from_raw_parts_mut(&mut *ptr, size) as *mut [T] })
    }

    #[inline]
    fn is_size_suitable(size: usize) -> bool {
        size % mem::size_of::<T>() == 0
    }

    #[inline]
    fn indiv_size() -> usize {
        mem::size_of::<T>()
    }
}

/*
TODO: do this when it's possible
unsafe impl Content for .. {}
impl<'a, T> !Content for &'a T {}
impl<'a, T> !Content for &'a mut T {}
impl<T> !Content for *const T {}
impl<T> !Content for *mut T {}
impl<T> !Content for Box<T> {}
impl<T> !Content for UnsafeCell<T> {}

*/
<|endoftext|>