<commit_before>use crate::convert::*;
use core::hash::{Hasher};

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
/// Instances of [`AHasher`] represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// [Clone] is also provided in case you wish to calculate hashes for two different items that
/// start with the same data.
///
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: [u64; 2],
    key: [u64; 2],
}

impl AHasher {
    /// Creates a new hasher keyed to the provided keys.
    /// # Example
    ///
    /// ```
    /// use std::hash::Hasher;
    /// use ahash::AHasher;
    ///
    /// let mut hasher = AHasher::new_with_keys(123, 456);
    ///
    /// hasher.write_u32(1989);
    /// hasher.write_u8(11);
    /// hasher.write_u8(9);
    /// hasher.write(b"Huh?");
    ///
    /// println!("Hash is {:x}!", hasher.finish());
    /// ```
    #[inline]
    pub fn new_with_keys(key0: u64, key1: u64) -> Self {
        Self { buffer: [key0, key1], key: [key1, key0]  }
    }

    #[cfg(test)]
    pub(crate) fn test_with_keys(key1: u64, key2: u64) -> AHasher {
        use crate::scramble_keys;
        let (k1, k2) = scramble_keys(key1, key2);
        AHasher { buffer: [k1, k2], key: [k2, k1] }
    }
}

#[inline(never)]
#[no_mangle]
fn hash_test_aes(input: &[u8]) -> u64 {
    let mut a = AHasher::new_with_keys(67, 87);
    a.write(input);
    a.finish()
}

/// Provides methods to hash all of the primitive types.
impl Hasher for AHasher {
    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.write_u128(i as u128);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.write_u128(i as u128);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.write_u128(i as u128);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        self.buffer = aeshash(self.buffer.convert(), i).convert();
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.write_u128(i as u128);
    }

    #[inline]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        //This will be scrambled by the first AES round in any branch.
        self.buffer[1] = self.buffer[1].wrapping_add(length);
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() <= 8 {
            if data.len() >= 2 {
                if data.len() >= 4 {
                    //len 4-8
                    self.buffer = aeshash(self.buffer.convert(), data.read_u32().0 as u128).convert();
                    self.buffer = aeshash(self.buffer.convert(), data.read_last_u32() as u128).convert();
                } else {
                    //len 2-3
                    self.buffer = aeshash(self.buffer.convert(), data.read_u16().0 as u128).convert();
                    self.buffer = aeshash(self.buffer.convert(), data[data.len() - 1] as u128).convert();
                }
            } else {
                let value;
                if data.len() > 0 {
                    value = data[0]; //len 1
                } else {
                    value = 0;
                }
                self.buffer = aeshash(self.buffer.convert(), value as u128).convert();
            }
        } else {
            if data.len() > 32 {
                if data.len() > 64 {
                    let (_, tail) = data.split_at(data.len() - 32);
                    let mut par_block: u128 = self.buffer.convert();
                    while data.len() > 32 {
                        let (b1, rest) = data.read_u128();
                        self.buffer = aeshash(self.buffer.convert(), b1).convert();
                        data = rest;
                        let (b2, rest) = data.read_u128();
                        par_block = aeshash(par_block, b2);
                        data = rest;
                    }
                    let (b1, rest) = tail.read_u128();
                    self.buffer = aeshash(self.buffer.convert(), b1).convert();
                    let (b2, _) = rest.read_u128();
                    par_block = aeshash(par_block, b2);
                    self.buffer = aeshash(self.buffer.convert(), par_block).convert();
                } else {
                    //len 33-64
                    let (head, _) = data.split_at(32);
                    let (_, tail) = data.split_at(data.len() - 32);
                    self.buffer = aeshash(self.buffer.convert(), head.read_u128().0).convert();
                    self.buffer = aeshash(self.buffer.convert(), head.read_last_u128()).convert();
                    self.buffer = aeshash(self.buffer.convert(), tail.read_u128().0).convert();
                    self.buffer = aeshash(self.buffer.convert(), tail.read_last_u128()).convert();
                }
            } else {
                if data.len() > 16 {
                    //len 17-32
                    self.buffer = aeshash(self.buffer.convert(), data.read_u128().0).convert();
                    self.buffer = aeshash(self.buffer.convert(), data.read_last_u128()).convert();
                } else {
                    //len 9-16
                    self.buffer = aeshash(self.buffer.convert(), data.read_u64().0 as u128).convert();
                    self.buffer = aeshash(self.buffer.convert(), data.read_last_u64() as u128).convert();
                }
            }
        }
    }
    #[inline]
    fn finish(&self) -> u64 {
        let result: [u64; 2] = aeshash(aeshash(self.buffer.convert(), self.key.convert()), self.key.convert()).convert();
        result[0] //.wrapping_add(result[1])
    }
}

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
#[inline(always)]
fn aeshash(value: u128, xor: u128) -> u128 {
    #[cfg(target_arch = "x86")]
    use core::arch::x86::*;
    #[cfg(target_arch = "x86_64")]
    use core::arch::x86_64::*;
    use core::mem::transmute;
    unsafe {
        let value = transmute(value);
        transmute(_mm_aesdec_si128(value, transmute(xor)))
    }
}

#[cfg(test)]
mod tests {
    use crate::aes_hash::*;
    use crate::convert::Convert;
    use std::collections::HashMap;
    use std::hash::BuildHasherDefault;

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_default() {
        let hasher_a = AHasher::default();
        assert_ne!(0, hasher_a.buffer[0]);
        assert_ne!(0, hasher_a.buffer[1]);
        assert_ne!(hasher_a.buffer[0], hasher_a.buffer[1]);
        let hasher_b = AHasher::default();
        assert_eq!(hasher_a.buffer[0], hasher_b.buffer[0]);
        assert_eq!(hasher_a.buffer[1], hasher_b.buffer[1]);
    }

    #[test]
    fn test_hash() {
        let mut result: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value: [u64; 2] = [1 << 32, 0xFEDCBA9876543210];
        result = aeshash(value.convert(), result.convert()).convert();
        result = aeshash(result.convert(), result.convert()).convert();
        let mut result2: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value2: [u64; 2] = [1, 0xFEDCBA9876543210];
        result2 = aeshash(value2.convert(), result2.convert()).convert();
        result2 = aeshash(result2.convert(), result.convert()).convert();
        let result: [u8; 16] = result.convert();
        let result2: [u8; 16] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}
<commit_msg>Add second AES round between updates to strengthen against certain differential attacks where an attacker can observer the full output hash.<commit_after>use crate::convert::*;
use core::hash::{Hasher};

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
/// Instances of [`AHasher`] represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// [Clone] is also provided in case you wish to calculate hashes for two different items that
/// start with the same data.
///
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: [u64; 2],
    key: [u64; 2],
}

impl AHasher {
    /// Creates a new hasher keyed to the provided keys.
    /// # Example
    ///
    /// ```
    /// use std::hash::Hasher;
    /// use ahash::AHasher;
    ///
    /// let mut hasher = AHasher::new_with_keys(123, 456);
    ///
    /// hasher.write_u32(1989);
    /// hasher.write_u8(11);
    /// hasher.write_u8(9);
    /// hasher.write(b"Huh?");
    ///
    /// println!("Hash is {:x}!", hasher.finish());
    /// ```
    #[inline]
    pub fn new_with_keys(key0: u64, key1: u64) -> Self {
        Self { buffer: [key0, key1], key: [key1, key0]  }
    }

    #[cfg(test)]
    pub(crate) fn test_with_keys(key1: u64, key2: u64) -> AHasher {
        use crate::scramble_keys;
        let (k1, k2) = scramble_keys(key1, key2);
        AHasher { buffer: [k1, k2], key: [k2, k1] }
    }
}

#[inline(never)]
#[no_mangle]
fn hash_test_aes(input: &[u8]) -> u64 {
    let mut a = AHasher::new_with_keys(67, 87);
    a.write(input);
    a.finish()
}

/// Provides methods to hash all of the primitive types.
impl Hasher for AHasher {
    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.write_u128(i as u128);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.write_u128(i as u128);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.write_u128(i as u128);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        self.buffer = aeshashx2(self.buffer.convert(), i, self.key.convert()).convert();
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.write_u128(i as u128);
    }

    #[inline]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        //This will be scrambled by the first AES round in any branch.
        self.buffer[1] = self.buffer[1].wrapping_add(length);
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() <= 8 {
            if data.len() >= 2 {
                if data.len() >= 4 {
                    //len 4-8
                    self.buffer = aeshash(self.buffer.convert(), data.read_u32().0 as u128).convert();
                    self.buffer = aeshash(self.buffer.convert(), data.read_last_u32() as u128).convert();
                } else {
                    //len 2-3
                    self.buffer = aeshash(self.buffer.convert(), data.read_u16().0 as u128).convert();
                    self.buffer = aeshash(self.buffer.convert(), data[data.len() - 1] as u128).convert();
                }
            } else {
                let value;
                if data.len() > 0 {
                    value = data[0]; //len 1
                } else {
                    value = 0;
                }
                self.buffer = aeshash(self.buffer.convert(), value as u128).convert();
            }
            self.buffer = aeshash(self.buffer.convert(), self.key.convert()).convert();
        } else {
            if data.len() > 32 {
                if data.len() > 64 {
                    let (_, tail) = data.split_at(data.len() - 32);
                    let mut par_block: u128 = self.buffer.convert();
                    while data.len() > 32 {
                        let (b1, rest) = data.read_u128();
                        self.buffer = aeshashx2(self.buffer.convert(), b1, self.key.convert()).convert();
                        data = rest;
                        let (b2, rest) = data.read_u128();
                        par_block = aeshashx2(par_block, b2, self.key.convert());
                        data = rest;
                    }
                    let (b1, rest) = tail.read_u128();
                    self.buffer = aeshashx2(self.buffer.convert(), b1, self.key.convert()).convert();
                    let (b2, _) = rest.read_u128();
                    par_block = aeshashx2(par_block, b2, self.key.convert());
                    self.buffer = aeshashx2(self.buffer.convert(), par_block, self.key.convert()).convert();
                } else {
                    //len 33-64
                    let (head, _) = data.split_at(32);
                    let (_, tail) = data.split_at(data.len() - 32);
                    self.buffer = aeshashx2(self.buffer.convert(), head.read_u128().0, self.key.convert()).convert();
                    self.buffer = aeshashx2(self.buffer.convert(), head.read_last_u128(), self.key.convert()).convert();
                    self.buffer = aeshashx2(self.buffer.convert(), tail.read_u128().0, self.key.convert()).convert();
                    self.buffer = aeshashx2(self.buffer.convert(), tail.read_last_u128(), self.key.convert()).convert();
                }
            } else {
                if data.len() > 16 {
                    //len 17-32
                    self.buffer = aeshashx2(self.buffer.convert(), data.read_u128().0, self.key.convert()).convert();
                    self.buffer = aeshashx2(self.buffer.convert(), data.read_last_u128(), self.key.convert()).convert();
                } else {
                    //len 9-16
                    self.buffer = aeshash(self.buffer.convert(), data.read_u64().0 as u128).convert();
                    self.buffer = aeshashx2(self.buffer.convert(), data.read_last_u64() as u128, self.key.convert()).convert();
                }
            }
        }
    }
    #[inline]
    fn finish(&self) -> u64 {
        let result: [u64; 2] = aeshash(self.buffer.convert(), self.key.convert()).convert();
        result[0] //.wrapping_add(result[1])
    }
}

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
#[inline(always)]
fn aeshash(value: u128, xor: u128) -> u128 {
    #[cfg(target_arch = "x86")]
    use core::arch::x86::*;
    #[cfg(target_arch = "x86_64")]
    use core::arch::x86_64::*;
    use core::mem::transmute;
    unsafe {
        let value = transmute(value);
        transmute(_mm_aesdec_si128(value, transmute(xor)))
    }
}
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
#[inline(always)]
fn aeshashx2(value: u128, k1: u128, k2: u128) -> u128 {
    #[cfg(target_arch = "x86")]
    use core::arch::x86::*;
    #[cfg(target_arch = "x86_64")]
    use core::arch::x86_64::*;
    use core::mem::transmute;
    unsafe {
        let value = transmute(value);
        let value = _mm_aesdec_si128(value, transmute(k1));
        transmute(_mm_aesdec_si128(value, transmute(k2)))
    }
}

