<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![old_impl_check]

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::hash_state::DefaultState;
use rand::Rng;
use std::hash::{Hash, Hasher, SipHasher};
use std::iter::repeat;
use rand;
use std::slice::Iter;
use std::default::Default;

#[cfg(test)]
use std::cell::Cell;

pub struct HashCache<K, V> {
    entries: HashMap<K, V, DefaultState<SipHasher>>,
}

impl<K, V> HashCache<K,V>
    where K: Clone + PartialEq + Eq + Hash,
          V: Clone,
{
    pub fn new() -> HashCache<K,V> {
        HashCache {
          entries: HashMap::with_hash_state(<DefaultState<SipHasher> as Default>::default()),
        }
    }

    pub fn insert(&mut self, key: K, value: V) {
        self.entries.insert(key, value);
    }

    pub fn find(&self, key: &K) -> Option<V> {
        match self.entries.get(key) {
            Some(v) => Some(v.clone()),
            None => None,
        }
    }

    pub fn find_or_create<F>(&mut self, key: &K, blk: F) -> V where F: Fn(&K) -> V {
        match self.entries.entry(key.clone()) {
            Occupied(occupied) => {
                (*occupied.get()).clone()
            }
            Vacant(vacant) => {
                (*vacant.insert(blk(key))).clone()
            }
        }
    }

    pub fn evict_all(&mut self) {
        self.entries.clear();
    }
}

#[test]
fn test_hashcache() {
    let mut cache: HashCache<usize, Cell<&str>> = HashCache::new();

    cache.insert(1, Cell::new("one"));
    assert!(cache.find(&1).is_some());
    assert!(cache.find(&2).is_none());

    cache.find_or_create(&2, |_v| { Cell::new("two") });
    assert!(cache.find(&1).is_some());
    assert!(cache.find(&2).is_some());
}

pub struct LRUCache<K, V> {
    entries: Vec<(K, V)>,
    cache_size: usize,
}

impl<K: Clone + PartialEq, V: Clone> LRUCache<K,V> {
    pub fn new(size: usize) -> LRUCache<K, V> {
        LRUCache {
          entries: vec!(),
          cache_size: size,
        }
    }

    #[inline]
    pub fn touch(&mut self, pos: usize) -> V {
        let last_index = self.entries.len() - 1;
        if pos != last_index {
            let entry = self.entries.remove(pos);
            self.entries.push(entry);
        }
        self.entries[last_index].1.clone()
    }

    pub fn iter<'a>(&'a self) -> Iter<'a,(K,V)> {
        self.entries.iter()
    }

    pub fn insert(&mut self, key: K, val: V) {
        if self.entries.len() == self.cache_size {
            self.entries.remove(0);
        }
        self.entries.push((key, val));
    }

    pub fn find(&mut self, key: &K) -> Option<V> {
        match self.entries.iter().position(|&(ref k, _)| key == k) {
            Some(pos) => Some(self.touch(pos)),
            None      => None,
        }
    }

    pub fn find_or_create<F>(&mut self, key: &K, blk: F) -> V where F: Fn(&K) -> V {
        match self.entries.iter().position(|&(ref k, _)| *k == *key) {
            Some(pos) => self.touch(pos),
            None => {
                let val = blk(key);
                self.insert(key.clone(), val.clone());
                val
            }
        }
    }

    pub fn evict_all(&mut self) {
        self.entries.clear();
    }
}

pub struct SimpleHashCache<K,V> {
    entries: Vec<Option<(K,V)>>,
    k0: u64,
    k1: u64,
}

impl<K:Clone+Eq+Hash,V:Clone> SimpleHashCache<K,V> {
    pub fn new(cache_size: usize) -> SimpleHashCache<K,V> {
        let mut r = rand::thread_rng();
        SimpleHashCache {
            entries: repeat(None).take(cache_size).collect(),
            k0: r.gen(),
            k1: r.gen(),
        }
    }

    #[inline]
    fn to_bucket(&self, h: usize) -> usize {
        h % self.entries.len()
    }

    #[inline]
    fn bucket_for_key<Q:Hash>(&self, key: &Q) -> usize {
        let mut hasher = SipHasher::new_with_keys(self.k0, self.k1);
        key.hash(&mut hasher);
        self.to_bucket(hasher.finish() as usize)
    }

    pub fn insert(&mut self, key: K, value: V) {
        let bucket_index = self.bucket_for_key(&key);
        self.entries[bucket_index] = Some((key, value));
    }

    pub fn find<Q>(&self, key: &Q) -> Option<V> where Q: PartialEq<K> + Hash + Eq {
        let bucket_index = self.bucket_for_key(key);
        match self.entries[bucket_index] {
            Some((ref existing_key, ref value)) if key == existing_key => Some((*value).clone()),
            _ => None,
        }
    }

    pub fn find_or_create<F>(&mut self, key: &K, blk: F) -> V where F: Fn(&K) -> V {
        match self.find(key) {
            Some(value) => return value,
            None => {}
        }
        let value = blk(key);
        self.insert((*key).clone(), value.clone());
        value
    }

    pub fn evict_all(&mut self) {
        for slot in self.entries.iter_mut() {
            *slot = None
        }
    }
}

#[test]
fn test_lru_cache() {
    let one = Cell::new("one");
    let two = Cell::new("two");
    let three = Cell::new("three");
    let four = Cell::new("four");

    // Test normal insertion.
    let mut cache: LRUCache<uint,Cell<&str>> = LRUCache::new(2); // (_, _) (cache is empty)
    cache.insert(1, one);    // (1, _)
    cache.insert(2, two);    // (1, 2)
    cache.insert(3, three);  // (2, 3)

    assert!(cache.find(&1).is_none());  // (2, 3) (no change)
    assert!(cache.find(&3).is_some());  // (2, 3)
    assert!(cache.find(&2).is_some());  // (3, 2)

    // Test that LRU works (this insertion should replace 3, not 2).
    cache.insert(4, four); // (2, 4)

    assert!(cache.find(&1).is_none());  // (2, 4) (no change)
    assert!(cache.find(&2).is_some());  // (4, 2)
    assert!(cache.find(&3).is_none());  // (4, 2) (no change)
    assert!(cache.find(&4).is_some());  // (2, 4) (no change)

    // Test find_or_create.
    cache.find_or_create(&1, |_| { Cell::new("one") }); // (4, 1)

    assert!(cache.find(&1).is_some()); // (4, 1) (no change)
    assert!(cache.find(&2).is_none()); // (4, 1) (no change)
    assert!(cache.find(&3).is_none()); // (4, 1) (no change)
    assert!(cache.find(&4).is_some()); // (1, 4)
}
<commit_msg>auto merge of #5269 : Manishearth/servo/old_impl, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::hash_state::DefaultState;
use rand::Rng;
use std::hash::{Hash, Hasher, SipHasher};
use std::iter::repeat;
use rand;
use std::slice::Iter;
use std::default::Default;

#[cfg(test)]
use std::cell::Cell;

pub struct HashCache<K, V> {
    entries: HashMap<K, V, DefaultState<SipHasher>>,
}

impl<K, V> HashCache<K,V>
    where K: Clone + PartialEq + Eq + Hash,
          V: Clone,
{
    pub fn new() -> HashCache<K,V> {
        HashCache {
          entries: HashMap::with_hash_state(<DefaultState<SipHasher> as Default>::default()),
        }
    }

    pub fn insert(&mut self, key: K, value: V) {
        self.entries.insert(key, value);
    }

    pub fn find(&self, key: &K) -> Option<V> {
        match self.entries.get(key) {
            Some(v) => Some(v.clone()),
            None => None,
        }
    }

    pub fn find_or_create<F>(&mut self, key: &K, blk: F) -> V where F: Fn(&K) -> V {
        match self.entries.entry(key.clone()) {
            Occupied(occupied) => {
                (*occupied.get()).clone()
            }
            Vacant(vacant) => {
                (*vacant.insert(blk(key))).clone()
            }
        }
    }

    pub fn evict_all(&mut self) {
        self.entries.clear();
    }
}

#[test]
fn test_hashcache() {
    let mut cache: HashCache<usize, Cell<&str>> = HashCache::new();

    cache.insert(1, Cell::new("one"));
    assert!(cache.find(&1).is_some());
    assert!(cache.find(&2).is_none());

    cache.find_or_create(&2, |_v| { Cell::new("two") });
    assert!(cache.find(&1).is_some());
    assert!(cache.find(&2).is_some());
}

pub struct LRUCache<K, V> {
    entries: Vec<(K, V)>,
    cache_size: usize,
}

impl<K: Clone + PartialEq, V: Clone> LRUCache<K,V> {
    pub fn new(size: usize) -> LRUCache<K, V> {
        LRUCache {
          entries: vec!(),
          cache_size: size,
        }
    }

    #[inline]
    pub fn touch(&mut self, pos: usize) -> V {
        let last_index = self.entries.len() - 1;
        if pos != last_index {
            let entry = self.entries.remove(pos);
            self.entries.push(entry);
        }
        self.entries[last_index].1.clone()
    }

    pub fn iter<'a>(&'a self) -> Iter<'a,(K,V)> {
        self.entries.iter()
    }

    pub fn insert(&mut self, key: K, val: V) {
        if self.entries.len() == self.cache_size {
            self.entries.remove(0);
        }
        self.entries.push((key, val));
    }

    pub fn find(&mut self, key: &K) -> Option<V> {
        match self.entries.iter().position(|&(ref k, _)| key == k) {
            Some(pos) => Some(self.touch(pos)),
            None      => None,
        }
    }

    pub fn find_or_create<F>(&mut self, key: &K, blk: F) -> V where F: Fn(&K) -> V {
        match self.entries.iter().position(|&(ref k, _)| *k == *key) {
            Some(pos) => self.touch(pos),
            None => {
                let val = blk(key);
                self.insert(key.clone(), val.clone());
                val
            }
        }
    }

    pub fn evict_all(&mut self) {
        self.entries.clear();
    }
}

pub struct SimpleHashCache<K,V> {
    entries: Vec<Option<(K,V)>>,
    k0: u64,
    k1: u64,
}

impl<K:Clone+Eq+Hash,V:Clone> SimpleHashCache<K,V> {
    pub fn new(cache_size: usize) -> SimpleHashCache<K,V> {
        let mut r = rand::thread_rng();
        SimpleHashCache {
            entries: repeat(None).take(cache_size).collect(),
            k0: r.gen(),
            k1: r.gen(),
        }
    }

    #[inline]
    fn to_bucket(&self, h: usize) -> usize {
        h % self.entries.len()
    }

    #[inline]
    fn bucket_for_key<Q:Hash>(&self, key: &Q) -> usize {
        let mut hasher = SipHasher::new_with_keys(self.k0, self.k1);
        key.hash(&mut hasher);
        self.to_bucket(hasher.finish() as usize)
    }

    pub fn insert(&mut self, key: K, value: V) {
        let bucket_index = self.bucket_for_key(&key);
        self.entries[bucket_index] = Some((key, value));
    }

    pub fn find<Q>(&self, key: &Q) -> Option<V> where Q: PartialEq<K> + Hash + Eq {
        let bucket_index = self.bucket_for_key(key);
        match self.entries[bucket_index] {
            Some((ref existing_key, ref value)) if key == existing_key => Some((*value).clone()),
            _ => None,
        }
    }

    pub fn find_or_create<F>(&mut self, key: &K, blk: F) -> V where F: Fn(&K) -> V {
        match self.find(key) {
            Some(value) => return value,
            None => {}
        }
        let value = blk(key);
        self.insert((*key).clone(), value.clone());
        value
    }

    pub fn evict_all(&mut self) {
        for slot in self.entries.iter_mut() {
            *slot = None
        }
    }
}