#[cfg(test)]
mod tests {
    use crate::aes_hash::*;
    use crate::convert::Convert;
    use std::collections::HashMap;
    use std::hash::BuildHasherDefault;

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_default() {
        let hasher_a = AHasher::default();
        assert_ne!(0, hasher_a.buffer[0]);
        assert_ne!(0, hasher_a.buffer[1]);
        assert_ne!(hasher_a.buffer[0], hasher_a.buffer[1]);
        let hasher_b = AHasher::default();
        assert_eq!(hasher_a.buffer[0], hasher_b.buffer[0]);
        assert_eq!(hasher_a.buffer[1], hasher_b.buffer[1]);
    }

    #[test]
    fn test_hash() {
        let mut result: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value: [u64; 2] = [1 << 32, 0xFEDCBA9876543210];
        result = aeshash(value.convert(), result.convert()).convert();
        result = aeshash(result.convert(), result.convert()).convert();
        let mut result2: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value2: [u64; 2] = [1, 0xFEDCBA9876543210];
        result2 = aeshash(value2.convert(), result2.convert()).convert();
        result2 = aeshash(result2.convert(), result.convert()).convert();
        let result: [u8; 16] = result.convert();
        let result2: [u8; 16] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}
<|endoftext|>


<commit_before>
extern crate mprovision;
#[macro_use(version)]
extern crate version;
extern crate chrono;
#[cfg(test)]
#[macro_use(expect)]
extern crate expectest;
extern crate clap;

use mprovision as mp;
use cli::Command;
use std::env;
use std::path::PathBuf;
use chrono::*;

mod cli;

fn main() {
    let result = cli::parse(env::args()).and_then(|command| {
        match command {
            Command::List(cli::ListParams { filter, expire_in_days, directory }) => {
                list(filter, expire_in_days, directory)
            }
            Command::ShowUuid(uuid, directory) => show_uuid(uuid, directory),
            Command::ShowFile(path) => show_file(path),
            Command::Remove(uuid, directory) => remove(uuid, directory),
            Command::Clean(directory) => clean(directory),
        }
    });
    if let Err(e) = result {
        e.exit();
    }
}

fn list(filter: Option<String>,
        expires_in_days: Option<i64>,
        directory: Option<PathBuf>)
        -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| {
            let total = entries.len();
            let date = expires_in_days.map(|days| UTC::now() + Duration::days(days));
            let filter_string = filter.as_ref();
            let profiles = mp::filter(entries, |profile| {
                match (date, filter_string) {
                    (Some(date), Some(string)) => {
                        profile.expiration_date <= date && profile.contains(&string)
                    }
                    (Some(date), _) => profile.expiration_date <= date,
                    (_, Some(string)) => profile.contains(&string),
                    (_, _) => true,
                }
            });
            (total, profiles)
        })
        .and_then(|(total, profiles)| {
            if profiles.is_empty() {
                Ok(println!("Nothing found"))
            } else {
                for profile in &profiles {
                    println!("\n{}", profile.description());
                }
                Ok(println!("\nFound {} of {}", profiles.len(), total))
            }
        })
}

fn show_uuid(uuid: String, directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_uuid(&directory, &uuid)
                .and_then(|profile| mp::show(&profile.path).map(|xml| println!("{}", xml)))
        })
        .map_err(|err| err.into())
}

fn show_file(path: PathBuf) -> Result<(), cli::Error> {
    mp::show(&path)
        .map(|xml| println!("{}", xml))
        .map_err(|err| err.into())
}

fn remove(uuid: String, directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_uuid(&directory, &uuid)
                .and_then(|profile| mp::remove(&profile.path))
                .map(|_| println!("'{}' was removed", uuid))
        })
        .map_err(|err| err.into())
}

fn clean(directory: Option<PathBuf>) -> Result<(), cli::Error> {

    fn concat(mut s1: String, s2: String) -> String {
        s1.push_str(&s2);
        s1
    }

    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| {
            let date = UTC::now();
            mp::filter(entries, |profile| profile.expiration_date <= date)
        })
        .and_then(|profiles| {
            if profiles.is_empty() {
                Ok(println!("All provisioning profiles are valid"))
            } else {
                profiles.iter()
                    .map(|profile| {
                        std::fs::remove_file(&profile.path)
                            .map(|_| format!("'{}' was removed\n", profile.uuid))
                            .map_err(|err| format!("'{}' {}\n", profile.uuid, err))
                    })
                    .fold(Ok(String::new()), |acc, s| {
                        match (acc, s) {
                            (Ok(acc), Ok(s)) => Ok(concat(acc, s)),
                            (Err(acc), Ok(s)) => Err(concat(acc, s)),
                            (Err(acc), Err(s)) => Err(concat(acc, s)),
                            (Ok(acc), Err(s)) => Err(concat(acc, s)),
                        }
                    })
                    .map(|s| println!("{}", s))
                    .map_err(|err| cli::Error::Custom(err))
            }
        })
}
<commit_msg>Sort listed profiles by creation date<commit_after>
extern crate mprovision;
#[macro_use(version)]
extern crate version;
extern crate chrono;
#[cfg(test)]
#[macro_use(expect)]
extern crate expectest;
extern crate clap;

use mprovision as mp;
use cli::Command;
use std::env;
use std::path::PathBuf;
use chrono::*;

mod cli;

fn main() {
    let result = cli::parse(env::args()).and_then(|command| {
        match command {
            Command::List(cli::ListParams { filter, expire_in_days, directory }) => {
                list(filter, expire_in_days, directory)
            }
            Command::ShowUuid(uuid, directory) => show_uuid(uuid, directory),
            Command::ShowFile(path) => show_file(path),
            Command::Remove(uuid, directory) => remove(uuid, directory),
            Command::Clean(directory) => clean(directory),
        }
    });
    if let Err(e) = result {
        e.exit();
    }
}

fn list(filter: Option<String>,
        expires_in_days: Option<i64>,
        directory: Option<PathBuf>)
        -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| {
            let total = entries.len();
            let date = expires_in_days.map(|days| UTC::now() + Duration::days(days));
            let filter_string = filter.as_ref();
            let mut profiles = mp::filter(entries, |profile| {
                match (date, filter_string) {
                    (Some(date), Some(string)) => {
                        profile.expiration_date <= date && profile.contains(&string)
                    }
                    (Some(date), _) => profile.expiration_date <= date,
                    (_, Some(string)) => profile.contains(&string),
                    (_, _) => true,
                }
            });
            profiles.sort_by(|a, b| a.creation_date.cmp(&b.creation_date));
            (total, profiles)
        })
        .and_then(|(total, profiles)| {
            if profiles.is_empty() {
                Ok(println!("Nothing found"))
            } else {
                for profile in &profiles {
                    println!("\n{}", profile.description());
                }
                Ok(println!("\nFound {} of {}", profiles.len(), total))
            }
        })
}

fn show_uuid(uuid: String, directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_uuid(&directory, &uuid)
                .and_then(|profile| mp::show(&profile.path).map(|xml| println!("{}", xml)))
        })
        .map_err(|err| err.into())
}

fn show_file(path: PathBuf) -> Result<(), cli::Error> {
    mp::show(&path)
        .map(|xml| println!("{}", xml))
        .map_err(|err| err.into())
}

fn remove(uuid: String, directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_uuid(&directory, &uuid)
                .and_then(|profile| mp::remove(&profile.path))
                .map(|_| println!("'{}' was removed", uuid))
        })
        .map_err(|err| err.into())
}

fn clean(directory: Option<PathBuf>) -> Result<(), cli::Error> {

    fn concat(mut s1: String, s2: String) -> String {
        s1.push_str(&s2);
        s1
    }

    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| {
            let date = UTC::now();
            mp::filter(entries, |profile| profile.expiration_date <= date)
        })
        .and_then(|profiles| {
            if profiles.is_empty() {
                Ok(println!("All provisioning profiles are valid"))
            } else {
                profiles.iter()
                    .map(|profile| {
                        std::fs::remove_file(&profile.path)
                            .map(|_| format!("'{}' was removed\n", profile.uuid))
                            .map_err(|err| format!("'{}' {}\n", profile.uuid, err))
                    })
                    .fold(Ok(String::new()), |acc, s| {
                        match (acc, s) {
                            (Ok(acc), Ok(s)) => Ok(concat(acc, s)),
                            (Err(acc), Ok(s)) => Err(concat(acc, s)),
                            (Err(acc), Err(s)) => Err(concat(acc, s)),
                            (Ok(acc), Err(s)) => Err(concat(acc, s)),
                        }
                    })
                    .map(|s| println!("{}", s))
                    .map_err(|err| cli::Error::Custom(err))
            }
        })
}
<|endoftext|>