#[test]
fn test_lru_cache() {
    let one = Cell::new("one");
    let two = Cell::new("two");
    let three = Cell::new("three");
    let four = Cell::new("four");

    // Test normal insertion.
    let mut cache: LRUCache<uint,Cell<&str>> = LRUCache::new(2); // (_, _) (cache is empty)
    cache.insert(1, one);    // (1, _)
    cache.insert(2, two);    // (1, 2)
    cache.insert(3, three);  // (2, 3)

    assert!(cache.find(&1).is_none());  // (2, 3) (no change)
    assert!(cache.find(&3).is_some());  // (2, 3)
    assert!(cache.find(&2).is_some());  // (3, 2)

    // Test that LRU works (this insertion should replace 3, not 2).
    cache.insert(4, four); // (2, 4)

    assert!(cache.find(&1).is_none());  // (2, 4) (no change)
    assert!(cache.find(&2).is_some());  // (4, 2)
    assert!(cache.find(&3).is_none());  // (4, 2) (no change)
    assert!(cache.find(&4).is_some());  // (2, 4) (no change)

    // Test find_or_create.
    cache.find_or_create(&1, |_| { Cell::new("one") }); // (4, 1)

    assert!(cache.find(&1).is_some()); // (4, 1) (no change)
    assert!(cache.find(&2).is_none()); // (4, 1) (no change)
    assert!(cache.find(&3).is_none()); // (4, 1) (no change)
    assert!(cache.find(&4).is_some()); // (1, 4)
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use super::{ElfResult, ElfWord, Section, section};

use core::{fmt, mem};

/// An ELF file header
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Header<W: ElfWord> {
    pub ident: Ident
  , elftype: TypeRepr
  , pub machine: Machine
  , /// Program entry point
    pub entry_point: W
  , /// Offset for start of program headers
    pub ph_offset: W
  , /// Offset for start of section headers
    pub sh_offset: W
  , pub flags: u32
  , pub header_size: u16
  , pub ph_entry_size: u16
  , pub ph_count: u16
  , pub sh_entry_size: u16
  , pub sh_count: u16
  , pub sh_str_idx: u16
}

impl<W> Header<W> where W: ElfWord {

    /// Attempt to extract an ELF file header from a slice of bytes.
    pub fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Header<W>> {
        if input.len() < mem::size_of::<Header<W>>() {
            Err("Input too short to extract ELF header")
        } else {
            unsafe { Ok(&super::extract_from_slice::<Header<W>>(input, 0, 1)[0]) }
        }
    }

    #[inline]
    pub fn get_type(&self) -> Type { self.elftype.as_type() }

}

impl Header<u64> {

    /// Attempt to extract a section header from a slice of bytes.
    pub fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>
    {
        if idx < section::SHN_LORESERVE {
            Err("Cannot parse reserved section.")
        } else {
            let start: u64// start offset for section
                = self.sh_offset + idx as u64 * self.sh_entry_size as u64;
            let end: u64 // end offset for section
                = start + self.sh_entry_size as u64;
            let raw
                = &input[start as usize .. end as usize];

            match self.ident.class {
                Class::None => Err("Invalid ELF class (ELFCLASSNONE).")
              , Class::Elf32 => Err("Cannot parse 32-bit section from 64-bit \
                                     ELF file.")
              , Class::Elf64 => unsafe {
                    Ok(mem::transmute(raw as *const [u8] as *const u8 as *const Section))
                }
            }
        }
    }

}

impl Header<u32> {

    /// Attempt to extract a section header from a slice of bytes.
    pub fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>
    {
        if idx < section::SHN_LORESERVE {
            Err("Cannot parse reserved section.")
        } else {
            let start: u32// start offset for section
                = self.sh_offset + idx as u32 * self.sh_entry_size as u32;
            let end: u32 // end offset for section
                = start + self.sh_entry_size as u32;
            let raw
                = &input[start as usize .. end as usize];

            match self.ident.class {
                Class::None => Err("Invalid ELF class (ELFCLASSNONE).")
              , Class::Elf32 => unsafe {
                    Ok(mem::transmute(raw as *const [u8] as *const u8 as *const Section))
                }
              , Class::Elf64 => Err("Cannot parse 64-bit section from 32-bit \
                                     ELF file.")
            }
        }
    }

}

/// ELF header magic
pub const MAGIC: Magic = [0x7f, b'E', b'L', b'F'];

/// Type of header magic
pub type Magic = [u8; 4];

/// ELF identifier (`e_ident` in the ELF standard)
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Ident {
    /// ELF magic numbers. Must be [0x7, E, L, F]
    pub magic: Magic
  , /// ELF file class (32- or 64-bit)
    pub class: Class
  , /// ELF data encoding (big- or little-endian)
    pub data: DataEncoding
  , /// ELF file version
    pub version: Version
  , pub abi: OsAbi
  , /// ABI version (often this is just padding)
    pub abi_version: u8
  , _padding: [u8; 7]
}

impl Ident {
    #[inline] pub fn check_magic(&self) -> bool { self.magic == MAGIC }
}

/// Identifies the class of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Class {
    /// Invalid ELF class file (`ELFCLASSNONE` in the standard)
    None  = 0
  , /// 32-bit ELF file (`ELFCLASS32` in the standard)
    Elf32 = 1
  , /// 64-bit ELF file (`ELFCLASS64` in the standard)
    Elf64 = 2
}

/// Identifies the data encoding of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum DataEncoding {
    /// Invalid data encoding (`ELFDATANONE` in the standard)
    None  = 0
  , /// Twos-complement little-endian data encoding
    /// (`ELFDATA2LSB` in the standard)
    LittleEndian = 1
  , /// Twos-complement big-endian data encoding
    /// (`ELFDATA2MSB` in the standard)
    BigEndian = 2
}

/// Operating system ABI
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
pub enum OsAbi { /// Ox00 also represents "none"
                 SystemV = 0x00
               , HpUx    = 0x01
               , NetBsd  = 0x02
               , Linux   = 0x03
               , Solaris = 0x06
               , Aix     = 0x07
               , Irix    = 0x08
               , FreeBsd = 0x09
               , OpenBsd = 0x0C
               , OpenVms = 0x0D
               }

/// Identifies the version of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Version { None = 0, Current = 1 }

#[derive(Clone, Copy, PartialEq)]
struct TypeRepr(u16);

impl TypeRepr {
    pub fn as_type(&self) -> Type {
        match self.0 {
            0 => Type::None
          , 1 => Type::Relocatable
          , 2 => Type::Executable
          , 3 => Type::SharedObject
          , 4 => Type::Core
          , anything => Type::Other(anything)
        }
    }
}

impl fmt::Debug for TypeRepr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_type().fmt(f)
    }
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Type { None
              , Relocatable
              , Executable
              , SharedObject
              , Core
              , Other(u16)
              }

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u16)]
pub enum Machine { None    = 0
                 , Sparc   = 0x02
                 , X86     = 0x03
                 , Mips    = 0x08
                 , PowerPc = 0x14
                 , Arm     = 0x28
                 , SuperH  = 0x2A
                 , Ia64    = 0x32
                 , X86_64  = 0x3E
                 , AArch64 = 0xB7
                 }
<commit_msg>[elf] replace some mem::transmutes with raw pointer deref according to https://doc.rust-lang.org/stable/book/raw-pointers.html#references-and-raw-pointers, this is better style<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use super::{ElfResult, ElfWord, Section, section};

use core::{fmt, mem};

/// An ELF file header
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Header<W: ElfWord> {
    pub ident: Ident
  , elftype: TypeRepr
  , pub machine: Machine
  , /// Program entry point
    pub entry_point: W
  , /// Offset for start of program headers
    pub ph_offset: W
  , /// Offset for start of section headers
    pub sh_offset: W
  , pub flags: u32
  , pub header_size: u16
  , pub ph_entry_size: u16
  , pub ph_count: u16
  , pub sh_entry_size: u16
  , pub sh_count: u16
  , pub sh_str_idx: u16
}

impl<W> Header<W> where W: ElfWord {

    /// Attempt to extract an ELF file header from a slice of bytes.
    pub fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Header<W>> {
        if input.len() < mem::size_of::<Header<W>>() {
            Err("Input too short to extract ELF header")
        } else {
            unsafe { Ok(&super::extract_from_slice::<Header<W>>(input, 0, 1)[0]) }
        }
    }

    #[inline]
    pub fn get_type(&self) -> Type { self.elftype.as_type() }

}

impl Header<u64> {

    /// Attempt to extract a section header from a slice of bytes.
    pub fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>
    {
        if idx < section::SHN_LORESERVE {
            Err("Cannot parse reserved section.")
        } else {
            let start: u64// start offset for section
                = self.sh_offset + idx as u64 * self.sh_entry_size as u64;
            let end: u64 // end offset for section
                = start + self.sh_entry_size as u64;
            let raw
                = &input[start as usize .. end as usize];

            match self.ident.class {
                Class::None => Err("Invalid ELF class (ELFCLASSNONE).")
              , Class::Elf32 => Err("Cannot parse 32-bit section from 64-bit \
                                     ELF file.")
              , Class::Elf64 => unsafe {
                    Ok(&*(raw as *const [u8] as *const u8 as *const Section))
                }
            }
        }
    }

}

impl Header<u32> {

    /// Attempt to extract a section header from a slice of bytes.
    pub fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>
    {
        if idx < section::SHN_LORESERVE {
            Err("Cannot parse reserved section.")
        } else {
            let start: u32// start offset for section
                = self.sh_offset + idx as u32 * self.sh_entry_size as u32;
            let end: u32 // end offset for section
                = start + self.sh_entry_size as u32;
            let raw
                = &input[start as usize .. end as usize];

            match self.ident.class {
                Class::None => Err("Invalid ELF class (ELFCLASSNONE).")
              , Class::Elf32 => unsafe {
                    Ok(&*(raw as *const [u8] as *const u8 as *const Section))
                }
              , Class::Elf64 => Err("Cannot parse 64-bit section from 32-bit \
                                     ELF file.")
            }
        }
    }

}

/// ELF header magic
pub const MAGIC: Magic = [0x7f, b'E', b'L', b'F'];

/// Type of header magic
pub type Magic = [u8; 4];

/// ELF identifier (`e_ident` in the ELF standard)
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Ident {
    /// ELF magic numbers. Must be [0x7, E, L, F]
    pub magic: Magic
  , /// ELF file class (32- or 64-bit)
    pub class: Class
  , /// ELF data encoding (big- or little-endian)
    pub data: DataEncoding
  , /// ELF file version
    pub version: Version
  , pub abi: OsAbi
  , /// ABI version (often this is just padding)
    pub abi_version: u8
  , _padding: [u8; 7]
}

impl Ident {
    #[inline] pub fn check_magic(&self) -> bool { self.magic == MAGIC }
}

/// Identifies the class of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Class {
    /// Invalid ELF class file (`ELFCLASSNONE` in the standard)
    None  = 0
  , /// 32-bit ELF file (`ELFCLASS32` in the standard)
    Elf32 = 1
  , /// 64-bit ELF file (`ELFCLASS64` in the standard)
    Elf64 = 2
}

/// Identifies the data encoding of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum DataEncoding {
    /// Invalid data encoding (`ELFDATANONE` in the standard)
    None  = 0
  , /// Twos-complement little-endian data encoding
    /// (`ELFDATA2LSB` in the standard)
    LittleEndian = 1
  , /// Twos-complement big-endian data encoding
    /// (`ELFDATA2MSB` in the standard)
    BigEndian = 2
}

/// Operating system ABI
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
pub enum OsAbi { /// Ox00 also represents "none"
                 SystemV = 0x00
               , HpUx    = 0x01
               , NetBsd  = 0x02
               , Linux   = 0x03
               , Solaris = 0x06
               , Aix     = 0x07
               , Irix    = 0x08
               , FreeBsd = 0x09
               , OpenBsd = 0x0C
               , OpenVms = 0x0D
               }

/// Identifies the version of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Version { None = 0, Current = 1 }

#[derive(Clone, Copy, PartialEq)]
struct TypeRepr(u16);

impl TypeRepr {
    pub fn as_type(&self) -> Type {
        match self.0 {
            0 => Type::None
          , 1 => Type::Relocatable
          , 2 => Type::Executable
          , 3 => Type::SharedObject
          , 4 => Type::Core
          , anything => Type::Other(anything)
        }
    }
}

impl fmt::Debug for TypeRepr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_type().fmt(f)
    }
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Type { None
              , Relocatable
              , Executable
              , SharedObject
              , Core
              , Other(u16)
              }

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u16)]
pub enum Machine { None    = 0
                 , Sparc   = 0x02
                 , X86     = 0x03
                 , Mips    = 0x08
                 , PowerPc = 0x14
                 , Arm     = 0x28
                 , SuperH  = 0x2A
                 , Ia64    = 0x32
                 , X86_64  = 0x3E
                 , AArch64 = 0xB7
                 }
<|endoftext|>


<commit_before>//! High level API to detect collisions in large, complex scenes.

pub use self::collision_object::{CollisionObject, CollisionObjectHandle, CollisionObjectSlab,
                                 CollisionObjects, GeometricQueryType};
pub use self::collision_groups::{CollisionGroups, CollisionGroupsPairFilter};
pub use self::collision_world::{BroadPhaseObject, CollisionWorld, NarrowPhaseObject};

use na::{Isometry2, Isometry3, Point2, Point3};

mod collision_object;
mod collision_groups;
mod collision_world;

/// A 3D collision world associating collision objects to user-defined data of type `T`.
pub type CollisionWorld3<N, T> = CollisionWorld<Point3<N>, Isometry3<N>, T>;
/// A 2D collision world associating collision objects to user-defined data of type `T`.
pub type CollisionWorld2<N, T> = CollisionWorld<Point2<N>, Isometry2<N>, T>;

/// A 3D collision object with user-defined data of type `T`.
pub type CollisionObject3<N, T> = CollisionObject<Point3<N>, Isometry3<N>, T>;
/// A 2D collision object with user-defined data of type `T`.
pub type CollisionObject2<N, T> = CollisionObject<Point2<N>, Isometry2<N>, T>;
<commit_msg>expose InterferencesWith* publicly<commit_after>//! High level API to detect collisions in large, complex scenes.

pub use self::collision_object::{CollisionObject, CollisionObjectHandle, CollisionObjectSlab,
                                 CollisionObjects, GeometricQueryType};
pub use self::collision_groups::{CollisionGroups, CollisionGroupsPairFilter};
pub use self::collision_world::{BroadPhaseObject, CollisionWorld, NarrowPhaseObject,
                                InterferencesWithAABB, InterferencesWithPoint,
                                InterferencesWithRay};

use na::{Isometry2, Isometry3, Point2, Point3};

mod collision_object;
mod collision_groups;
mod collision_world;

/// A 3D collision world associating collision objects to user-defined data of type `T`.
pub type CollisionWorld3<N, T> = CollisionWorld<Point3<N>, Isometry3<N>, T>;
/// A 2D collision world associating collision objects to user-defined data of type `T`.
pub type CollisionWorld2<N, T> = CollisionWorld<Point2<N>, Isometry2<N>, T>;

/// A 3D collision object with user-defined data of type `T`.
pub type CollisionObject3<N, T> = CollisionObject<Point3<N>, Isometry3<N>, T>;
/// A 2D collision object with user-defined data of type `T`.
pub type CollisionObject2<N, T> = CollisionObject<Point2<N>, Isometry2<N>, T>;
<|endoftext|>


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

use std::sync::Arc;
use core::{core, global};
use core::core::hash::Hashed;
use core::core::target::Difficulty;
use chain;
use util::secp::pedersen;
use rest::*;
use util;

/// The state of the current fork tip
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Tip {
	/// Height of the tip (max height of the fork)
	pub height: u64,
	// Last block pushed to the fork
	pub last_block_pushed: String,
	// Block previous to last
	pub prev_block_to_last: String,
	// Total difficulty accumulated on that fork
	pub total_difficulty: u64,
}

impl Tip {
	pub fn from_tip(tip: chain::Tip) -> Tip {
		Tip {
			height: tip.height,
			last_block_pushed: util::to_hex(tip.last_block_h.to_vec()),
			prev_block_to_last: util::to_hex(tip.prev_block_h.to_vec()),
			total_difficulty: tip.total_difficulty.into_num(),
		}
	}
}

/// Sumtrees
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SumTrees {
	/// UTXO Root Hash
	pub utxo_root_hash: String,
	// UTXO Root Sum
	pub utxo_root_sum: String,
	// Rangeproof root hash
	pub range_proof_root_hash: String,
	// Kernel set root hash
	pub kernel_root_hash: String,
}

impl SumTrees {
	pub fn from_head(head: Arc<chain::Chain>) -> SumTrees {
		let roots = head.get_sumtree_roots();
		SumTrees {
			utxo_root_hash: util::to_hex(roots.0.hash.to_vec()),
			utxo_root_sum: util::to_hex(roots.0.sum.commit.0.to_vec()),
			range_proof_root_hash: util::to_hex(roots.1.hash.to_vec()),
			kernel_root_hash: util::to_hex(roots.2.hash.to_vec()),
		}
	}
}

/// Wrapper around a list of sumtree nodes, so it can be
/// presented properly via json
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SumTreeNode {
	// The hash
	pub hash: String,
	// Output (if included)
	pub output: Option<OutputPrintable>,
}

impl SumTreeNode {
	pub fn get_last_n_utxo(chain: Arc<chain::Chain>, distance: u64) -> Vec<SumTreeNode> {
		let mut return_vec = Vec::new();
		let last_n = chain.get_last_n_utxo(distance);
		for elem_output in last_n {
			let header = chain
				.get_block_header_by_output_commit(&elem_output.1.commit)
				.map_err(|_| Error::NotFound);
			// Need to call further method to check if output is spent
			let mut output = OutputPrintable::from_output(&elem_output.1, &header.unwrap(),true);
			if let Ok(_) = chain.get_unspent(&elem_output.1.commit) {
				output.spent = false;
			}
			return_vec.push(SumTreeNode {
				hash: util::to_hex(elem_output.0.to_vec()),
				output: Some(output),
			});
		}
		return_vec
	}

	pub fn get_last_n_rangeproof(head: Arc<chain::Chain>, distance: u64) -> Vec<SumTreeNode> {
		let mut return_vec = Vec::new();
		let last_n = head.get_last_n_rangeproof(distance);
		for elem in last_n {
			return_vec.push(SumTreeNode {
				hash: util::to_hex(elem.hash.to_vec()),
				output: None,
			});
		}
		return_vec
	}