<commit_before>extern crate ilog2;
extern crate num;

use std::fmt::Binary;
use self::ilog2::Future;

pub trait Bitalloc {
    fn clear_all(&mut self);
    fn fill_all(&mut self);
    fn alloc(&mut self, size: usize) -> isize;
}

impl<T: ilog2::Bitops + Binary> Bitalloc for [T] {
    fn clear_all(&mut self) {
        for item in self.iter_mut() {
            *item = T::zero();
        }
    }
    fn fill_all(&mut self) {
        for item in self.iter_mut() {
            *item = ilog2::bit_mask::<T>();
        }
    }
    fn alloc(&mut self, size: usize) -> isize {
        let block_size = ilog2::bit_length::<T>() as usize;
        let block_count = size / block_size;
        let rem_count = size % block_size;

        let mut blocks_allocated = 0usize;
        let mut rem_allocated = 0usize;
        let mut blocks_needed = block_count;
        let mut rem_needed = rem_count;

        enum State {
            FindFirst,
            FindMid,
            FindLast,
        };

        let mut found_index = 0usize;
        let mut found_offset = 0usize;
        let mut found = false;
        let mut state = State::FindFirst;
        let mut index = 0usize;
        let limit = self.len();
        loop {
            if index == limit {
                break;
            }
            let val = self[index];

            match state {
                State::FindFirst => {
                    //reset
                    blocks_allocated = 0;
                    rem_allocated = 0;
                    blocks_needed = block_count;
                    rem_needed = rem_count;
                    found_index = 0;
                    found_offset = 0;

                    if size <= block_size { // allocated region may inside an integer
                        let mut possible = val;
                        let mut shifted = 0usize;
                        loop {
                            let current_available = possible.leading_zeros() as usize;
                            //println!("debug2 {} {} {} {:064b}", current_available, size, shifted, possible);
                            if current_available >= size {
                                found = true;
                                found_index = index;
                                found_offset = shifted;
                                break;
                            }
                            possible = possible << current_available; //discard current;
                            shifted += current_available;
                            //println!("debug3 {} {} {} {:064b}", current_available, size, shifted, possible);
                            let current_skip = possible.leading_ones() as usize;
                            shifted += current_skip;
                            if (shifted + size) > block_size {
                                break;
                            }
                            possible = possible << current_skip;
                            possible = possible | ilog2::bit_mask::<T>() >> (block_size - shifted);
                            //println!("debug4 {} {} {} {:064b}", current_available, size, shifted, possible);
                        }
                        if found {
                            break;
                        }
                    }
                    //size exceeded block size or failed to allocated inside a block
                    //find zeros from lsb position
                    let current_available = val.trailing_zeros() as usize;
                    if current_available > 0 {
                        //possible start location
                        found_index = index;
                        found_offset = block_size - current_available;
                        if current_available > rem_needed {
                            assert!(blocks_needed > 0);
                            rem_needed = rem_needed + block_size - current_available;
                            blocks_needed -= 1;
                        }
                        rem_allocated += current_available;
                        state = State::FindMid;
                    }
                },
                State::FindMid => {
                    if blocks_allocated == blocks_needed {
                        state = State::FindLast;
                        continue;
                    } else if val == T::zero() {
                        blocks_allocated += 1;
                    }
                },
                State::FindLast => {
                    let current_available = val.leading_zeros() as usize;
                    rem_allocated += current_available;
                    if rem_allocated >= rem_needed {
                        found = true;
                        break;
                    }
                    state = State::FindFirst;
                    continue;
                },
            }
            index += 1;
        }
        if found {
            let mut allocated = 0usize;
            let mut first_mask = ilog2::bit_mask::<T>();
            first_mask = first_mask >> found_offset;
            allocated += block_size - found_offset;
            if allocated > size {
                let diff = allocated - size;
                first_mask = first_mask >> diff;
                first_mask = first_mask << diff;
                allocated = size;
            }
            let mut update_index = found_index;
            assert!(self[update_index] & first_mask == T::zero());
            println!("Allocate first at block {} [{},{}] : {:064b}", update_index, found_index, found_offset, self[update_index]);
            self[update_index] = self[update_index] | first_mask;
            println!("Allocate first at block {} [{},{}] : {:064b}", update_index, found_index, found_offset, self[update_index]);
            update_index += 1;

            let rem = size - allocated;
            let fill = rem / block_size;
            let last_fill = rem % block_size;

            for i in 0 .. fill {
                println!("Allocate mid at block {} [{},{}] : {:064b}", update_index + i, found_index, found_offset, self[update_index + i]);
                let mid_mask = ilog2::bit_mask::<T>();
                assert!(self[update_index + i] & mid_mask == T::zero());
                self[update_index + i] = self[update_index + i] | mid_mask;
                allocated += block_size;
                println!("Allocate mid at block {} [{},{}] : {:064b}", update_index + i, found_index, found_offset, self[update_index + i]);
            }
            if last_fill > 0 {
                println!("Allocate last at block {} [{},{}] : {:064b}", update_index + fill, found_index, found_offset, self[update_index + fill]);
                let mut last_mask = ilog2::bit_mask::<T>();
                let diff = block_size - last_fill;
                last_mask = last_mask >> diff;
                last_mask = last_mask << diff;
                assert!(self[update_index + fill] & last_mask == T::zero());
                self[update_index + fill] = self[update_index + fill] | last_mask;
                allocated += last_fill;
                println!("Allocate last at block {} [{},{}] : {:064b}", update_index + fill, found_index, found_offset, self[update_index + fill]);
            }
            assert!(allocated == size);

            ((found_index * block_size) + found_offset) as isize
        } else {
            -1isize
        }
    }
}<commit_msg>Use bitalloc trait directly.<commit_after>extern crate ilog2;
extern crate num;

use std::fmt::Binary;
use self::ilog2::Bitops;

pub trait Bitalloc {
    fn clear_all(&mut self);
    fn fill_all(&mut self);
    fn alloc(&mut self, size: usize) -> isize;
}

impl<T: ilog2::Bitops + Binary> Bitalloc for [T] {
    fn clear_all(&mut self) {
        for item in self.iter_mut() {
            *item = T::zero();
        }
    }
    fn fill_all(&mut self) {
        for item in self.iter_mut() {
            *item = ilog2::bit_mask::<T>();
        }
    }
    fn alloc(&mut self, size: usize) -> isize {
        let block_size = ilog2::bit_length::<T>() as usize;
        let block_count = size / block_size;
        let rem_count = size % block_size;

        let mut blocks_allocated = 0usize;
        let mut rem_allocated = 0usize;
        let mut blocks_needed = block_count;
        let mut rem_needed = rem_count;

        enum State {
            FindFirst,
            FindMid,
            FindLast,
        };

        let mut found_index = 0usize;
        let mut found_offset = 0usize;
        let mut found = false;
        let mut state = State::FindFirst;
        let mut index = 0usize;
        let limit = self.len();
        loop {
            if index == limit {
                break;
            }
            let val = self[index];

            match state {
                State::FindFirst => {
                    //reset
                    blocks_allocated = 0;
                    rem_allocated = 0;
                    blocks_needed = block_count;
                    rem_needed = rem_count;
                    found_index = 0;
                    found_offset = 0;

                    if size <= block_size { // allocated region may inside an integer
                        let mut possible = val;
                        let mut shifted = 0usize;
                        loop {
                            let current_available = possible.leading_zeros() as usize;
                            //println!("debug2 {} {} {} {:064b}", current_available, size, shifted, possible);
                            if current_available >= size {
                                found = true;
                                found_index = index;
                                found_offset = shifted;
                                break;
                            }
                            possible = possible << current_available; //discard current;
                            shifted += current_available;
                            //println!("debug3 {} {} {} {:064b}", current_available, size, shifted, possible);
                            let current_skip = possible.leading_ones() as usize;
                            shifted += current_skip;
                            if (shifted + size) > block_size {
                                break;
                            }
                            possible = possible << current_skip;
                            possible = possible | ilog2::bit_mask::<T>() >> (block_size - shifted);
                            //println!("debug4 {} {} {} {:064b}", current_available, size, shifted, possible);
                        }
                        if found {
                            break;
                        }
                    }
                    //size exceeded block size or failed to allocated inside a block
                    //find zeros from lsb position
                    let current_available = val.trailing_zeros() as usize;
                    if current_available > 0 {
                        //possible start location
                        found_index = index;
                        found_offset = block_size - current_available;
                        if current_available > rem_needed {
                            assert!(blocks_needed > 0);
                            rem_needed = rem_needed + block_size - current_available;
                            blocks_needed -= 1;
                        }
                        rem_allocated += current_available;
                        state = State::FindMid;
                    }
                },
                State::FindMid => {
                    if blocks_allocated == blocks_needed {
                        state = State::FindLast;
                        continue;
                    } else if val == T::zero() {
                        blocks_allocated += 1;
                    }
                },
                State::FindLast => {
                    let current_available = val.leading_zeros() as usize;
                    rem_allocated += current_available;
                    if rem_allocated >= rem_needed {
                        found = true;
                        break;
                    }
                    state = State::FindFirst;
                    continue;
                },
            }
            index += 1;
        }
        if found {
            let mut allocated = 0usize;
            let mut first_mask = ilog2::bit_mask::<T>();
            first_mask = first_mask >> found_offset;
            allocated += block_size - found_offset;
            if allocated > size {
                let diff = allocated - size;
                first_mask = first_mask >> diff;
                first_mask = first_mask << diff;
                allocated = size;
            }
            let mut update_index = found_index;
            assert!(self[update_index] & first_mask == T::zero());
            println!("Allocate first at block {} [{},{}] : {:064b}", update_index, found_index, found_offset, self[update_index]);
            self[update_index] = self[update_index] | first_mask;
            println!("Allocate first at block {} [{},{}] : {:064b}", update_index, found_index, found_offset, self[update_index]);
            update_index += 1;

            let rem = size - allocated;
            let fill = rem / block_size;
            let last_fill = rem % block_size;

            for i in 0 .. fill {
                println!("Allocate mid at block {} [{},{}] : {:064b}", update_index + i, found_index, found_offset, self[update_index + i]);
                let mid_mask = ilog2::bit_mask::<T>();
                assert!(self[update_index + i] & mid_mask == T::zero());
                self[update_index + i] = self[update_index + i] | mid_mask;
                allocated += block_size;
                println!("Allocate mid at block {} [{},{}] : {:064b}", update_index + i, found_index, found_offset, self[update_index + i]);
            }
            if last_fill > 0 {
                println!("Allocate last at block {} [{},{}] : {:064b}", update_index + fill, found_index, found_offset, self[update_index + fill]);
                let mut last_mask = ilog2::bit_mask::<T>();
                let diff = block_size - last_fill;
                last_mask = last_mask >> diff;
                last_mask = last_mask << diff;
                assert!(self[update_index + fill] & last_mask == T::zero());
                self[update_index + fill] = self[update_index + fill] | last_mask;
                allocated += last_fill;
                println!("Allocate last at block {} [{},{}] : {:064b}", update_index + fill, found_index, found_offset, self[update_index + fill]);
            }
            assert!(allocated == size);

            ((found_index * block_size) + found_offset) as isize
        } else {
            -1isize
        }
    }
}<|endoftext|>