	pub fn get_last_n_kernel(head: Arc<chain::Chain>, distance: u64) -> Vec<SumTreeNode> {
		let mut return_vec = Vec::new();
		let last_n = head.get_last_n_kernel(distance);
		for elem in last_n {
			return_vec.push(SumTreeNode {
				hash: util::to_hex(elem.hash.to_vec()),
				output: None,
			});
		}
		return_vec
	}
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum OutputType {
	Coinbase,
	Transaction,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Output {
	/// The type of output Coinbase|Transaction
	pub output_type: OutputType,
	/// The homomorphic commitment representing the output's amount
	pub commit: pedersen::Commitment,
	/// switch commit hash
	pub switch_commit_hash: Option<core::SwitchCommitHash>,
	/// A proof that the commitment is in the right range
	pub proof: Option<pedersen::RangeProof>,
	/// The height of the block creating this output
	pub height: u64,
	/// The lock height (earliest block this output can be spent)
	pub lock_height: u64,
}

impl Output {
	pub fn from_output(output: &core::Output, block_header: &core::BlockHeader,
		include_proof:bool, include_switch: bool) -> Output {
		let (output_type, lock_height) = match output.features {
			x if x.contains(core::transaction::COINBASE_OUTPUT) => (
				OutputType::Coinbase,
				block_header.height + global::coinbase_maturity(),
			),
			_ => (OutputType::Transaction, 0),
		};

		Output {
			output_type: output_type,
			commit: output.commit,
			switch_commit_hash: match include_switch {
				true => Some(output.switch_commit_hash),
				false => None,
			},
			proof: match include_proof {
				true => Some(output.proof),
				false => None,
			},
			height: block_header.height,
			lock_height: lock_height,
		}
	}
}

// As above, except formatted a bit better for human viewing
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct OutputPrintable {
	/// The type of output Coinbase|Transaction
	pub output_type: OutputType,
	/// The homomorphic commitment representing the output's amount (as hex
	/// string)
	pub commit: String,
	/// switch commit hash
	pub switch_commit_hash: String,
	/// The height of the block creating this output
	pub height: u64,
	/// The lock height (earliest block this output can be spent)
	pub lock_height: u64,
	/// Whether the output has been spent
	pub spent: bool,
	/// Rangeproof hash  (as hex string)
	pub proof_hash: Option<String>,
}

impl OutputPrintable {
	pub fn from_output(output: &core::Output, block_header: &core::BlockHeader, include_proof_hash:bool) -> OutputPrintable {
		let (output_type, lock_height) = match output.features {
			x if x.contains(core::transaction::COINBASE_OUTPUT) => (
				OutputType::Coinbase,
				block_header.height + global::coinbase_maturity(),
			),
			_ => (OutputType::Transaction, 0),
		};
		OutputPrintable {
			output_type: output_type,
			commit: util::to_hex(output.commit.0.to_vec()),
			switch_commit_hash: util::to_hex(output.switch_commit_hash.hash.to_vec()),
			height: block_header.height,
			lock_height: lock_height,
			spent: true,
			proof_hash: match include_proof_hash {
				true => Some(util::to_hex(output.proof.hash().to_vec())),
				false => None,
			}
		}
	}
}

// As above, except just the info needed for wallet reconstruction
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct OutputSwitch {
	/// the commit
	pub commit: String,
	/// switch commit hash
	pub switch_commit_hash: [u8; core::SWITCH_COMMIT_HASH_SIZE],
	/// The height of the block creating this output
	pub height: u64,
}

impl OutputSwitch {
	pub fn from_output(output: &core::Output, block_header: &core::BlockHeader) -> OutputSwitch {
		OutputSwitch {
			commit: util::to_hex(output.commit.0.to_vec()),
			switch_commit_hash: output.switch_commit_hash.hash,
			height: block_header.height,
		}
	}
}

// Printable representation of a block
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TxKernelPrintable {
	pub features: String,
	pub fee: u64,
	pub lock_height: u64,
	pub excess: String,
	pub excess_sig: String,
}

impl TxKernelPrintable {
	pub fn from_txkernel(k: &core::TxKernel) -> TxKernelPrintable {
		TxKernelPrintable {
			features: format!("{:?}", k.features),
			fee: k.fee,
			lock_height: k.lock_height,
			excess: util::to_hex(k.excess.0.to_vec()),
			excess_sig: util::to_hex(k.excess_sig.to_vec())
		}
	}
}

// Just the information required for wallet reconstruction
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BlockHeaderInfo {
	// Hash
	pub hash: String,
	/// Version of the block
	pub version: u16,
	/// Height of this block since the genesis block (height 0)
	pub height: u64,
	/// Hash of the block previous to this in the chain.
	pub previous: String,
	/// rfc3339 timestamp at which the block was built.
	pub timestamp: String,
	/// Merklish root of all the commitments in the UTXO set
	pub utxo_root: String,
	/// Merklish root of all range proofs in the UTXO set
	pub range_proof_root: String,
	/// Merklish root of all transaction kernels in the UTXO set
	pub kernel_root: String,
	/// Nonce increment used to mine this block.
	pub nonce: u64,
	/// Difficulty used to mine the block.
	pub difficulty: Difficulty,
	/// Total accumulated difficulty since genesis block
	pub total_difficulty: Difficulty,
}

impl BlockHeaderInfo {
	pub fn from_header(h: &core::BlockHeader) -> BlockHeaderInfo {
		BlockHeaderInfo {
			hash: util::to_hex(h.hash().to_vec()),
			version: h.version,
			height: h.height,
			previous: util::to_hex(h.previous.to_vec()),
			timestamp: h.timestamp.rfc3339().to_string(),
			utxo_root: util::to_hex(h.utxo_root.to_vec()),
			range_proof_root: util::to_hex(h.range_proof_root.to_vec()),
			kernel_root: util::to_hex(h.kernel_root.to_vec()),
			nonce: h.nonce,
			difficulty: h.difficulty.clone(),
			total_difficulty: h.total_difficulty.clone(),
		}
	}
}

// Printable representation of a block
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BlockPrintable {
	/// The block header
	pub header: BlockHeaderInfo,
	// Input transactions
	pub inputs: Vec<String>,
	/// A printable version of the outputs
	pub outputs: Vec<OutputPrintable>,
	/// A printable version of the transaction kernels
	pub kernels: Vec<TxKernelPrintable>,
}

impl BlockPrintable {
	pub fn from_block(block: &core::Block) -> BlockPrintable {
		let inputs = block.inputs
			.iter()
			.map(|input| util::to_hex((input.0).0.to_vec()))
			.collect();
		let outputs = block.outputs
			.iter()
			.map(|output| OutputPrintable::from_output(output, &block.header, true))
			.collect();
		let kernels = block.kernels
			.iter()
			.map(|kernel| TxKernelPrintable::from_txkernel(kernel))
			.collect();
		BlockPrintable {
			header: BlockHeaderInfo::from_header(&block.header),
			inputs: inputs,
			outputs: outputs,
			kernels: kernels,
		}
	}
}

// For wallet reconstruction, include the header info along with the
// transactions in the block
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BlockOutputs {
	/// The block header
	pub header: BlockHeaderInfo,
	/// A printable version of the outputs
	pub outputs: Vec<OutputSwitch>,
}

#[derive(Serialize, Deserialize)]
pub struct PoolInfo {
	/// Size of the pool
	pub pool_size: usize,
	/// Size of orphans
	pub orphans_size: usize,
	/// Total size of pool + orphans
	pub total_size: usize,
}
<commit_msg>fix to header info for wallet restore (#435)<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::sync::Arc;
use core::{core, global};
use core::core::hash::Hashed;
use chain;
use util::secp::pedersen;
use rest::*;
use util;

/// The state of the current fork tip
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Tip {
	/// Height of the tip (max height of the fork)
	pub height: u64,
	// Last block pushed to the fork
	pub last_block_pushed: String,
	// Block previous to last
	pub prev_block_to_last: String,
	// Total difficulty accumulated on that fork
	pub total_difficulty: u64,
}

impl Tip {
	pub fn from_tip(tip: chain::Tip) -> Tip {
		Tip {
			height: tip.height,
			last_block_pushed: util::to_hex(tip.last_block_h.to_vec()),
			prev_block_to_last: util::to_hex(tip.prev_block_h.to_vec()),
			total_difficulty: tip.total_difficulty.into_num(),
		}
	}
}

/// Sumtrees
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SumTrees {
	/// UTXO Root Hash
	pub utxo_root_hash: String,
	// UTXO Root Sum
	pub utxo_root_sum: String,
	// Rangeproof root hash
	pub range_proof_root_hash: String,
	// Kernel set root hash
	pub kernel_root_hash: String,
}

impl SumTrees {
	pub fn from_head(head: Arc<chain::Chain>) -> SumTrees {
		let roots = head.get_sumtree_roots();
		SumTrees {
			utxo_root_hash: util::to_hex(roots.0.hash.to_vec()),
			utxo_root_sum: util::to_hex(roots.0.sum.commit.0.to_vec()),
			range_proof_root_hash: util::to_hex(roots.1.hash.to_vec()),
			kernel_root_hash: util::to_hex(roots.2.hash.to_vec()),
		}
	}
}

/// Wrapper around a list of sumtree nodes, so it can be
/// presented properly via json
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SumTreeNode {
	// The hash
	pub hash: String,
	// Output (if included)
	pub output: Option<OutputPrintable>,
}

impl SumTreeNode {
	pub fn get_last_n_utxo(chain: Arc<chain::Chain>, distance: u64) -> Vec<SumTreeNode> {
		let mut return_vec = Vec::new();
		let last_n = chain.get_last_n_utxo(distance);
		for elem_output in last_n {
			let header = chain
				.get_block_header_by_output_commit(&elem_output.1.commit)
				.map_err(|_| Error::NotFound);
			// Need to call further method to check if output is spent
			let mut output = OutputPrintable::from_output(&elem_output.1, &header.unwrap(),true);
			if let Ok(_) = chain.get_unspent(&elem_output.1.commit) {
				output.spent = false;
			}
			return_vec.push(SumTreeNode {
				hash: util::to_hex(elem_output.0.to_vec()),
				output: Some(output),
			});
		}
		return_vec
	}

	pub fn get_last_n_rangeproof(head: Arc<chain::Chain>, distance: u64) -> Vec<SumTreeNode> {
		let mut return_vec = Vec::new();
		let last_n = head.get_last_n_rangeproof(distance);
		for elem in last_n {
			return_vec.push(SumTreeNode {
				hash: util::to_hex(elem.hash.to_vec()),
				output: None,
			});
		}
		return_vec
	}

	pub fn get_last_n_kernel(head: Arc<chain::Chain>, distance: u64) -> Vec<SumTreeNode> {
		let mut return_vec = Vec::new();
		let last_n = head.get_last_n_kernel(distance);
		for elem in last_n {
			return_vec.push(SumTreeNode {
				hash: util::to_hex(elem.hash.to_vec()),
				output: None,
			});
		}
		return_vec
	}
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum OutputType {
	Coinbase,
	Transaction,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Output {
	/// The type of output Coinbase|Transaction
	pub output_type: OutputType,
	/// The homomorphic commitment representing the output's amount
	pub commit: pedersen::Commitment,
	/// switch commit hash
	pub switch_commit_hash: Option<core::SwitchCommitHash>,
	/// A proof that the commitment is in the right range
	pub proof: Option<pedersen::RangeProof>,
	/// The height of the block creating this output
	pub height: u64,
	/// The lock height (earliest block this output can be spent)
	pub lock_height: u64,
}

impl Output {
	pub fn from_output(output: &core::Output, block_header: &core::BlockHeader,
		include_proof:bool, include_switch: bool) -> Output {
		let (output_type, lock_height) = match output.features {
			x if x.contains(core::transaction::COINBASE_OUTPUT) => (
				OutputType::Coinbase,
				block_header.height + global::coinbase_maturity(),
			),
			_ => (OutputType::Transaction, 0),
		};

		Output {
			output_type: output_type,
			commit: output.commit,
			switch_commit_hash: match include_switch {
				true => Some(output.switch_commit_hash),
				false => None,
			},
			proof: match include_proof {
				true => Some(output.proof),
				false => None,
			},
			height: block_header.height,
			lock_height: lock_height,
		}
	}
}

// As above, except formatted a bit better for human viewing
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct OutputPrintable {
	/// The type of output Coinbase|Transaction
	pub output_type: OutputType,
	/// The homomorphic commitment representing the output's amount (as hex
	/// string)
	pub commit: String,
	/// switch commit hash
	pub switch_commit_hash: String,
	/// The height of the block creating this output
	pub height: u64,
	/// The lock height (earliest block this output can be spent)
	pub lock_height: u64,
	/// Whether the output has been spent
	pub spent: bool,
	/// Rangeproof hash  (as hex string)
	pub proof_hash: Option<String>,
}

impl OutputPrintable {
	pub fn from_output(output: &core::Output, block_header: &core::BlockHeader, include_proof_hash:bool) -> OutputPrintable {
		let (output_type, lock_height) = match output.features {
			x if x.contains(core::transaction::COINBASE_OUTPUT) => (
				OutputType::Coinbase,
				block_header.height + global::coinbase_maturity(),
			),
			_ => (OutputType::Transaction, 0),
		};
		OutputPrintable {
			output_type: output_type,
			commit: util::to_hex(output.commit.0.to_vec()),
			switch_commit_hash: util::to_hex(output.switch_commit_hash.hash.to_vec()),
			height: block_header.height,
			lock_height: lock_height,
			spent: true,
			proof_hash: match include_proof_hash {
				true => Some(util::to_hex(output.proof.hash().to_vec())),
				false => None,
			}
		}
	}
}

// As above, except just the info needed for wallet reconstruction
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct OutputSwitch {
	/// the commit
	pub commit: String,
	/// switch commit hash
	pub switch_commit_hash: [u8; core::SWITCH_COMMIT_HASH_SIZE],
	/// The height of the block creating this output
	pub height: u64,
}

impl OutputSwitch {
	pub fn from_output(output: &core::Output, block_header: &core::BlockHeader) -> OutputSwitch {
		OutputSwitch {
			commit: util::to_hex(output.commit.0.to_vec()),
			switch_commit_hash: output.switch_commit_hash.hash,
			height: block_header.height,
		}
	}
}

// Printable representation of a block
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TxKernelPrintable {
	pub features: String,
	pub fee: u64,
	pub lock_height: u64,
	pub excess: String,
	pub excess_sig: String,
}

impl TxKernelPrintable {
	pub fn from_txkernel(k: &core::TxKernel) -> TxKernelPrintable {
		TxKernelPrintable {
			features: format!("{:?}", k.features),
			fee: k.fee,
			lock_height: k.lock_height,
			excess: util::to_hex(k.excess.0.to_vec()),
			excess_sig: util::to_hex(k.excess_sig.to_vec())
		}
	}
}

// Just the information required for wallet reconstruction
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BlockHeaderInfo {
	// Hash
	pub hash: String,
	/// Version of the block
	pub version: u16,
	/// Height of this block since the genesis block (height 0)
	pub height: u64,
	/// Hash of the block previous to this in the chain.
	pub previous: String,
	/// rfc3339 timestamp at which the block was built.
	pub timestamp: String,
	/// Merklish root of all the commitments in the UTXO set
	pub utxo_root: String,
	/// Merklish root of all range proofs in the UTXO set
	pub range_proof_root: String,
	/// Merklish root of all transaction kernels in the UTXO set
	pub kernel_root: String,
	/// Nonce increment used to mine this block.
	pub nonce: u64,
	/// Difficulty used to mine the block.
	pub difficulty: u64,
	/// Total accumulated difficulty since genesis block
	pub total_difficulty: u64,
}

impl BlockHeaderInfo {
	pub fn from_header(h: &core::BlockHeader) -> BlockHeaderInfo {
		BlockHeaderInfo {
			hash: util::to_hex(h.hash().to_vec()),
			version: h.version,
			height: h.height,
			previous: util::to_hex(h.previous.to_vec()),
			timestamp: h.timestamp.rfc3339().to_string(),
			utxo_root: util::to_hex(h.utxo_root.to_vec()),
			range_proof_root: util::to_hex(h.range_proof_root.to_vec()),
			kernel_root: util::to_hex(h.kernel_root.to_vec()),
			nonce: h.nonce,
			difficulty: h.difficulty.into_num(),
			total_difficulty: h.total_difficulty.into_num()
		}
	}
}

// Printable representation of a block
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BlockPrintable {
	/// The block header
	pub header: BlockHeaderInfo,
	// Input transactions
	pub inputs: Vec<String>,
	/// A printable version of the outputs
	pub outputs: Vec<OutputPrintable>,
	/// A printable version of the transaction kernels
	pub kernels: Vec<TxKernelPrintable>,
}

impl BlockPrintable {
	pub fn from_block(block: &core::Block) -> BlockPrintable {
		let inputs = block.inputs
			.iter()
			.map(|input| util::to_hex((input.0).0.to_vec()))
			.collect();
		let outputs = block.outputs
			.iter()
			.map(|output| OutputPrintable::from_output(output, &block.header, true))
			.collect();
		let kernels = block.kernels
			.iter()
			.map(|kernel| TxKernelPrintable::from_txkernel(kernel))
			.collect();
		BlockPrintable {
			header: BlockHeaderInfo::from_header(&block.header),
			inputs: inputs,
			outputs: outputs,
			kernels: kernels,
		}
	}
}

// For wallet reconstruction, include the header info along with the
// transactions in the block
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BlockOutputs {
	/// The block header
	pub header: BlockHeaderInfo,
	/// A printable version of the outputs
	pub outputs: Vec<OutputSwitch>,
}

#[derive(Serialize, Deserialize)]
pub struct PoolInfo {
	/// Size of the pool
	pub pool_size: usize,
	/// Size of orphans
	pub orphans_size: usize,
	/// Total size of pool + orphans
	pub total_size: usize,
}
<|endoftext|>


<commit_before>//! A wrapper around a drawable. This controls all the other state about
//! the surface, such as the cursor used or where it on the screen.

// NOTE need to store the drawable in lua, because it's a reference to a
// drawable a lua object

use std::slice;

use {
    cairo::ImageSurface,
    glib::translate::ToGlibPtr,
    rlua::{
        self, prelude::LuaInteger, Table, ToLua, UserData, UserDataMethods,
        Value
    }
};

use crate::{
    area::{Area, Margin, Origin, Size},
    common::{
        class::{self, Class, ClassBuilder},
        object::{self, Object, ObjectBuilder},
        property::Property
    },
    objects::drawable::{Drawable, Shell}
};

pub const DRAWINS_HANDLE: &'static str = "__drawins";

#[derive(Debug, Default)]
pub struct DrawinState {
    // NOTE This has a drawable, but it is stored in lua.
    ontop: bool,
    visible: bool,
    cursor: String,
    geometry: Area,
    struts: Margin,
    geometry_dirty: bool
}

pub type Drawin<'lua> = Object<'lua, DrawinState>;

impl UserData for DrawinState {
    fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
        object::default_add_methods(methods);
    }
}

impl<'lua> Drawin<'lua> {
    fn new(
        lua: rlua::Context<'lua>,
        args: Table<'lua>
    ) -> rlua::Result<Drawin<'lua>> {
        let class = class::class_setup(lua, "drawin")?;
        let mut drawins =
            lua.named_registry_value::<str, Vec<Drawin>>(DRAWINS_HANDLE)?;

        let drawin = object_setup(lua, Drawin::allocate(lua, class)?)?
            .handle_constructor_argument(args)?
            .build();

        drawins.push(drawin.clone());
        lua.set_named_registry_value(DRAWINS_HANDLE, drawins.to_lua(lua)?)?;
        Ok(drawin)
    }

    /// Get the drawable associated with this drawin.
    ///
    /// It has the surface that is needed to render to the screen.
    pub fn drawable(&mut self) -> rlua::Result<Drawable<'lua>> {
        self.get_associated_data::<Drawable>("drawable")
    }

    fn update_drawing(&mut self, lua: rlua::Context<'lua>) -> rlua::Result<()> {
        let mut drawable: Drawable = self.get_associated_data("drawable")?;
        {
            let mut state = self.state_mut()?;
            if state.geometry_dirty {
                drawable.set_geometry(lua, state.geometry)?;
                state.geometry_dirty = false;
            }
        }
        self.set_associated_data("drawable", drawable)?;
        Ok(())
    }

    fn map(&mut self, lua: rlua::Context<'lua>) -> rlua::Result<()> {
        // TODO other things
        self.update_drawing(lua)?;
        Ok(())
    }

    fn unmap(&mut self) -> rlua::Result<()> {
        // TODO?
        Ok(())
    }
}

pub fn init(lua: rlua::Context) -> rlua::Result<Class<DrawinState>> {
    let drawins: Vec<Drawin> = Vec::new();
    lua.set_named_registry_value(DRAWINS_HANDLE, drawins.to_lua(lua)?)?;
    property_setup(
        lua,
        method_setup(lua, Class::builder(lua, "drawin", None)?)?
    )?
    .save_class("drawin")?
    .build()
}

fn method_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ClassBuilder<'lua, DrawinState>
) -> rlua::Result<ClassBuilder<'lua, DrawinState>> {
    // TODO Do properly
    builder
           // TODO This should be adding properties, e.g like luaA_class_new
           .method("__call".into(), lua.create_function(|lua, args: Table| Drawin::new(lua, args))?)
}

fn property_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ClassBuilder<'lua, DrawinState>
) -> rlua::Result<ClassBuilder<'lua, DrawinState>> {
    builder
        .property(Property::new(
            "x".into(),
            Some(lua.create_function(set_x)?),
            Some(lua.create_function(get_x)?),
            Some(lua.create_function(set_x)?)
        ))?
        .property(Property::new(
            "y".into(),
            Some(lua.create_function(set_y)?),
            Some(lua.create_function(get_y)?),
            Some(lua.create_function(set_y)?)
        ))?
        .property(Property::new(
            "width".into(),
            Some(lua.create_function(set_width)?),
            Some(lua.create_function(get_width)?),
            Some(lua.create_function(set_width)?)
        ))?
        .property(Property::new(
            "height".into(),
            Some(lua.create_function(set_height)?),
            Some(lua.create_function(get_height)?),
            Some(lua.create_function(set_height)?)
        ))?
        .property(Property::new(
            "visible".into(),
            Some(lua.create_function(set_visible)?),
            Some(lua.create_function(get_visible)?),
            Some(lua.create_function(set_visible)?)
        ))
}

fn object_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ObjectBuilder<'lua, DrawinState>
) -> rlua::Result<ObjectBuilder<'lua, DrawinState>> {
    let table = lua.create_table()?;
    table.set("geometry", lua.create_function(drawin_geometry)?)?;
    table.set("struts", lua.create_function(drawin_struts)?)?;
    table.set("buttons", lua.create_function(super::dummy)?)?;

    let drawable_table = Drawable::new(
        lua,
        lua.create_function(refresh_drawin)?,
        builder.object.clone().to_lua(lua)?
    )?
    .to_lua(lua)?;

    table.set("drawable", drawable_table)?;

    builder.add_to_meta(table)
}

fn refresh_drawin<'lua>(
    _: rlua::Context<'lua>,
    mut drawin: Drawin<'lua>
) -> rlua::Result<()> {
    let mut drawable = drawin.drawable()?;
    let drawin_state = drawin.state()?;
    let mut drawable_state = drawable.state_mut()?;

    if let Some(Shell {
        ref mut surface,
        shell
    }) = drawable_state.shell.as_mut()
    {
        shell.set_margin(drawin_state.struts);
        let data = get_data(surface);
        shell
            .write_to_buffer(data)
            .expect("Could not write data to buffer");
    }
    Ok(())
}

fn set_visible<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, visible): (Drawin<'lua>, bool)
) -> rlua::Result<()> {
    let mut state = drawin.state_mut()?;
    state.visible = visible;
    drop(state);

    if visible {
        drawin.map(lua)?;
    } else {
        drawin.unmap()?;
    }

    Object::emit_signal(lua, &drawin, "property::visible".into(), Value::Nil)
}

fn get_visible<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<bool> {
    let state = drawin.state()?;

    // TODO signal

    Ok(state.visible)
}

fn drawin_geometry<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, geometry): (Drawin<'lua>, Option<Table<'lua>>)
) -> rlua::Result<Table<'lua>> {
    if let Some(geometry) = geometry {
        let width = geometry.get::<_, u32>("width")?;
        let height = geometry.get::<_, u32>("height")?;
        let x = geometry.get::<_, i32>("x")?;
        let y = geometry.get::<_, i32>("y")?;
        if width > 0 && height > 0 {
            let geo = Area {
                origin: Origin { x, y },
                size: Size { width, height }
            };
            resize(lua, &mut drawin, geo)?;
        }
    }

    let new_geo = drawin.state()?.geometry;
    let Size { width, height } = new_geo.size;
    let Origin { x, y } = new_geo.origin;

    let res = lua.create_table()?;
    res.set("x", x)?;
    res.set("y", y)?;
    res.set("height", height)?;
    res.set("width", width)?;

    Ok(res)
}

fn get_x<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Origin { x, .. } = drawin.state()?.geometry.origin;
    Ok(x as LuaInteger)
}

fn set_x<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, x): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.state()?.geometry;
    geo.origin.x = x as i32;

    resize(lua, &mut drawin, geo)?;

    Ok(())
}

fn get_y<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Origin { y, .. } = drawin.state()?.geometry.origin;
    Ok(y as LuaInteger)
}

fn set_y<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, y): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.state()?.geometry;
    geo.origin.y = y as i32;

    resize(lua, &mut drawin, geo)?;

    Ok(())
}

fn get_width<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Size { width, .. } = drawin.state()?.geometry.size;
    Ok(width as LuaInteger)
}

fn set_width<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, width): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.state()?.geometry;

    if width > 0 {
        geo.size.width = width as u32;
        resize(lua, &mut drawin, geo)?;
    }

    Ok(())
}

fn get_height<'lua>(
    _lua: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Size { height, .. } = drawin.state()?.geometry.size;
    Ok(height as LuaInteger)
}

fn set_height<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, height): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.state()?.geometry;

    if height > 0 {
        geo.size.height = height as u32;
        resize(lua, &mut drawin, geo)?;
    }

    Ok(())
}

fn drawin_struts<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, struts): (Drawin<'lua>, Option<Margin>)
) -> rlua::Result<Value<'lua>> {
    match struts {
        Some(new_struts) => {
            drawin.state_mut()?.struts = new_struts;
            Ok(Value::Nil)
        },
        None => drawin.state()?.struts.to_lua(lua)
    }
}

fn resize<'lua>(
    lua: rlua::Context<'lua>,
    drawin: &mut Drawin<'lua>,
    geometry: Area
) -> rlua::Result<()> {
    let mut state = drawin.state_mut()?;
    let old_geometry = state.geometry;
    state.geometry = geometry;

    let Size {
        ref mut width,
        ref mut height
    } = state.geometry.size;
    if *width == 0 {
        *width = old_geometry.size.width;
    }
    if *height == 0 {
        *height = old_geometry.size.height
    }

    state.geometry_dirty = true;
    // TODO emit signals
    // TODO update screen workareas like in awesome? Might not be necessary

    drop(state);
    drawin.update_drawing(lua)
}

/// Get the data associated with the ImageSurface.
fn get_data(surface: &mut ImageSurface) -> &[u8] {
    // NOTE This is safe to do because there's one thread.
    //
    // We know Lua is not modifying it because it's not running.
    unsafe {
        let len = surface.get_stride() as usize * surface.get_height() as usize;
        let surface = surface.to_glib_none().0;
        slice::from_raw_parts(
            cairo_sys::cairo_image_surface_get_data(surface as _),
            len
        )
    }
}
<commit_msg>Notify Lua when a drawin resizes<commit_after>//! A wrapper around a drawable. This controls all the other state about
//! the surface, such as the cursor used or where it on the screen.

// NOTE need to store the drawable in lua, because it's a reference to a
// drawable a lua object

use std::slice;

use {
    cairo::ImageSurface,
    glib::translate::ToGlibPtr,
    rlua::{
        self, prelude::LuaInteger, Table, ToLua, UserData, UserDataMethods,
        Value
    }
};

use crate::{
    area::{Area, Margin, Origin, Size},
    common::{
        class::{self, Class, ClassBuilder},
        object::{self, Object, ObjectBuilder},
        property::Property
    },
    objects::drawable::{Drawable, Shell}
};

pub const DRAWINS_HANDLE: &'static str = "__drawins";

#[derive(Debug, Default)]
pub struct DrawinState {
    // NOTE This has a drawable, but it is stored in lua.
    ontop: bool,
    visible: bool,
    cursor: String,
    geometry: Area,
    struts: Margin,
    geometry_dirty: bool
}

pub type Drawin<'lua> = Object<'lua, DrawinState>;

impl UserData for DrawinState {
    fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
        object::default_add_methods(methods);
    }
}

impl<'lua> Drawin<'lua> {
    fn new(
        lua: rlua::Context<'lua>,
        args: Table<'lua>
    ) -> rlua::Result<Drawin<'lua>> {
        let class = class::class_setup(lua, "drawin")?;
        let mut drawins =
            lua.named_registry_value::<str, Vec<Drawin>>(DRAWINS_HANDLE)?;

        let drawin = object_setup(lua, Drawin::allocate(lua, class)?)?
            .handle_constructor_argument(args)?
            .build();