<commit_before>use libc;
use std::ptr;
use std::ffi::CStr;
use constants::*;
use csh;
use ffi::{cs_close, cs_open, cs_disasm, cs_reg_name, cs_insn_name, cs_errno};
use instruction::{Insn, Instructions};

pub struct Capstone {
    csh: csh, // Opaque handle to cs_engine
}

pub type CsResult<T> = Result<T, CsErr>;

impl Capstone {
    pub fn new(arch: CsArch, mode: CsMode) -> CsResult<Capstone> {
        let mut handle = 0;
        let err = unsafe { cs_open(arch, mode, &mut handle) };

        if CsErr::CS_ERR_OK == err {
            Ok(Capstone { csh: handle })
        } else {
            Err(err)
        }
    }

    pub fn disasm(&self, code: &[u8], addr: u64, count: isize) -> CsResult<Instructions> {
        let mut ptr: *const Insn = ptr::null();
        let insn_count = unsafe {
            cs_disasm(self.csh,
                      code.as_ptr(),
                      code.len() as libc::size_t,
                      addr,
                      count as libc::size_t,
                      &mut ptr)
        };
        if insn_count == 0 {
            return Err(unsafe { cs_errno(self.csh) })
        }

        Ok(Instructions::from_raw_parts(ptr, insn_count as isize))
    }

    pub fn reg_name(&self, reg_id: u64) -> Option<String> {
        let reg_name = unsafe {
            let _reg_name = cs_reg_name(self.csh, reg_id as libc::size_t);
            if _reg_name == ptr::null() {
                return None
            }

            CStr::from_ptr(_reg_name).to_string_lossy().into_owned()
        };

        Some(reg_name)
    }

    pub fn insn_name(&self, reg_id: u64) -> Option<String> {
        let reg_name = unsafe {
            let _reg_name = cs_insn_name(self.csh, reg_id as libc::size_t);
            if _reg_name == ptr::null() {
                return None
            }

            CStr::from_ptr(_reg_name).to_string_lossy().into_owned()
        };

        Some(reg_name)
    }
}

impl Drop for Capstone {
    fn drop(&mut self) {
        unsafe { cs_close(&mut self.csh) };
    }
}
<commit_msg>Add some documentation<commit_after>use libc;
use std::ptr;
use std::ffi::CStr;
use constants::*;
use csh;
use ffi::{cs_close, cs_open, cs_disasm, cs_reg_name, cs_insn_name, cs_errno};
use instruction::{Insn, Instructions};

/// An instance of the capstone disassembler
pub struct Capstone {
    csh: csh, // Opaque handle to cs_engine
}

pub type CsResult<T> = Result<T, CsErr>;

impl Capstone {
    /// Create a new instance of the decompiler
    ///
    /// ```
    /// use capstone::Capstone;
    /// use capstone::constants::*;
    /// let cs = Capstone::new(CsArch::ARCH_X86, CsMode::MODE_64);
    /// assert!(cs.is_ok());
    ///
    /// let cs = Capstone::new(CsArch::ARCH_ALL, CsMode::MODE_64);
    /// assert!(!cs.is_ok());
    /// ```
    pub fn new(arch: CsArch, mode: CsMode) -> CsResult<Capstone> {
        let mut handle = 0;
        let err = unsafe { cs_open(arch, mode, &mut handle) };

        if CsErr::CS_ERR_OK == err {
            Ok(Capstone { csh: handle })
        } else {
            Err(err)
        }
    }

    /// Disassemble a &[u8] full of instructions
    ///
    /// Pass count = 0 to disassemble all instructions in the buffer
    pub fn disasm(&self, code: &[u8], addr: u64, count: isize) -> CsResult<Instructions> {
        let mut ptr: *const Insn = ptr::null();
        let insn_count = unsafe {
            cs_disasm(self.csh,
                      code.as_ptr(),
                      code.len() as libc::size_t,
                      addr,
                      count as libc::size_t,
                      &mut ptr)
        };
        if insn_count == 0 {
            return Err(unsafe { cs_errno(self.csh) })
        }

        Ok(Instructions::from_raw_parts(ptr, insn_count as isize))
    }

    pub fn reg_name(&self, reg_id: u64) -> Option<String> {
        let reg_name = unsafe {
            let _reg_name = cs_reg_name(self.csh, reg_id as libc::size_t);
            if _reg_name == ptr::null() {
                return None
            }

            CStr::from_ptr(_reg_name).to_string_lossy().into_owned()
        };

        Some(reg_name)
    }

    pub fn insn_name(&self, reg_id: u64) -> Option<String> {
        let reg_name = unsafe {
            let _reg_name = cs_insn_name(self.csh, reg_id as libc::size_t);
            if _reg_name == ptr::null() {
                return None
            }

            CStr::from_ptr(_reg_name).to_string_lossy().into_owned()
        };

        Some(reg_name)
    }
}

impl Drop for Capstone {
    fn drop(&mut self) {
        unsafe { cs_close(&mut self.csh) };
    }
}
<|endoftext|>


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

extern crate libc;

use self::libc::funcs::posix88::unistd::execvp;
use std::io::process::Command;
use std::thread::Thread;
use std::ptr::null;
use std::os;
use std::c_str::ToCStr;
use std::io::fs::PathExtensions;
use std::io::{fs, File, Open, Write};
use config::Config;
use layout::LayoutMsg;
use xlib_window_system::XlibWindowSystem;
use workspaces::{Workspaces, MoveOp};
use xlib::Window;

pub enum Cmd {
  Exec(String),
  SwitchWorkspace(uint),
  SwitchScreen(uint),
  MoveToWorkspace(uint),
  MoveToScreen(uint),
  SendLayoutMsg(LayoutMsg),
  Reload,
  Exit,
  KillClient,
  FocusUp,
  FocusDown,
  FocusMaster,
  SwapUp,
  SwapDown,
  SwapMaster,
}