        drawins.push(drawin.clone());
        lua.set_named_registry_value(DRAWINS_HANDLE, drawins.to_lua(lua)?)?;
        Ok(drawin)
    }

    /// Get the drawable associated with this drawin.
    ///
    /// It has the surface that is needed to render to the screen.
    pub fn drawable(&mut self) -> rlua::Result<Drawable<'lua>> {
        self.get_associated_data::<Drawable>("drawable")
    }

    fn update_drawing(&mut self, lua: rlua::Context<'lua>) -> rlua::Result<()> {
        let mut drawable: Drawable = self.get_associated_data("drawable")?;
        {
            let mut state = self.state_mut()?;
            if state.geometry_dirty {
                drawable.set_geometry(lua, state.geometry)?;
                state.geometry_dirty = false;
            }
        }
        self.set_associated_data("drawable", drawable)?;
        Ok(())
    }

    fn map(&mut self, lua: rlua::Context<'lua>) -> rlua::Result<()> {
        // TODO other things
        self.update_drawing(lua)?;
        Ok(())
    }

    fn unmap(&mut self) -> rlua::Result<()> {
        // TODO?
        Ok(())
    }
}

pub fn init(lua: rlua::Context) -> rlua::Result<Class<DrawinState>> {
    let drawins: Vec<Drawin> = Vec::new();
    lua.set_named_registry_value(DRAWINS_HANDLE, drawins.to_lua(lua)?)?;
    property_setup(
        lua,
        method_setup(lua, Class::builder(lua, "drawin", None)?)?
    )?
    .save_class("drawin")?
    .build()
}

fn method_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ClassBuilder<'lua, DrawinState>
) -> rlua::Result<ClassBuilder<'lua, DrawinState>> {
    // TODO Do properly
    builder
           // TODO This should be adding properties, e.g like luaA_class_new
           .method("__call".into(), lua.create_function(|lua, args: Table| Drawin::new(lua, args))?)
}

fn property_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ClassBuilder<'lua, DrawinState>
) -> rlua::Result<ClassBuilder<'lua, DrawinState>> {
    builder
        .property(Property::new(
            "x".into(),
            Some(lua.create_function(set_x)?),
            Some(lua.create_function(get_x)?),
            Some(lua.create_function(set_x)?)
        ))?
        .property(Property::new(
            "y".into(),
            Some(lua.create_function(set_y)?),
            Some(lua.create_function(get_y)?),
            Some(lua.create_function(set_y)?)
        ))?
        .property(Property::new(
            "width".into(),
            Some(lua.create_function(set_width)?),
            Some(lua.create_function(get_width)?),
            Some(lua.create_function(set_width)?)
        ))?
        .property(Property::new(
            "height".into(),
            Some(lua.create_function(set_height)?),
            Some(lua.create_function(get_height)?),
            Some(lua.create_function(set_height)?)
        ))?
        .property(Property::new(
            "visible".into(),
            Some(lua.create_function(set_visible)?),
            Some(lua.create_function(get_visible)?),
            Some(lua.create_function(set_visible)?)
        ))
}

fn object_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ObjectBuilder<'lua, DrawinState>
) -> rlua::Result<ObjectBuilder<'lua, DrawinState>> {
    let table = lua.create_table()?;
    table.set("geometry", lua.create_function(drawin_geometry)?)?;
    table.set("struts", lua.create_function(drawin_struts)?)?;
    table.set("buttons", lua.create_function(super::dummy)?)?;

    let drawable_table = Drawable::new(
        lua,
        lua.create_function(refresh_drawin)?,
        builder.object.clone().to_lua(lua)?
    )?
    .to_lua(lua)?;

    table.set("drawable", drawable_table)?;

    builder.add_to_meta(table)
}

fn refresh_drawin<'lua>(
    _: rlua::Context<'lua>,
    mut drawin: Drawin<'lua>
) -> rlua::Result<()> {
    let mut drawable = drawin.drawable()?;
    let drawin_state = drawin.state()?;
    let mut drawable_state = drawable.state_mut()?;

    if let Some(Shell {
        ref mut surface,
        shell
    }) = drawable_state.shell.as_mut()
    {
        shell.set_margin(drawin_state.struts);
        let data = get_data(surface);
        shell
            .write_to_buffer(data)
            .expect("Could not write data to buffer");
    }
    Ok(())
}

fn set_visible<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, visible): (Drawin<'lua>, bool)
) -> rlua::Result<()> {
    let mut state = drawin.state_mut()?;
    state.visible = visible;
    drop(state);

    if visible {
        drawin.map(lua)?;
    } else {
        drawin.unmap()?;
    }

    Object::emit_signal(lua, &drawin, "property::visible".into(), Value::Nil)
}

fn get_visible<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<bool> {
    let state = drawin.state()?;

    // TODO signal

    Ok(state.visible)
}

fn drawin_geometry<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, geometry): (Drawin<'lua>, Option<Table<'lua>>)
) -> rlua::Result<Table<'lua>> {
    if let Some(geometry) = geometry {
        let width = geometry.get::<_, u32>("width")?;
        let height = geometry.get::<_, u32>("height")?;
        let x = geometry.get::<_, i32>("x")?;
        let y = geometry.get::<_, i32>("y")?;
        if width > 0 && height > 0 {
            let geo = Area {
                origin: Origin { x, y },
                size: Size { width, height }
            };
            resize(lua, &mut drawin, geo)?;
        }
    }

    let new_geo = drawin.state()?.geometry;
    let Size { width, height } = new_geo.size;
    let Origin { x, y } = new_geo.origin;

    let res = lua.create_table()?;
    res.set("x", x)?;
    res.set("y", y)?;
    res.set("height", height)?;
    res.set("width", width)?;

    Ok(res)
}

fn get_x<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Origin { x, .. } = drawin.state()?.geometry.origin;
    Ok(x as LuaInteger)
}

fn set_x<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, x): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.state()?.geometry;
    geo.origin.x = x as i32;

    resize(lua, &mut drawin, geo)?;

    Ok(())
}

fn get_y<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Origin { y, .. } = drawin.state()?.geometry.origin;
    Ok(y as LuaInteger)
}

fn set_y<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, y): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.state()?.geometry;
    geo.origin.y = y as i32;

    resize(lua, &mut drawin, geo)?;

    Ok(())
}

fn get_width<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Size { width, .. } = drawin.state()?.geometry.size;
    Ok(width as LuaInteger)
}

fn set_width<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, width): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.state()?.geometry;

    if width > 0 {
        geo.size.width = width as u32;
        resize(lua, &mut drawin, geo)?;
    }

    Ok(())
}

fn get_height<'lua>(
    _lua: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Size { height, .. } = drawin.state()?.geometry.size;
    Ok(height as LuaInteger)
}

fn set_height<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, height): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.state()?.geometry;

    if height > 0 {
        geo.size.height = height as u32;
        resize(lua, &mut drawin, geo)?;
    }

    Ok(())
}

fn drawin_struts<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, struts): (Drawin<'lua>, Option<Margin>)
) -> rlua::Result<Value<'lua>> {
    match struts {
        Some(new_struts) => {
            drawin.state_mut()?.struts = new_struts;
            Ok(Value::Nil)
        },
        None => drawin.state()?.struts.to_lua(lua)
    }
}

fn resize<'lua>(
    lua: rlua::Context<'lua>,
    drawin: &mut Drawin<'lua>,
    geometry: Area
) -> rlua::Result<()> {
    let Area {
        mut origin,
        mut size
    } = drawin.state()?.geometry.clone();
    let Area {
        origin: Origin { x: new_x, y: new_y },
        size:
            Size {
                width: new_width,
                height: new_height
            }
    } = geometry;

    let mut changed = false;
    if new_width > 0 && new_width != size.width {
        size.width = new_width;
        Object::emit_signal(lua, drawin, "property::width", 0)?;
        changed = true;
    }
    if new_height > 0 && new_height != size.height {
        size.height = new_height;
        Object::emit_signal(lua, drawin, "property::height", 0)?;
        changed = true;
    }
    if new_x != origin.x {
        origin.x = new_x;
        Object::emit_signal(lua, drawin, "property::x", 0)?;
        changed = true;
    }
    if new_y != origin.y {
        origin.y = new_y;
        Object::emit_signal(lua, drawin, "property::y", 0)?;
        changed = true;
    }
    if changed {
        Object::emit_signal(lua, drawin, "property::geometry", 0)?;
    }

    drawin.state_mut()?.geometry = Area { origin, size };
    drawin.state_mut()?.geometry_dirty = true;
    // TODO emit signals
    // TODO update screen workareas like in awesome? Might not be necessary

    drawin.update_drawing(lua)
}

/// Get the data associated with the ImageSurface.
fn get_data(surface: &mut ImageSurface) -> &[u8] {
    // NOTE This is safe to do because there's one thread.
    //
    // We know Lua is not modifying it because it's not running.
    unsafe {
        let len = surface.get_stride() as usize * surface.get_height() as usize;
        let surface = surface.to_glib_none().0;
        slice::from_raw_parts(
            cairo_sys::cairo_image_surface_get_data(surface as _),
            len
        )
    }
}
<|endoftext|>


<commit_before>use std::cell::Cell;
use std::marker::PhantomData;

use super::{BaseIndex, BaseIndexIter, Result, Snapshot, Fork, StorageValue};

pub struct ListIndex<T, V> {
    base: BaseIndex<T>,
    length: Cell<Option<u64>>,
    _v: PhantomData<V>,
}

pub struct ListIndexIter<'a, V> {
    base_iter: BaseIndexIter<'a, u64, V>
}

impl<T, V> ListIndex<T, V> {
    pub fn new(prefix: Vec<u8>, base: T) -> Self {
        ListIndex {
            base: BaseIndex::new(prefix, base),
            length: Cell::new(None),
            _v: PhantomData
        }
    }
}

impl<T, V> ListIndex<T, V> where T: AsRef<Snapshot>,
                                 V: StorageValue {
    pub fn get(&self, index: u64) -> Result<Option<V>> {
        self.base.get(&index)
    }

    pub fn last(&self) -> Result<Option<V>> {
        match self.len()? {
            0 => Ok(None),
            l => self.get(l - 1)
        }
    }

    pub fn is_empty(&self) -> Result<bool> {
        Ok(self.len()? == 0)
    }

    pub fn len(&self) -> Result<u64> {
        if let Some(len) = self.length.get() {
            return Ok(len)
        }
        let len = self.base.get(&())?.unwrap_or(0);
        self.length.set(Some(len));
        Ok(len)
    }

    pub fn iter(&self) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter() }
    }

    pub fn iter_from(&self, from: u64) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter_from(&from) }
    }
}

impl<'a, V> ListIndex<&'a mut Fork, V> where V: StorageValue {
    pub fn push(&mut self, value: V) -> Result<()> {
        let len = self.len()?;
        self.base.put(&len, value);
        self.base.put(&(), len + 1);
        self.length.set(Some(len + 1));
        Ok(())
    }

    pub fn pop(&mut self) -> Result<Option<V>> {
        // TODO: shoud we get and return dropped value?
        match self.len()? {
            0 => Ok(None),
            l => {
                let v = self.base.get(&(l - 1))?;
                self.base.delete(&(l - 1));
                self.base.put(&(), l - 1);
                Ok(v)
            }
        }
    }

    pub fn extend<I>(&mut self, iter: I) -> Result<()> where I: IntoIterator<Item=V> {
        let mut len = self.len()?;
        for value in iter {
            self.base.put(&len, value);
            len = len + 1;
        }
        self.base.put(&(), len);
        self.length.set(Some(len));
        Ok(())
    }

    pub fn truncate(&mut self, len: u64) -> Result<()> {
        // TODO: optimize this
        while self.len()? > len {
            self.pop()?;
        }
        Ok(())
    }

    pub fn set(&mut self, index: u64, value: V) -> Result<()> {
        // TODO: shoud we panic here?
        if index < self.len()? {
            self.base.put(&index, value)
        }
        Ok(())
    }

    pub fn clear(&mut self) {
        self.base.clear()
    }
}

impl<'a, V> Iterator for ListIndexIter<'a, V> where V: StorageValue {
    type Item = V;

    fn next(&mut self) -> Option<Self::Item> {
        self.base_iter.next().map(|(.., v)| v)
    }
}

#[cfg(test)]
mod tests {
    use ::storage::{MemoryDB, Database, List, ListTable};