impl Cmd {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces<'a>, config: &Config) {
    match *self {
      Cmd::Exec(ref cmd) => {
        debug!("Cmd::Exec: {}", cmd);
        exec(cmd.clone());
      },
      Cmd::SwitchWorkspace(index) => {
        debug!("Cmd::SwitchWorkspace: {}", index);
        workspaces.switch_to(ws, config, index - 1);
      },
      Cmd::SwitchScreen(screen) => {
        debug!("Cmd::SwitchScreen: {}", screen);
        workspaces.switch_to_screen(ws, config, screen - 1);
      },
      Cmd::MoveToWorkspace(index) => {
        debug!("Cmd::MoveToWorkspace: {}", index);
        workspaces.move_window_to(ws, config, index - 1);
      },
      Cmd::MoveToScreen(screen) => {
        debug!("Cmd::MoveToScreen: {}", screen);
        workspaces.move_window_to_screen(ws, config, screen - 1);
      },
      Cmd::SendLayoutMsg(ref msg) => {
        debug!("Cmd::SendLayoutMsg::{}", msg);
        workspaces.current_mut().get_layout_mut().send_msg(msg.clone());
        workspaces.current().redraw(ws, config);
      },
      Cmd::Reload => {
        let path = os::self_exe_name().unwrap();
        let filename = String::from_str(path.filename_str().unwrap());
        let absolute = String::from_str(path.as_str().unwrap());
        let dir = String::from_str(path.dirname_str().unwrap());

        debug!("Cmd::Reload: compiling...");

        let mut cmd = Command::new(String::from_str("cargo"));
        cmd.cwd(&Path::new(dir)).arg("build").env("RUST_LOG", "none");

        match cmd.output() {
          Ok(output) => {
            if output.status.success() {
              debug!("Cmd::Reload: restarting... {}", absolute);

              unsafe {
                let mut slice : &mut [*const i8; 2] = &mut [
                  filename.to_c_str().as_ptr(),
                  null()
                ];

                let path = Path::new(concat!(env!("HOME"), "/.xr3wm/.tmp"));
                if path.exists() {
                  fs::unlink(&path);
                }

                let mut file = File::open_mode(&path, Open, Write).unwrap();
                file.write_str(workspaces.serialize().as_slice());
                file.flush();

                execvp(absolute.to_c_str().as_ptr(), slice.as_mut_ptr());
              }
            } else {
              panic!("failed to recompile: '{}'", output.status);
            }
          },
          _ => panic!("failed to start \"{}\"", cmd)
        }
      },
      Cmd::Exit => {
        debug!("Cmd::Exit");
        ws.close();
      },
      Cmd::KillClient => {
        debug!("Cmd::KillClient: {}", workspaces.current_mut().focused_window());
        ws.kill_window(workspaces.current_mut().focused_window());
      },
      Cmd::FocusUp => {
        debug!("Cmd::FocusUp: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Up);
      },
      Cmd::FocusDown => {
        debug!("Cmd::FocusDown: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Down);
      },
      Cmd::FocusMaster => {
        debug!("Cmd::FocusMaster: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Swap);
      },
      Cmd::SwapUp => {
        debug!("Cmd::SwapUp: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Up);
      },
      Cmd::SwapDown => {
        debug!("Cmd::SwapDown: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Down);
      },
      Cmd::SwapMaster => {
        debug!("Cmd::SwapMaster: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Swap);
      }
    }
  }
}

pub struct ManageHook {
  pub class_name: String,
  pub cmd: CmdManage
}

pub enum CmdManage {
  Move(uint),
  Float,
  Fullscreen,
  Ignore
}

impl CmdManage {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces<'a>, config: &Config, window: Window) {
    match *self {
      CmdManage::Move(index) => {
        debug!("CmdManage::Move: {}, {}", window, index);
        workspaces.get_mut(index - 1).add_window(ws, config, window);
        workspaces.get_mut(index - 1).focus_window(ws, config, window);
      },
      CmdManage::Float => {
        debug!("CmdManage::Float");
        unimplemented!()
      },
      CmdManage::Fullscreen => {
        debug!("CmdManage::Fullscreen");
        unimplemented!()
      },
      CmdManage::Ignore => {
        debug!("CmdManage::Ignore");
        unimplemented!()
      }
    }
  }
}

pub enum LogInfo {
  Workspaces(Vec<String>, uint, Vec<uint>),
  Title(String),
  Layout(String)
}

pub struct LogHook<'a> {
  pub logs: Vec<CmdLogHook>,
  pub output: |Vec<LogInfo>|:'a -> String
}

impl<'a> LogHook<'a> {
  pub fn call<'b>(&mut self, ws: &XlibWindowSystem, workspaces: &Workspaces<'b>) {
    println!("{}", (self.output)(self.logs.iter().map(|x| x.call(ws, workspaces)).collect()));
  }
}

pub enum CmdLogHook {
  Workspaces,
  Title,
  Layout
}

impl CmdLogHook {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &Workspaces<'a>) -> LogInfo {
    match *self {
      CmdLogHook::Workspaces => {
        LogInfo::Workspaces(workspaces.all().iter().map(|x| x.get_tag()).collect(), workspaces.get_index(), Vec::new())
      },
      CmdLogHook::Title => {
        LogInfo::Title(ws.get_window_title(workspaces.current().focused_window()))
      },
      CmdLogHook::Layout => {
        LogInfo::Layout(workspaces.current().get_layout().name())
      }
    }
  }
}

fn exec(cmd: String) {
  Thread::spawn(move || {
    let args : Vec<&str> = cmd.as_slice().split(' ').collect();

    if args.len() > 0 {
      let mut cmd = Command::new(args[0]);

      if args.len() > 1 {
        cmd.args(args.as_slice().slice_from(1));
      }

      match cmd.detached().output() {
        Ok(_) => (),
        _ => panic!("failed to start \"{}\"", cmd)
      }
    }
  }).detach();
}
<commit_msg>removed obsolete closure syntax<commit_after>#![allow(dead_code, unused_must_use)]

extern crate libc;

use self::libc::funcs::posix88::unistd::execvp;
use std::io::process::Command;
use std::thread::Thread;
use std::ptr::null;
use std::os;
use std::c_str::ToCStr;
use std::io::fs::PathExtensions;
use std::io::{fs, File, Open, Write};
use config::Config;
use layout::LayoutMsg;
use xlib_window_system::XlibWindowSystem;
use workspaces::{Workspaces, MoveOp};
use xlib::Window;

pub enum Cmd {
  Exec(String),
  SwitchWorkspace(uint),
  SwitchScreen(uint),
  MoveToWorkspace(uint),
  MoveToScreen(uint),
  SendLayoutMsg(LayoutMsg),
  Reload,
  Exit,
  KillClient,
  FocusUp,
  FocusDown,
  FocusMaster,
  SwapUp,
  SwapDown,
  SwapMaster,
}

impl Cmd {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces<'a>, config: &Config) {
    match *self {
      Cmd::Exec(ref cmd) => {
        debug!("Cmd::Exec: {}", cmd);
        exec(cmd.clone());
      },
      Cmd::SwitchWorkspace(index) => {
        debug!("Cmd::SwitchWorkspace: {}", index);
        workspaces.switch_to(ws, config, index - 1);
      },
      Cmd::SwitchScreen(screen) => {
        debug!("Cmd::SwitchScreen: {}", screen);
        workspaces.switch_to_screen(ws, config, screen - 1);
      },
      Cmd::MoveToWorkspace(index) => {
        debug!("Cmd::MoveToWorkspace: {}", index);
        workspaces.move_window_to(ws, config, index - 1);
      },
      Cmd::MoveToScreen(screen) => {
        debug!("Cmd::MoveToScreen: {}", screen);
        workspaces.move_window_to_screen(ws, config, screen - 1);
      },
      Cmd::SendLayoutMsg(ref msg) => {
        debug!("Cmd::SendLayoutMsg::{}", msg);
        workspaces.current_mut().get_layout_mut().send_msg(msg.clone());
        workspaces.current().redraw(ws, config);
      },
      Cmd::Reload => {
        let path = os::self_exe_name().unwrap();
        let filename = String::from_str(path.filename_str().unwrap());
        let absolute = String::from_str(path.as_str().unwrap());
        let dir = String::from_str(path.dirname_str().unwrap());

        debug!("Cmd::Reload: compiling...");

        let mut cmd = Command::new(String::from_str("cargo"));
        cmd.cwd(&Path::new(dir)).arg("build").env("RUST_LOG", "none");

        match cmd.output() {
          Ok(output) => {
            if output.status.success() {
              debug!("Cmd::Reload: restarting... {}", absolute);

              unsafe {
                let mut slice : &mut [*const i8; 2] = &mut [
                  filename.to_c_str().as_ptr(),
                  null()
                ];

                let path = Path::new(concat!(env!("HOME"), "/.xr3wm/.tmp"));
                if path.exists() {
                  fs::unlink(&path);
                }

                let mut file = File::open_mode(&path, Open, Write).unwrap();
                file.write_str(workspaces.serialize().as_slice());
                file.flush();

                execvp(absolute.to_c_str().as_ptr(), slice.as_mut_ptr());
              }
            } else {
              panic!("failed to recompile: '{}'", output.status);
            }
          },
          _ => panic!("failed to start \"{}\"", cmd)
        }
      },
      Cmd::Exit => {
        debug!("Cmd::Exit");
        ws.close();
      },
      Cmd::KillClient => {
        debug!("Cmd::KillClient: {}", workspaces.current_mut().focused_window());
        ws.kill_window(workspaces.current_mut().focused_window());
      },
      Cmd::FocusUp => {
        debug!("Cmd::FocusUp: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Up);
      },
      Cmd::FocusDown => {
        debug!("Cmd::FocusDown: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Down);
      },
      Cmd::FocusMaster => {
        debug!("Cmd::FocusMaster: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Swap);
      },
      Cmd::SwapUp => {
        debug!("Cmd::SwapUp: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Up);
      },
      Cmd::SwapDown => {
        debug!("Cmd::SwapDown: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Down);
      },
      Cmd::SwapMaster => {
        debug!("Cmd::SwapMaster: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Swap);
      }
    }
  }
}

pub struct ManageHook {
  pub class_name: String,
  pub cmd: CmdManage
}

pub enum CmdManage {
  Move(uint),
  Float,
  Fullscreen,
  Ignore
}

impl CmdManage {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces<'a>, config: &Config, window: Window) {
    match *self {
      CmdManage::Move(index) => {
        debug!("CmdManage::Move: {}, {}", window, index);
        workspaces.get_mut(index - 1).add_window(ws, config, window);
        workspaces.get_mut(index - 1).focus_window(ws, config, window);
      },
      CmdManage::Float => {
        debug!("CmdManage::Float");
        unimplemented!()
      },
      CmdManage::Fullscreen => {
        debug!("CmdManage::Fullscreen");
        unimplemented!()
      },
      CmdManage::Ignore => {
        debug!("CmdManage::Ignore");
        unimplemented!()
      }
    }
  }
}

pub enum LogInfo {
  Workspaces(Vec<String>, uint, Vec<uint>),
  Title(String),
  Layout(String)
}

pub struct LogHook<'a> {
  pub logs: Vec<CmdLogHook>,
  pub output: Box<Fn(Vec<LogInfo>) -> String + 'a>
}

impl<'a> LogHook<'a> {
  pub fn call<'b>(&mut self, ws: &XlibWindowSystem, workspaces: &Workspaces<'b>) {
    println!("{}", (self.output)(self.logs.iter().map(|x| x.call(ws, workspaces)).collect()));
  }
}

pub enum CmdLogHook {
  Workspaces,
  Title,
  Layout
}

impl CmdLogHook {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &Workspaces<'a>) -> LogInfo {
    match *self {
      CmdLogHook::Workspaces => {
        LogInfo::Workspaces(workspaces.all().iter().map(|x| x.get_tag()).collect(), workspaces.get_index(), Vec::new())
      },
      CmdLogHook::Title => {
        LogInfo::Title(ws.get_window_title(workspaces.current().focused_window()))
      },
      CmdLogHook::Layout => {
        LogInfo::Layout(workspaces.current().get_layout().name())
      }
    }
  }
}

fn exec(cmd: String) {
  Thread::spawn(move || {
    let args : Vec<&str> = cmd.as_slice().split(' ').collect();

    if args.len() > 0 {
      let mut cmd = Command::new(args[0]);

      if args.len() > 1 {
        cmd.args(args.as_slice().slice_from(1));
      }

      match cmd.detached().output() {
        Ok(_) => (),
        _ => panic!("failed to start \"{}\"", cmd)
      }
    }
  }).detach();
}
<|endoftext|>


<commit_before>use calx_grid::{FovValue, HexGeom};
use euclid::Vector2D;
use location::Location;
use terraform::TerrainQuery;
use world::World;

#[derive(Clone)]
pub struct SightFov<'a> {
    w: &'a World,
    range: u32,
    pub origin: Location,
    is_edge: bool,
}

impl<'a> SightFov<'a> {
    pub fn new(w: &'a World, range: u32, origin: Location) -> SightFov<'a> {
        SightFov {
            w,
            range,
            origin,
            is_edge: false,
        }
    }
}

impl<'a> PartialEq for SightFov<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.w as *const World == other.w as *const World && self.range == other.range &&
            self.origin == other.origin && self.is_edge == other.is_edge
    }
}

impl<'a> Eq for SightFov<'a> {}

impl<'a> FovValue for SightFov<'a> {
    fn advance(&self, offset: Vector2D<i32>) -> Option<Self> {
        if offset.hex_dist() as u32 > self.range {
            return None;
        }

        if self.is_edge {
            return None;
        }

        let mut ret = self.clone();
        if let Some(dest) = self.w.visible_portal(self.origin + offset) {
            ret.origin = dest - offset;
        }

        if self.w.terrain(self.origin + offset).blocks_sight() {
            ret.is_edge = true;
        }

        Some(ret)
    }

    fn is_fake_isometric_wall(&self, offset: Vector2D<i32>) -> bool {
        self.w.terrain(self.origin + offset).is_wall()
    }
}

#[derive(Clone)]
/// Field for spherical explosions that can be blocked by terrain.
pub struct SphereVolumeFov<'a> {
    w: &'a World,
    range: u32,
    pub origin: Location,
}

impl<'a> SphereVolumeFov<'a> {
    pub fn new(w: &'a World, range: u32, origin: Location) -> SphereVolumeFov<'a> {
        SphereVolumeFov { w, range, origin }
    }
}

impl<'a> PartialEq for SphereVolumeFov<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.w as *const World == other.w as *const World && self.range == other.range &&
            self.origin == other.origin
    }
}

impl<'a> Eq for SphereVolumeFov<'a> {}

impl<'a> FovValue for SphereVolumeFov<'a> {
    fn advance(&self, offset: Vector2D<i32>) -> Option<Self> {
        if offset.hex_dist() as u32 > self.range {
            return None;
        }

        let mut ret = self.clone();
        // NB: Sphere volumes don't spread over non-visible portals. Not sure if this is the right
        // choice but it would probably be annoying and surprising if they did.
        if let Some(dest) = self.w.visible_portal(self.origin + offset) {
            ret.origin = dest - offset;
        }

        // Unlike with sight fov, the blocking cells won't be included in the result set.

        // TODO: Stopping criteria should be generalized to a function, don't just assume
        // `blocks_shot` is good.
        if self.w.terrain(self.origin + offset).blocks_shot() {
            return None;
        }

        Some(ret)
    }
}
<commit_msg>Probably want this to be past the portal<commit_after>use calx_grid::{FovValue, HexGeom};
use euclid::Vector2D;
use location::Location;
use terraform::TerrainQuery;
use world::World;

#[derive(Clone)]
pub struct SightFov<'a> {
    w: &'a World,
    range: u32,
    pub origin: Location,
    is_edge: bool,
}

impl<'a> SightFov<'a> {
    pub fn new(w: &'a World, range: u32, origin: Location) -> SightFov<'a> {
        SightFov {
            w,
            range,
            origin,
            is_edge: false,
        }
    }
}

impl<'a> PartialEq for SightFov<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.w as *const World == other.w as *const World && self.range == other.range &&
            self.origin == other.origin && self.is_edge == other.is_edge
    }
}

impl<'a> Eq for SightFov<'a> {}

impl<'a> FovValue for SightFov<'a> {
    fn advance(&self, offset: Vector2D<i32>) -> Option<Self> {
        if offset.hex_dist() as u32 > self.range {
            return None;
        }

        if self.is_edge {
            return None;
        }

        let mut ret = self.clone();
        if let Some(dest) = self.w.visible_portal(self.origin + offset) {
            ret.origin = dest - offset;
        }

        if self.w.terrain(ret.origin + offset).blocks_sight() {
            ret.is_edge = true;
        }

        Some(ret)
    }

    fn is_fake_isometric_wall(&self, offset: Vector2D<i32>) -> bool {
        self.w.terrain(self.origin + offset).is_wall()
    }
}

#[derive(Clone)]
/// Field for spherical explosions that can be blocked by terrain.
pub struct SphereVolumeFov<'a> {
    w: &'a World,
    range: u32,
    pub origin: Location,
}

impl<'a> SphereVolumeFov<'a> {
    pub fn new(w: &'a World, range: u32, origin: Location) -> SphereVolumeFov<'a> {
        SphereVolumeFov { w, range, origin }
    }
}

impl<'a> PartialEq for SphereVolumeFov<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.w as *const World == other.w as *const World && self.range == other.range &&
            self.origin == other.origin
    }
}

impl<'a> Eq for SphereVolumeFov<'a> {}

impl<'a> FovValue for SphereVolumeFov<'a> {
    fn advance(&self, offset: Vector2D<i32>) -> Option<Self> {
        if offset.hex_dist() as u32 > self.range {
            return None;
        }

        let mut ret = self.clone();
        // NB: Sphere volumes don't spread over non-visible portals. Not sure if this is the right
        // choice but it would probably be annoying and surprising if they did.
        if let Some(dest) = self.w.visible_portal(self.origin + offset) {
            ret.origin = dest - offset;
        }

        // Unlike with sight fov, the blocking cells won't be included in the result set.

        // TODO: Stopping criteria should be generalized to a function, don't just assume
        // `blocks_shot` is good.
        if self.w.terrain(self.origin + offset).blocks_shot() {
            return None;
        }

        Some(ret)
    }
}
<|endoftext|>


<commit_before>extern crate image;
extern crate euclid;
extern crate vitral;
extern crate calx_color;
#[macro_use]
extern crate calx_ecs;
#[macro_use]
extern crate calx_resource;

mod brush;
pub mod terrain;

pub use brush::{Brush, BrushBuilder, Color, Frame, ImageRef, Splat};
<commit_msg>Activate more world crate stuff<commit_after>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

extern crate rand;
extern crate bincode;
extern crate serde;
extern crate vec_map;
extern crate cgmath;
extern crate image;
extern crate euclid;
extern crate vitral;
extern crate calx_alg;
extern crate calx_grid;
extern crate calx_color;
#[macro_use]
extern crate calx_ecs;
#[macro_use]
extern crate calx_resource;

mod brush;
pub use brush::{Brush, BrushBuilder, Color, Frame, ImageRef, Splat};

pub mod item;

mod location;
pub use location::{Location, Chart, Unchart};

mod location_set;
mod spatial;

pub mod terrain;
<|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };

struct App {
    gl: GlGraphics,
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];

        self.gl.draw(args.viewport(), |c, gl| {
            clear(WHITE, gl);
        });
    }
}

fn main() {
    let opengl = OpenGL::V3_2;

    let window: Window = WindowSettings::new(
        "Sierpinski-Triangle",
        [1000, 800])
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    let mut app = App{gl: GlGraphics::new(opengl)};

    for e in window.events() {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }
    }
}
<commit_msg>Drawing a triangle<commit_after>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };

struct App {
    gl: GlGraphics,
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
        const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

        let triangle = [[100.0, 200.0], [200.0, 200.0],
                        [150.0, 100.0], [100.0, 200.0]];

        self.gl.draw(args.viewport(), |c, gl| {
            clear(WHITE, gl);

            let transform = c.transform.trans(100.0, 100.0);

            polygon(BLACK, &triangle, transform, gl);
        });
    }
}

fn main() {
    let opengl = OpenGL::V3_2;

    let window: Window = WindowSettings::new(
        "Sierpinski-Triangle",
        [1000, 800])
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    let mut app = App{gl: GlGraphics::new(opengl)};

    for e in window.events() {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)] // until raw_ops are implemented

use libc::c_float;
use libc::c_int;
use libc::c_uchar;
use libc::c_void;
use libc::size_t;
use std::ffi::{CStr, CString};
use std::os::raw::c_void as std_c_void;
use std::ptr;

use crate::eager::{Context, TensorHandle};
use crate::{AnyTensor, DataType, Result, Shape, Status};

use tensorflow_sys as tf;

/// Description of the TensorFlow op to execute.
struct Op {
    inner: *mut tf::TFE_Op,
}
impl_drop!(Op, TFE_DeleteOp);

impl Op {
    fn new(ctx: &Context, op_or_function_name: &str) -> Result<Op> {
        let status = Status::new();

        let op_or_function_name = CString::new(op_or_function_name)?;
        let inner = unsafe { tf::TFE_NewOp(ctx.inner, op_or_function_name.as_ptr(), status.inner) };
        if inner.is_null() {
            return Err(status);
        }
        Ok(Self { inner })
    }

    #[allow(dead_code)]
    fn get_name(&self) -> Result<&str> {
        let status = Status::new();

        let name = unsafe {
            let name = tf::TFE_OpGetName(self.inner, status.inner);
            CStr::from_ptr(name)
        };
        if status.is_ok() {
            return Ok(name.to_str()?);
        }
        Err(status)
    }

    /// Context may not be outlive over the lifetime of `op'
    #[allow(dead_code)]
    fn get_context(&self) -> &Context {
        unimplemented!()
    }

    /// Adds an input to this operation.
    fn add_input(&mut self, input: &TensorHandle) -> Result<()> {
        let status = Status::new();
        unsafe {
            tf::TFE_OpAddInput(self.inner, input.inner, status.inner);
        };
        status.into_result()
    }

    /// Adds multiple inputs to this operation.
    #[allow(dead_code)]
    fn add_input_list(&mut self, inputs: &[TensorHandle]) -> Result<()> {
        let status = Status::new();
        unsafe {
            let mut inputs: Vec<*mut tf::TFE_TensorHandle> =
                inputs.iter().map(|v| v.inner).collect();
            tf::TFE_OpAddInputList(
                self.inner,
                inputs.as_mut_ptr(),
                inputs.len() as c_int,
                status.inner,
            );
        };
        status.into_result()
    }

    /// Sets the value of a string attribute.
    fn set_attr_string(&mut self, attr_name: &str, value: &str) -> Result<()> {
        let attr_name = CString::new(attr_name)?;
        let c_value = value.as_bytes();
        unsafe {
            tf::TFE_OpSetAttrString(
                self.inner,
                attr_name.as_ptr(),
                c_value.as_ptr() as *const std_c_void,
                c_value.len() as size_t,
            );
        }
        Ok(())
    }