    #[test]
    fn test_list_table_methods() {
        let fork = MemoryDB::new().fork();
        let list_table = ListTable::new(vec![255], &mut fork);

        assert!(list_table.is_empty().unwrap());
        assert_eq!(0, list_table.len().unwrap());
        assert!(list_table.last().unwrap().is_none());

        let extended_by = vec![45u64, 3422u64, 234u64];
        list_table.extend(extended_by.into_iter()).unwrap();
        assert!(!list_table.is_empty().unwrap());
        assert_eq!(Some(45u64), list_table.get(0u64).unwrap());
        assert_eq!(Some(3422u64), list_table.get(1).unwrap());
        assert_eq!(Some(234u64), list_table.get(2).unwrap());
        assert_eq!(3, list_table.len().unwrap());

        list_table.set(2, 777u64).unwrap();
        assert_eq!(Some(777u64), list_table.get(2).unwrap());
        assert_eq!(Some(777u64), list_table.last().unwrap());
        assert_eq!(3, list_table.len().unwrap());

        let mut extended_by_again = vec![666u64, 999u64];
        for el in &extended_by_again {
            list_table.append(*el).unwrap();
        }
        assert_eq!(Some(666u64), list_table.get(3).unwrap());
        assert_eq!(Some(999u64), list_table.get(4).unwrap());
        assert_eq!(5, list_table.len().unwrap());
        extended_by_again[1] = 1001u64;
        list_table.extend(extended_by_again).unwrap();
        assert_eq!(7, list_table.len().unwrap());
        assert_eq!(Some(1001u64), list_table.last().unwrap());
    }

}
<commit_msg>Drop len for ListIndex when clear it<commit_after>use std::cell::Cell;
use std::marker::PhantomData;

use super::{BaseIndex, BaseIndexIter, Result, Snapshot, Fork, StorageValue};

pub struct ListIndex<T, V> {
    base: BaseIndex<T>,
    length: Cell<Option<u64>>,
    _v: PhantomData<V>,
}

pub struct ListIndexIter<'a, V> {
    base_iter: BaseIndexIter<'a, u64, V>
}

impl<T, V> ListIndex<T, V> {
    pub fn new(prefix: Vec<u8>, base: T) -> Self {
        ListIndex {
            base: BaseIndex::new(prefix, base),
            length: Cell::new(None),
            _v: PhantomData
        }
    }
}

impl<T, V> ListIndex<T, V> where T: AsRef<Snapshot>,
                                 V: StorageValue {
    pub fn get(&self, index: u64) -> Result<Option<V>> {
        self.base.get(&index)
    }

    pub fn last(&self) -> Result<Option<V>> {
        match self.len()? {
            0 => Ok(None),
            l => self.get(l - 1)
        }
    }

    pub fn is_empty(&self) -> Result<bool> {
        Ok(self.len()? == 0)
    }

    pub fn len(&self) -> Result<u64> {
        if let Some(len) = self.length.get() {
            return Ok(len)
        }
        let len = self.base.get(&())?.unwrap_or(0);
        self.length.set(Some(len));
        Ok(len)
    }

    pub fn iter(&self) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter() }
    }

    pub fn iter_from(&self, from: u64) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter_from(&from) }
    }
}

impl<'a, V> ListIndex<&'a mut Fork, V> where V: StorageValue {
    pub fn push(&mut self, value: V) -> Result<()> {
        let len = self.len()?;
        self.base.put(&len, value);
        self.base.put(&(), len + 1);
        self.length.set(Some(len + 1));
        Ok(())
    }

    pub fn pop(&mut self) -> Result<Option<V>> {
        // TODO: shoud we get and return dropped value?
        match self.len()? {
            0 => Ok(None),
            l => {
                let v = self.base.get(&(l - 1))?;
                self.base.delete(&(l - 1));
                self.base.put(&(), l - 1);
                Ok(v)
            }
        }
    }

    pub fn extend<I>(&mut self, iter: I) -> Result<()> where I: IntoIterator<Item=V> {
        let mut len = self.len()?;
        for value in iter {
            self.base.put(&len, value);
            len = len + 1;
        }
        self.base.put(&(), len);
        self.length.set(Some(len));
        Ok(())
    }

    pub fn truncate(&mut self, len: u64) -> Result<()> {
        // TODO: optimize this
        while self.len()? > len {
            self.pop()?;
        }
        Ok(())
    }

    pub fn set(&mut self, index: u64, value: V) -> Result<()> {
        // TODO: shoud we panic here?
        if index < self.len()? {
            self.base.put(&index, value)
        }
        Ok(())
    }

    pub fn clear(&mut self) {
        self.length.set(Some(0));
        self.base.clear()
    }
}

impl<'a, V> Iterator for ListIndexIter<'a, V> where V: StorageValue {
    type Item = V;

    fn next(&mut self) -> Option<Self::Item> {
        self.base_iter.next().map(|(.., v)| v)
    }
}

#[cfg(test)]
mod tests {
    use ::storage::{MemoryDB, Database, List, ListTable};

    #[test]
    fn test_list_table_methods() {
        let fork = MemoryDB::new().fork();
        let list_table = ListTable::new(vec![255], &mut fork);

        assert!(list_table.is_empty().unwrap());
        assert_eq!(0, list_table.len().unwrap());
        assert!(list_table.last().unwrap().is_none());

        let extended_by = vec![45u64, 3422u64, 234u64];
        list_table.extend(extended_by.into_iter()).unwrap();
        assert!(!list_table.is_empty().unwrap());
        assert_eq!(Some(45u64), list_table.get(0u64).unwrap());
        assert_eq!(Some(3422u64), list_table.get(1).unwrap());
        assert_eq!(Some(234u64), list_table.get(2).unwrap());
        assert_eq!(3, list_table.len().unwrap());

        list_table.set(2, 777u64).unwrap();
        assert_eq!(Some(777u64), list_table.get(2).unwrap());
        assert_eq!(Some(777u64), list_table.last().unwrap());
        assert_eq!(3, list_table.len().unwrap());

        let mut extended_by_again = vec![666u64, 999u64];
        for el in &extended_by_again {
            list_table.append(*el).unwrap();
        }
        assert_eq!(Some(666u64), list_table.get(3).unwrap());
        assert_eq!(Some(999u64), list_table.get(4).unwrap());
        assert_eq!(5, list_table.len().unwrap());
        extended_by_again[1] = 1001u64;
        list_table.extend(extended_by_again).unwrap();
        assert_eq!(7, list_table.len().unwrap());
        assert_eq!(Some(1001u64), list_table.last().unwrap());
    }

}
<|endoftext|>


<commit_before>//! Procedural macro implementing `#[derive(EnumMap)]`
//!
//! This is supposed to used with `enum-map` crate, which provides the
//! actual usage documentation.

#![recursion_limit = "128"]

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use std::iter;

use proc_macro::TokenStream;
use syn::{Body, Ident, Variant, VariantData};
use quote::Tokens;

fn generate_enum_code(name: &Ident, variants: &[Variant]) -> Tokens {
    let mut enum_count = 0usize;
    let mut has_discriminants = false;
    for &Variant {
        ref data,
        ref discriminant,
        ..
    } in variants
    {
        if data != &VariantData::Unit {
            panic!("#[derive(EnumMap)] requires C style style enum");
        }
        if discriminant.is_some() {
            has_discriminants = true;
        }
        enum_count += 1;
    }

    let variant_a = variants.iter().map(|variant| &variant.ident);
    let variant_b = variants.iter().map(|variant| &variant.ident);
    let repeat_name_a = iter::repeat(name).take(variants.len());
    let repeat_name_b = repeat_name_a.clone();
    let counter = 0..variants.len();

    let to_usize = if variants.len() == 0 || has_discriminants {
        let repeat_name = repeat_name_a.clone();
        let variant = variants.iter().map(|variant| &variant.ident);
        let counter = 0..variants.len();
        quote! {
            match self {
                #(
                    #repeat_name::#variant => #counter,
                )*
            }
        }
    } else {
        quote! { self as usize }
    };

    quote! {
        impl<V> ::enum_map::Internal<V> for #name {
            type Array = [V; #enum_count];
            fn slice(array: &Self::Array) -> &[V] {
                array
            }
            fn slice_mut(array: &mut Self::Array) -> &mut [V] {
                array
            }
            fn from_usize(value: usize) -> Self {
                match value {
                    #(
                        #counter => #repeat_name_a::#variant_a,
                    )*
                    _ => unreachable!()
                }
            }
            fn to_usize(self) -> usize {
                #to_usize
            }
            fn from_function<F: FnMut(Self) -> V>(mut _f: F) -> Self::Array {
                [#(
                    _f(#repeat_name_b::#variant_b),
                )*]
            }
        }
    }
}

#[proc_macro_derive(EnumMap)]
pub fn derive_enum_map(input: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input(&input.to_string()).unwrap();
    match input.body {
        Body::Enum(ref variants) => generate_enum_code(&input.ident, variants),
        _ => panic!("#[derive(EnumMap)] is only defined for enums"),
    }.parse()
        .unwrap()
}
<commit_msg>Reduce duplication of repeat_name in enum-map-derive<commit_after>//! Procedural macro implementing `#[derive(EnumMap)]`
//!
//! This is supposed to used with `enum-map` crate, which provides the
//! actual usage documentation.

#![recursion_limit = "128"]

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use std::iter;

use proc_macro::TokenStream;
use syn::{Body, Ident, Variant, VariantData};
use quote::Tokens;

fn generate_enum_code(name: &Ident, variants: &[Variant]) -> Tokens {
    let mut enum_count = 0usize;
    let mut has_discriminants = false;
    for &Variant {
        ref data,
        ref discriminant,
        ..
    } in variants
    {
        if data != &VariantData::Unit {
            panic!("#[derive(EnumMap)] requires C style style enum");
        }
        if discriminant.is_some() {
            has_discriminants = true;
        }
        enum_count += 1;
    }

    let variant_a = variants.iter().map(|variant| &variant.ident);
    let variant_b = variants.iter().map(|variant| &variant.ident);
    let repeat_name = iter::repeat(name);
    let repeat_name_b = repeat_name.clone();
    let counter = 0..variants.len();

    let to_usize = if variants.len() == 0 || has_discriminants {
        let repeat_name = repeat_name.clone();
        let variant = variants.iter().map(|variant| &variant.ident);
        let counter = 0..variants.len();
        quote! {
            match self {
                #(
                    #repeat_name::#variant => #counter,
                )*
            }
        }
    } else {
        quote! { self as usize }
    };

    quote! {
        impl<V> ::enum_map::Internal<V> for #name {
            type Array = [V; #enum_count];
            fn slice(array: &Self::Array) -> &[V] {
                array
            }
            fn slice_mut(array: &mut Self::Array) -> &mut [V] {
                array
            }
            fn from_usize(value: usize) -> Self {
                match value {
                    #(
                        #counter => #repeat_name::#variant_a,
                    )*
                    _ => unreachable!()
                }
            }
            fn to_usize(self) -> usize {
                #to_usize
            }
            fn from_function<F: FnMut(Self) -> V>(mut _f: F) -> Self::Array {
                [#(
                    _f(#repeat_name_b::#variant_b),
                )*]
            }
        }
    }
}

#[proc_macro_derive(EnumMap)]
pub fn derive_enum_map(input: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input(&input.to_string()).unwrap();
    match input.body {
        Body::Enum(ref variants) => generate_enum_code(&input.ident, variants),
        _ => panic!("#[derive(EnumMap)] is only defined for enums"),
    }.parse()
        .unwrap()
}
<|endoftext|>


<commit_before>/**
 * Exponential Functions
 */

use num::Num;

use ncast::*;

pub trait Exp {
    pure fn pow(n: self) -> self;
    pure fn exp() -> self;
    pure fn log_() -> self;
    pure fn exp2() -> self;
    pure fn log2() -> self;
    pure fn sqrt() -> self;
    pure fn inv_sqrt() -> self;
}