    /// Sets the value of an attribute which holds a list of strings.
    fn set_attr_string_list<S: AsRef<str>>(&mut self, attr_name: &str, values: &[S]) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        let bytes: Vec<&[u8]> = values.iter().map(|x| x.as_ref().as_bytes()).collect();
        let ptrs: Vec<*const c_void> = bytes.iter().map(|x| x.as_ptr() as *const c_void).collect();
        let lens: Vec<size_t> = bytes.iter().map(|x| x.len() as size_t).collect();
        unsafe {
            tf::TFE_OpSetAttrStringList(
                self.inner,
                c_attr_name.as_ptr(),
                ptrs.as_ptr() as *const *const std_c_void,
                lens.as_ptr(),
                ptrs.len() as c_int,
            );
        }
        Ok(())
    }

    /// Sets an int-valued attribute.
    fn set_attr_int(&mut self, attr_name: &str, value: i64) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            tf::TFE_OpSetAttrInt(self.inner, c_attr_name.as_ptr(), value);
        }
        Ok(())
    }

    /// Sets an attribute which holds an array of ints.
    fn set_attr_int_list(&mut self, attr_name: &str, value: &[i64]) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            tf::TFE_OpSetAttrIntList(
                self.inner,
                c_attr_name.as_ptr(),
                value.as_ptr(),
                value.len() as i32,
            );
        }
        Ok(())
    }

    /// Sets a float-valued attribute.
    fn set_attr_float(&mut self, attr_name: &str, value: f32) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            tf::TFE_OpSetAttrFloat(self.inner, c_attr_name.as_ptr(), value);
        }
        Ok(())
    }

    /// Sets an attribute which holds an array of floats.
    fn set_attr_float_list(&mut self, attr_name: &str, value: &[f32]) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        // Allow trivial_numeric_casts here because f32 is not necessarily equal to c_float.
        let c_value: Vec<c_float> = value.iter().map(|x| *x as c_float).collect();
        unsafe {
            tf::TFE_OpSetAttrFloatList(
                self.inner,
                c_attr_name.as_ptr(),
                c_value.as_ptr(),
                c_value.len() as i32,
            );
        }
        Ok(())
    }

    /// Sets a boolean-valued attribute.
    fn set_attr_bool(&mut self, attr_name: &str, value: bool) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            tf::TFE_OpSetAttrBool(self.inner, c_attr_name.as_ptr(), if value { 1 } else { 0 });
        }
        Ok(())
    }

    /// Sets an attribute which holds an array of booleans.
    fn set_attr_bool_list(&mut self, attr_name: &str, value: &[bool]) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        let c_value: Vec<c_uchar> = value.iter().map(|x| if *x { 1 } else { 0 }).collect();
        unsafe {
            tf::TFE_OpSetAttrBoolList(
                self.inner,
                c_attr_name.as_ptr(),
                c_value.as_ptr(),
                c_value.len() as c_int,
            );
        }
        Ok(())
    }

    /// Sets a type-valued attribute.
    fn set_attr_type(&mut self, attr_name: &str, value: DataType) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            tf::TFE_OpSetAttrType(self.inner, c_attr_name.as_ptr(), value.to_c());
        }
        Ok(())
    }

    /// Sets an attribute which holds an array of types.
    fn set_attr_type_list(&mut self, attr_name: &str, value: &[DataType]) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        let c_value: Vec<tf::TF_DataType> = value.iter().map(|x| x.to_c()).collect();
        unsafe {
            tf::TFE_OpSetAttrTypeList(
                self.inner,
                c_attr_name.as_ptr(),
                c_value.as_ptr(),
                c_value.len() as i32,
            );
        }
        Ok(())
    }

    /// Sets a shape-valued attribute.
    fn set_attr_shape(&mut self, attr_name: &str, value: &Shape) -> Result<()> {
        let status = Status::new();

        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            match value.0 {
                None => tf::TFE_OpSetAttrShape(
                    self.inner,
                    c_attr_name.as_ptr(),
                    ptr::null(),
                    -1,
                    status.inner,
                ),
                Some(ref dims) => {
                    let c_dims: Vec<i64> = dims.iter().map(|x| (*x).unwrap_or(-1)).collect();
                    tf::TFE_OpSetAttrShape(
                        self.inner,
                        c_attr_name.as_ptr(),
                        c_dims.as_ptr(),
                        c_dims.len() as i32,
                        status.inner,
                    );
                }
            }
        }
        status.into_result()
    }

    /// Sets an attribute which holds an array of shapes.
    fn set_attr_shape_list(&mut self, attr_name: &str, value: &[Shape]) -> Result<()> {
        let status = Status::new();

        let c_attr_name = CString::new(attr_name)?;
        // Convert Option<i64> in each shape to i64 with None becoming -1.
        let c_dims: Vec<Option<Vec<i64>>> = value
            .iter()
            .map(|x| {
                x.0.as_ref()
                    .map(|dims| dims.iter().map(|x| (*x).unwrap_or(-1)).collect())
            })
            .collect();
        let mut ptrs: Vec<*const i64> = c_dims
            .iter()
            .map(|x| match *x {
                None => ptr::null(),
                Some(ref dims) => dims.as_ptr(),
            })
            .collect();
        let lens: Vec<c_int> = value
            .iter()
            .map(|x| match x.0 {
                None => -1,
                Some(ref dims) => dims.len() as c_int,
            })
            .collect();
        unsafe {
            tf::TFE_OpSetAttrShapeList(
                self.inner,
                c_attr_name.as_ptr(),
                ptrs.as_mut_ptr(),
                lens.as_ptr(),
                ptrs.len() as c_int,
                status.inner,
            );
        }
        status.into_result()
    }

    /// Sets a tensor-valued attribute.
    fn set_attr_any_tensor(&mut self, attr_name: &str, value: &dyn AnyTensor) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        let mut status = Status::new();
        unsafe {
            tf::TFE_OpSetAttrTensor(
                self.inner,
                c_attr_name.as_ptr(),
                value.inner()?,
                status.inner(),
            );
        }
        status.into_result()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::eager::{Context, ContextOptions, TensorHandle};
    use crate::Tensor;

    // Tentative implementation of raw_ops for unit testing.
    mod raw_ops {
        use super::*;
        use crate::eager::TensorHandle;

        /// Add
        #[derive(::std::fmt::Debug)]
        pub struct Add {
            T: ::std::option::Option<crate::DataType>,
        }

        impl ::std::default::Default for Add {
            fn default() -> Self {
                Self { T: None }
            }
        }

        impl Add {
            /// Creates a new `Add`.
            pub fn new() -> Self {
                Self::default()
            }

            /// Sets the `T` attribute.
            pub fn T<ArgType: ::std::convert::Into<crate::DataType>>(
                mut self,
                value: ArgType,
            ) -> Self {
                self.T = ::std::option::Option::Some(value.into());
                self
            }

            /// Execute add.
            pub fn call<'a>(
                &self,
                ctx: &'a crate::eager::Context,
                x: &TensorHandle,
                y: &TensorHandle,
            ) -> Result<TensorHandle<'a>> {
                let status = crate::Status::new();

                // Define Op

                let op_name = "Add";
                let mut op = Op::new(ctx, op_name)?;

                // Required input arguments
                op.add_input(&x)?;
                op.add_input(&y)?;

                // Attributes
                if let ::std::option::Option::Some(value) = &self.T {
                    let attr_name = "T";
                    op.set_attr_type(attr_name, *value)?;
                }

                // Execute Op
                let mut num_output = 1;
                let mut res = [std::ptr::null_mut::<tensorflow_sys::TFE_TensorHandle>(); 1];
                unsafe {
                    tf::TFE_Execute(
                        op.inner,
                        res.as_mut_ptr(),
                        (&mut num_output) as *mut i32,
                        status.inner,
                    );
                };
                if status.is_ok() {
                    let ret = TensorHandle::from_tensor_handle(ctx, res[0]);
                    return Ok(ret);
                }
                Err(status)
            }
        }

        /// add with default options.
        pub fn add<'a>(
            ctx: &'a crate::eager::Context,
            x: &TensorHandle,
            y: &TensorHandle,
        ) -> Result<TensorHandle<'a>> {
            let op = Add::new();
            op.call(ctx, x, y)
        }
    }

    #[test]
    fn test_add() {
        use raw_ops::add;

        let ctx = Context::new(ContextOptions::new()).unwrap();
        let x = Tensor::new(&[2, 2]).with_values(&[1i32, 2, 3, 4]).unwrap();
        let h_x = TensorHandle::new(&ctx, &x).unwrap();
        let h_y = h_x.copy_sharing_tensor().unwrap();
        let h_z = add(&ctx, &h_x, &h_y).unwrap();
        let z: crate::Tensor<i32> = h_z.resolve().unwrap();
        assert_eq!(&z[..], &[2i32, 4, 6, 8]);
    }
}
<commit_msg>add Operation's device setter/getter<commit_after>#![allow(dead_code)] // until raw_ops are implemented

use libc::c_float;
use libc::c_int;
use libc::c_uchar;
use libc::c_void;
use libc::size_t;
use std::ffi::{CStr, CString};
use std::os::raw::c_void as std_c_void;
use std::ptr;

use crate::eager::{Context, TensorHandle};
use crate::{AnyTensor, DataType, Result, Shape, Status};

use tensorflow_sys as tf;

/// Description of the TensorFlow op to execute.
struct Op {
    inner: *mut tf::TFE_Op,
}
impl_drop!(Op, TFE_DeleteOp);

impl Op {
    fn new(ctx: &Context, op_or_function_name: &str) -> Result<Op> {
        let status = Status::new();

        let op_or_function_name = CString::new(op_or_function_name)?;
        let inner = unsafe { tf::TFE_NewOp(ctx.inner, op_or_function_name.as_ptr(), status.inner) };
        if inner.is_null() {
            return Err(status);
        }
        Ok(Self { inner })
    }

    #[allow(dead_code)]
    fn get_name(&self) -> Result<&str> {
        let status = Status::new();

        let name = unsafe {
            let name = tf::TFE_OpGetName(self.inner, status.inner);
            CStr::from_ptr(name)
        };
        if status.is_ok() {
            return Ok(name.to_str()?);
        }
        Err(status)
    }

    /// Context may not be outlive over the lifetime of `op'
    #[allow(dead_code)]
    fn get_context(&self) -> &Context {
        unimplemented!()
    }

    /// Adds an input to this operation.
    fn add_input(&mut self, input: &TensorHandle) -> Result<()> {
        let status = Status::new();
        unsafe {
            tf::TFE_OpAddInput(self.inner, input.inner, status.inner);
        };
        status.into_result()
    }

    /// Set the device where this operation is computed.
    fn set_device(&mut self, device_name: &str) -> Result<()> {
        let status = Status::new();
        let c_device_name = CString::new(device_name)?;
        unsafe {
            tf::TFE_OpSetDevice(self.inner, c_device_name.as_ptr(), status.inner);
        }
        status.into_result()
    }

    /// Get the device where this operation is computed.
    fn get_device(&self) -> Result<&str> {
        let status = Status::new();
        let device_name = unsafe {
            // The returned string remains valid throughout the lifetime of 'op'.
            let device_name = tf::TFE_OpGetDevice(self.inner, status.inner);
            CStr::from_ptr(device_name)
        };
        if status.is_ok() {
            return Ok(device_name.to_str()?);
        }
        Err(status)
    }

    /// Adds multiple inputs to this operation.
    #[allow(dead_code)]
    fn add_input_list(&mut self, inputs: &[TensorHandle]) -> Result<()> {
        let status = Status::new();
        unsafe {
            let mut inputs: Vec<*mut tf::TFE_TensorHandle> =
                inputs.iter().map(|v| v.inner).collect();
            tf::TFE_OpAddInputList(
                self.inner,
                inputs.as_mut_ptr(),
                inputs.len() as c_int,
                status.inner,
            );
        };
        status.into_result()
    }

    /// Sets the value of a string attribute.
    fn set_attr_string(&mut self, attr_name: &str, value: &str) -> Result<()> {
        let attr_name = CString::new(attr_name)?;
        let c_value = value.as_bytes();
        unsafe {
            tf::TFE_OpSetAttrString(
                self.inner,
                attr_name.as_ptr(),
                c_value.as_ptr() as *const std_c_void,
                c_value.len() as size_t,
            );
        }
        Ok(())
    }

    /// Sets the value of an attribute which holds a list of strings.
    fn set_attr_string_list<S: AsRef<str>>(&mut self, attr_name: &str, values: &[S]) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        let bytes: Vec<&[u8]> = values.iter().map(|x| x.as_ref().as_bytes()).collect();
        let ptrs: Vec<*const c_void> = bytes.iter().map(|x| x.as_ptr() as *const c_void).collect();
        let lens: Vec<size_t> = bytes.iter().map(|x| x.len() as size_t).collect();
        unsafe {
            tf::TFE_OpSetAttrStringList(
                self.inner,
                c_attr_name.as_ptr(),
                ptrs.as_ptr() as *const *const std_c_void,
                lens.as_ptr(),
                ptrs.len() as c_int,
            );
        }
        Ok(())
    }

    /// Sets an int-valued attribute.
    fn set_attr_int(&mut self, attr_name: &str, value: i64) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            tf::TFE_OpSetAttrInt(self.inner, c_attr_name.as_ptr(), value);
        }
        Ok(())
    }

    /// Sets an attribute which holds an array of ints.
    fn set_attr_int_list(&mut self, attr_name: &str, value: &[i64]) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            tf::TFE_OpSetAttrIntList(
                self.inner,
                c_attr_name.as_ptr(),
                value.as_ptr(),
                value.len() as i32,
            );
        }
        Ok(())
    }

    /// Sets a float-valued attribute.
    fn set_attr_float(&mut self, attr_name: &str, value: f32) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            tf::TFE_OpSetAttrFloat(self.inner, c_attr_name.as_ptr(), value);
        }
        Ok(())
    }

    /// Sets an attribute which holds an array of floats.
    fn set_attr_float_list(&mut self, attr_name: &str, value: &[f32]) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        // Allow trivial_numeric_casts here because f32 is not necessarily equal to c_float.
        let c_value: Vec<c_float> = value.iter().map(|x| *x as c_float).collect();
        unsafe {
            tf::TFE_OpSetAttrFloatList(
                self.inner,
                c_attr_name.as_ptr(),
                c_value.as_ptr(),
                c_value.len() as i32,
            );
        }
        Ok(())
    }

    /// Sets a boolean-valued attribute.
    fn set_attr_bool(&mut self, attr_name: &str, value: bool) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            tf::TFE_OpSetAttrBool(self.inner, c_attr_name.as_ptr(), if value { 1 } else { 0 });
        }
        Ok(())
    }

    /// Sets an attribute which holds an array of booleans.
    fn set_attr_bool_list(&mut self, attr_name: &str, value: &[bool]) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        let c_value: Vec<c_uchar> = value.iter().map(|x| if *x { 1 } else { 0 }).collect();
        unsafe {
            tf::TFE_OpSetAttrBoolList(
                self.inner,
                c_attr_name.as_ptr(),
                c_value.as_ptr(),
                c_value.len() as c_int,
            );
        }
        Ok(())
    }

    /// Sets a type-valued attribute.
    fn set_attr_type(&mut self, attr_name: &str, value: DataType) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            tf::TFE_OpSetAttrType(self.inner, c_attr_name.as_ptr(), value.to_c());
        }
        Ok(())
    }

    /// Sets an attribute which holds an array of types.
    fn set_attr_type_list(&mut self, attr_name: &str, value: &[DataType]) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        let c_value: Vec<tf::TF_DataType> = value.iter().map(|x| x.to_c()).collect();
        unsafe {
            tf::TFE_OpSetAttrTypeList(
                self.inner,
                c_attr_name.as_ptr(),
                c_value.as_ptr(),
                c_value.len() as i32,
            );
        }
        Ok(())
    }

    /// Sets a shape-valued attribute.
    fn set_attr_shape(&mut self, attr_name: &str, value: &Shape) -> Result<()> {
        let status = Status::new();

        let c_attr_name = CString::new(attr_name)?;
        unsafe {
            match value.0 {
                None => tf::TFE_OpSetAttrShape(
                    self.inner,
                    c_attr_name.as_ptr(),
                    ptr::null(),
                    -1,
                    status.inner,
                ),
                Some(ref dims) => {
                    let c_dims: Vec<i64> = dims.iter().map(|x| (*x).unwrap_or(-1)).collect();
                    tf::TFE_OpSetAttrShape(
                        self.inner,
                        c_attr_name.as_ptr(),
                        c_dims.as_ptr(),
                        c_dims.len() as i32,
                        status.inner,
                    );
                }
            }
        }
        status.into_result()
    }

    /// Sets an attribute which holds an array of shapes.
    fn set_attr_shape_list(&mut self, attr_name: &str, value: &[Shape]) -> Result<()> {
        let status = Status::new();

        let c_attr_name = CString::new(attr_name)?;
        // Convert Option<i64> in each shape to i64 with None becoming -1.
        let c_dims: Vec<Option<Vec<i64>>> = value
            .iter()
            .map(|x| {
                x.0.as_ref()
                    .map(|dims| dims.iter().map(|x| (*x).unwrap_or(-1)).collect())
            })
            .collect();
        let mut ptrs: Vec<*const i64> = c_dims
            .iter()
            .map(|x| match *x {
                None => ptr::null(),
                Some(ref dims) => dims.as_ptr(),
            })
            .collect();
        let lens: Vec<c_int> = value
            .iter()
            .map(|x| match x.0 {
                None => -1,
                Some(ref dims) => dims.len() as c_int,
            })
            .collect();
        unsafe {
            tf::TFE_OpSetAttrShapeList(
                self.inner,
                c_attr_name.as_ptr(),
                ptrs.as_mut_ptr(),
                lens.as_ptr(),
                ptrs.len() as c_int,
                status.inner,
            );
        }
        status.into_result()
    }

    /// Sets a tensor-valued attribute.
    fn set_attr_any_tensor(&mut self, attr_name: &str, value: &dyn AnyTensor) -> Result<()> {
        let c_attr_name = CString::new(attr_name)?;
        let mut status = Status::new();
        unsafe {
            tf::TFE_OpSetAttrTensor(
                self.inner,
                c_attr_name.as_ptr(),
                value.inner()?,
                status.inner(),
            );
        }
        status.into_result()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::eager::{Context, ContextOptions, TensorHandle};
    use crate::Tensor;

    // Tentative implementation of raw_ops for unit testing.
    mod raw_ops {
        use super::*;
        use crate::eager::TensorHandle;

        /// Add
        #[derive(::std::fmt::Debug)]
        pub struct Add {
            T: ::std::option::Option<crate::DataType>,
        }

        impl ::std::default::Default for Add {
            fn default() -> Self {
                Self { T: None }
            }
        }

        impl Add {
            /// Creates a new `Add`.
            pub fn new() -> Self {
                Self::default()
            }

            /// Sets the `T` attribute.
            pub fn T<ArgType: ::std::convert::Into<crate::DataType>>(
                mut self,
                value: ArgType,
            ) -> Self {
                self.T = ::std::option::Option::Some(value.into());
                self
            }

            /// Execute add.
            pub fn call<'a>(
                &self,
                ctx: &'a crate::eager::Context,
                x: &TensorHandle,
                y: &TensorHandle,
            ) -> Result<TensorHandle<'a>> {
                let status = crate::Status::new();

                // Define Op

                let op_name = "Add";
                let mut op = Op::new(ctx, op_name)?;

                // Required input arguments
                op.add_input(&x)?;
                op.add_input(&y)?;

                // Attributes
                if let ::std::option::Option::Some(value) = &self.T {
                    let attr_name = "T";
                    op.set_attr_type(attr_name, *value)?;
                }

                // Execute Op
                let mut num_output = 1;
                let mut res = [std::ptr::null_mut::<tensorflow_sys::TFE_TensorHandle>(); 1];
                unsafe {
                    tf::TFE_Execute(
                        op.inner,
                        res.as_mut_ptr(),
                        (&mut num_output) as *mut i32,
                        status.inner,
                    );
                };
                if status.is_ok() {
                    let ret = TensorHandle::from_tensor_handle(ctx, res[0]);
                    return Ok(ret);
                }
                Err(status)
            }
        }

        /// add with default options.
        pub fn add<'a>(
            ctx: &'a crate::eager::Context,
            x: &TensorHandle,
            y: &TensorHandle,
        ) -> Result<TensorHandle<'a>> {
            let op = Add::new();
            op.call(ctx, x, y)
        }
    }

    #[test]
    fn test_add() {
        use raw_ops::add;

        let ctx = Context::new(ContextOptions::new()).unwrap();
        let x = Tensor::new(&[2, 2]).with_values(&[1i32, 2, 3, 4]).unwrap();
        let h_x = TensorHandle::new(&ctx, &x).unwrap();
        let h_y = h_x.copy_sharing_tensor().unwrap();
        let h_z = add(&ctx, &h_x, &h_y).unwrap();
        let z: crate::Tensor<i32> = h_z.resolve().unwrap();
        assert_eq!(&z[..], &[2i32, 4, 6, 8]);
    }
}
<|endoftext|>