#[inline(always)] pub pure fn pow<T:Exp>(x: T, y: T) -> T { x.pow(move y) }
#[inline(always)] pub pure fn exp<T:Exp>(x: T) -> T { x.exp() }
#[inline(always)] pub pure fn log_<T:Exp>(x: T) -> T { x.log_() }
#[inline(always)] pub pure fn exp2<T:Exp>(x: T) -> T { x.exp2() }
#[inline(always)] pub pure fn log2<T:Exp>(x: T) -> T { x.log2() }
#[inline(always)] pub pure fn sqrt<T:Exp>(x: T) -> T { x.sqrt() }
#[inline(always)] pub pure fn inv_sqrt<T:Exp>(x: T) -> T { x.inv_sqrt() }

pub impl f32: Exp {
    #[inline(always)] pure fn pow(y: f32) -> f32 { f32::pow(self, y) }
    #[inline(always)] pure fn exp() -> f32 { f32::exp(self) }
    #[inline(always)] pure fn log_() -> f32 { f32::ln(self) }
    #[inline(always)] pure fn exp2() -> f32 { f32::exp2(self) }
    #[inline(always)] pure fn log2() -> f32 { f32::log2(self) }
    #[inline(always)] pure fn sqrt() -> f32 { f32::sqrt(self) }
    #[inline(always)] pure fn inv_sqrt() -> f32 { 1f32 / self.sqrt() }  // TODO: optimise? need a wizard
}

pub impl f64: Exp {
    #[inline(always)] pure fn pow(y: f64) -> f64 { f64::pow(self, y) }
    #[inline(always)] pure fn exp() -> f64 { f64::exp(self) }
    #[inline(always)] pure fn log_() -> f64 { f64::ln(self) }
    #[inline(always)] pure fn exp2() -> f64 { f64::exp2(self) }
    #[inline(always)] pure fn log2() -> f64 { f64::log2(self) }
    #[inline(always)] pure fn sqrt() -> f64 { f64::sqrt(self) }
    #[inline(always)] pure fn inv_sqrt() -> f64 { 1f64 / self.sqrt() }  // TODO: optimise? need a wizard
}

pub impl float: Exp {
    #[inline(always)] pure fn pow(y: float) -> float { cast(float::pow(cast(self), cast(y))) }
    #[inline(always)] pure fn exp() -> float { cast(float::exp(cast(self))) }
    #[inline(always)] pure fn log_() -> float { cast(float::ln(cast(self))) }
    #[inline(always)] pure fn exp2() -> float { cast(float::exp2(cast(self))) }
    #[inline(always)] pure fn log2() -> float { cast(float::log2(cast(self))) }
    #[inline(always)] pure fn sqrt() -> float { cast(float::sqrt(cast(self))) }
    #[inline(always)] pure fn inv_sqrt() -> float { 1f / self.sqrt() }  // TODO: optimise? need a wizard
}<commit_msg>OCD formatting<commit_after>/**
 * Exponential Functions
 */

use num::Num;

use ncast::*;

pub trait Exp {
    pure fn pow(n: self) -> self;
    pure fn exp()        -> self;
    pure fn log_()       -> self;
    pure fn exp2()       -> self;
    pure fn log2()       -> self;
    pure fn sqrt()       -> self;
    pure fn inv_sqrt()   -> self;
}

#[inline(always)] pub pure fn pow<T:Exp>(x: T, n: T) -> T { x.pow(move n) }
#[inline(always)] pub pure fn exp<T:Exp>(x: T)       -> T { x.exp() }
#[inline(always)] pub pure fn log_<T:Exp>(x: T)      -> T { x.log_() }
#[inline(always)] pub pure fn exp2<T:Exp>(x: T)      -> T { x.exp2() }
#[inline(always)] pub pure fn log2<T:Exp>(x: T)      -> T { x.log2() }
#[inline(always)] pub pure fn sqrt<T:Exp>(x: T)      -> T { x.sqrt() }
#[inline(always)] pub pure fn inv_sqrt<T:Exp>(x: T)  -> T { x.inv_sqrt() }

pub impl f32: Exp {
    #[inline(always)] pure fn pow(n: f32)   -> f32 { f32::pow(self, n) }
    #[inline(always)] pure fn exp()         -> f32 { f32::exp(self) }
    #[inline(always)] pure fn log_()        -> f32 { f32::ln(self) }
    #[inline(always)] pure fn exp2()        -> f32 { f32::exp2(self) }
    #[inline(always)] pure fn log2()        -> f32 { f32::log2(self) }
    #[inline(always)] pure fn sqrt()        -> f32 { f32::sqrt(self) }
    #[inline(always)] pure fn inv_sqrt()    -> f32 { 1f32 / self.sqrt() }  // TODO: optimise? need a wizard
}

pub impl f64: Exp {
    #[inline(always)] pure fn pow(n: f64)   -> f64 { f64::pow(self, n) }
    #[inline(always)] pure fn exp()         -> f64 { f64::exp(self) }
    #[inline(always)] pure fn log_()        -> f64 { f64::ln(self) }
    #[inline(always)] pure fn exp2()        -> f64 { f64::exp2(self) }
    #[inline(always)] pure fn log2()        -> f64 { f64::log2(self) }
    #[inline(always)] pure fn sqrt()        -> f64 { f64::sqrt(self) }
    #[inline(always)] pure fn inv_sqrt()    -> f64 { 1f64 / self.sqrt() }  // TODO: optimise? need a wizard
}

pub impl float: Exp {
    #[inline(always)] pure fn pow(n: float) -> float { cast(float::pow(cast(self), cast(n))) }
    #[inline(always)] pure fn exp()         -> float { cast(float::exp(cast(self))) }
    #[inline(always)] pure fn log_()        -> float { cast(float::ln(cast(self))) }
    #[inline(always)] pure fn exp2()        -> float { cast(float::exp2(cast(self))) }
    #[inline(always)] pure fn log2()        -> float { cast(float::log2(cast(self))) }
    #[inline(always)] pure fn sqrt()        -> float { cast(float::sqrt(cast(self))) }
    #[inline(always)] pure fn inv_sqrt()    -> float { 1f / self.sqrt() }  // TODO: optimise? need a wizard
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Mul, Index, BitXor};

pub struct Vec2i {
    pub x: i32,
    pub y: i32,
}

impl Vec2i {
    pub fn new(x: i32, y: i32) -> Vec2i {
        Vec2i { x: x, y: y }
    }
    pub fn newf32(x: f32, y: f32) -> Vec2i {
        Vec2i {
            x: x as i32,
            y: y as i32,
        }
    }
    pub fn index_set(&mut self, index: usize, v: i32) {
        match index {
            0 => self.x = v,
            1 => self.y = v,
            _ => panic!("exhaust"),
        }
    }
    pub fn set(&mut self, x: i32, y: i32) {
        self.x = x;
        self.y = y;
    }
}

impl Add for Vec2i {
    type Output = Vec2i;
    fn add(self, rhs: Vec2i) -> Vec2i {
        Vec2i::new(self.x + rhs.x, self.y + rhs.y)
    }
}

impl Sub for Vec2i {
    type Output = Vec2i;
    fn sub(self, rhs: Vec2i) -> Vec2i {
        Vec2i::new(self.x - rhs.x, self.y - rhs.y)
    }
}

impl Mul<f32> for Vec2i {
    type Output = Vec2i;
    fn mul(self, rhs: f32) -> Vec2i {
        Vec2i::new((self.x as f32 * rhs) as i32, (self.y as f32 * rhs) as i32)
    }
}

impl Index<usize> for Vec2i {
    type Output = i32;
    fn index(&self, index: usize) -> &i32 {
        match index {
            0 => &self.x,
            1 => &self.y,
            _ => panic!("exhaust"),
        }
    }
}

#[derive(Clone,Copy)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

impl Vec3f {
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x, y: y, z: z }
    }
    pub fn newi32(x: i32, y: i32, z: i32) -> Vec3f {
        Vec3f::new(x as f32, y as f32, z as f32)
    }
    fn norm(&self) -> f32 {
        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
    }
    pub fn normalize(&self) -> Vec3f {
        let n = self.norm();
        Vec3f::new(self.x / n, self.y / n, self.z / n)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, rhs: Vec3f) -> Vec3f {
        Vec3f::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
    }
}

impl BitXor for Vec3f {
    type Output = Vec3f;
    fn bitxor(self, rhs: Vec3f) -> Vec3f {
        Vec3f::new(self.y * rhs.z - self.z * rhs.y,
                   self.z * rhs.x - self.x * rhs.z,
                   self.x * rhs.y - self.y * rhs.x)
    }
}

impl Mul for Vec3f {
    type Output = f32;
    fn mul(self, rhs: Vec3f) -> f32 {
        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
}

pub fn barycentric(pts: &[Vec2i; 3], p: &Vec2i) -> Vec3f {
    let u = Vec3f::newi32(pts[2].x - pts[0].x, pts[1].x - pts[0].x, pts[0].x - p.x) ^
            Vec3f::newi32(pts[2].y - pts[0].y, pts[1].y - pts[0].y, pts[0].y - p.y);
    if u.z.abs() < 1f32 {
        return Vec3f::new(-1f32, 1f32, 1f32);
    }
    Vec3f::new(1f32 - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z)
}
<commit_msg>comments<commit_after>use std::ops::{Add, Sub, Mul, Index, BitXor};

pub struct Vec2i {
    pub x: i32,
    pub y: i32,
}

impl Vec2i {
    pub fn new(x: i32, y: i32) -> Vec2i {
        Vec2i { x: x, y: y }
    }
    pub fn newf32(x: f32, y: f32) -> Vec2i {
        Vec2i {
            x: x as i32,
            y: y as i32,
        }
    }
    pub fn index_set(&mut self, index: usize, v: i32) {
        match index {
            0 => self.x = v,
            1 => self.y = v,
            _ => panic!("exhaust"),
        }
    }
    pub fn set(&mut self, x: i32, y: i32) {
        self.x = x;
        self.y = y;
    }
}

impl Add for Vec2i {
    type Output = Vec2i;
    fn add(self, rhs: Vec2i) -> Vec2i {
        Vec2i::new(self.x + rhs.x, self.y + rhs.y)
    }
}

impl Sub for Vec2i {
    type Output = Vec2i;
    fn sub(self, rhs: Vec2i) -> Vec2i {
        Vec2i::new(self.x - rhs.x, self.y - rhs.y)
    }
}

impl Mul<f32> for Vec2i {
    type Output = Vec2i;
    fn mul(self, rhs: f32) -> Vec2i {
        Vec2i::new((self.x as f32 * rhs) as i32, (self.y as f32 * rhs) as i32)
    }
}

impl Index<usize> for Vec2i {
    type Output = i32;
    fn index(&self, index: usize) -> &i32 {
        match index {
            0 => &self.x,
            1 => &self.y,
            _ => panic!("exhaust"),
        }
    }
}

#[derive(Clone,Copy)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

impl Vec3f {
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x, y: y, z: z }
    }
    pub fn newi32(x: i32, y: i32, z: i32) -> Vec3f {
        Vec3f::new(x as f32, y as f32, z as f32)
    }
    fn norm(&self) -> f32 {
        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
    }
    pub fn normalize(&self) -> Vec3f {
        let n = self.norm();
        Vec3f::new(self.x / n, self.y / n, self.z / n)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, rhs: Vec3f) -> Vec3f {
        Vec3f::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
    }
}

// cross product
impl BitXor for Vec3f {
    type Output = Vec3f;
    fn bitxor(self, rhs: Vec3f) -> Vec3f {
        Vec3f::new(self.y * rhs.z - self.z * rhs.y,
                   self.z * rhs.x - self.x * rhs.z,
                   self.x * rhs.y - self.y * rhs.x)
    }
}

// dot product
impl Mul for Vec3f {
    type Output = f32;
    fn mul(self, rhs: Vec3f) -> f32 {
        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
}

pub fn barycentric(pts: &[Vec2i; 3], p: &Vec2i) -> Vec3f {
    let u = Vec3f::newi32(pts[2].x - pts[0].x, pts[1].x - pts[0].x, pts[0].x - p.x) ^
            Vec3f::newi32(pts[2].y - pts[0].y, pts[1].y - pts[0].y, pts[0].y - p.y);
    if u.z.abs() < 1f32 {
        return Vec3f::new(-1f32, 1f32, 1f32);
    }
    Vec3f::new(1f32 - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z)
}
<|endoftext|>