<commit_before>use crate::prelude::*;
use serde_derive::*;
use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::Write;
use std::rc::Rc;
use std::str;

use crate::handles::Handle;
use adapter_protocol::DisassembledInstruction;
use lldb::*;
use superslice::Ext;

struct Ranges {
    pub by_handle: HashMap<Handle, Rc<DisassembledRange>>,
    pub by_address: Vec<Rc<DisassembledRange>>,
}
pub struct AddressSpace {
    target: SBTarget,
    ranges: RefCell<Ranges>,
}

impl AddressSpace {
    pub fn new(target: &SBTarget) -> AddressSpace {
        AddressSpace {
            target: target.clone(),
            ranges: RefCell::new(Ranges {
                by_handle: HashMap::new(),
                by_address: Vec::new(),
            }),
        }
    }

    pub fn find_by_handle(&self, handle: Handle) -> Option<Rc<DisassembledRange>> {
        self.ranges.borrow_mut().by_handle.get(&handle).map(|dasm| dasm.clone())
    }

    fn find_by_address(&self, load_addr: Address) -> Option<Rc<DisassembledRange>> {
        let ranges = self.ranges.borrow_mut();
        let idx = ranges.by_address.upper_bound_by_key(&load_addr, |dasm| dasm.start_load_addr);
        if idx == 0 {
            None
        } else {
            let dasm = &ranges.by_address[idx - 1];
            if dasm.start_load_addr <= load_addr && load_addr < dasm.end_load_addr {
                Some(dasm.clone())
            } else {
                None
            }
        }
    }

    pub fn from_address(&self, load_addr: Address) -> Result<Rc<DisassembledRange>, Error> {
        if let Some(dasm) = self.find_by_address(load_addr) {
            return Ok(dasm);
        }

        let addr = SBAddress::from_load_address(load_addr, &self.target);
        debug!("{:?}", addr);

        let start_addr;
        let end_addr;
        let instructions;
        match addr.symbol() {
            Some(symbol) => {
                start_addr = symbol.start_address();
                end_addr = symbol.end_address();
                instructions = symbol.instructions(&self.target);
            }
            None => {
                // How many instructions to put into DisassembledRange if the address is not in scope of any symbol.
                const NO_SYMBOL_INSTRUCTIONS: u32 = 32;
                start_addr = addr.clone();
                instructions = self.target.read_instructions(&start_addr, NO_SYMBOL_INSTRUCTIONS + 1);
                end_addr = if instructions.len() > 0 {
                    let last_instr = instructions.instruction_at_index((instructions.len() - 1) as u32);
                    last_instr.address()
                } else {
                    start_addr.clone()
                };
            }
        }

        if instructions.len() > 0 {
            Ok(self.add(start_addr, end_addr, instructions))
        } else {
            bail!("Can't read instructions at that address.")
        }
    }

    fn add(
        &self,
        start_addr: SBAddress,
        end_addr: SBAddress,
        instructions: SBInstructionList,
    ) -> Rc<DisassembledRange> {
        let mut ranges = self.ranges.borrow_mut();
        let handle = Handle::new((ranges.by_handle.len() + 1000) as u32).unwrap();
        let instruction_addrs = instructions.iter().map(|i| i.address().load_address(&self.target)).collect();
        let start_load_addr = start_addr.load_address(&self.target);
        let end_load_addr = end_addr.load_address(&self.target);
        let source_name = match start_addr.symbol() {
            Some(symbol) => format!("@{}", symbol.name()),
            None => format!("@{:x}..{:x}", start_load_addr, end_load_addr),
        };
        let dasm = Rc::new(DisassembledRange {
            handle: handle,
            target: self.target.clone(),
            start_addr: start_addr,
            start_load_addr: start_load_addr,
            end_load_addr: end_load_addr,
            source_name: source_name,
            instructions: instructions,
            instruction_addresses: instruction_addrs,
        });
        ranges.by_handle.insert(handle, dasm.clone());
        let idx = ranges.by_address.lower_bound_by_key(&dasm.start_load_addr, |dasm| dasm.start_load_addr);
        ranges.by_address.insert(idx, dasm.clone());
        dasm
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct AdapterData {
    pub start: Address,
    pub end: Address,
    pub line_offsets: Vec<u32>,
}

#[derive(Debug)]
pub struct DisassembledRange {
    handle: Handle,
    target: SBTarget,
    start_addr: SBAddress,
    start_load_addr: Address,
    end_load_addr: Address,
    source_name: String,
    instructions: SBInstructionList,
    instruction_addresses: Vec<Address>,
}

impl DisassembledRange {
    pub fn handle(&self) -> Handle {
        self.handle
    }

    pub fn source_name(&self) -> &str {
        &self.source_name
    }

    pub fn line_num_by_address(&self, load_addr: Address) -> u32 {
        self.instruction_addresses.lower_bound(&load_addr) as u32 + 3
    }

    pub fn address_by_line_num(&self, line: u32) -> Address {
        self.instruction_addresses[line as usize - 3]
    }

    pub fn adapter_data(&self) -> AdapterData {
        let line_offsets = self.instruction_addresses.windows(2).map(|w| (w[1] - w[0]) as u32).collect();
        AdapterData {
            start: self.start_load_addr,
            end: self.end_load_addr,
            line_offsets: line_offsets,
        }
    }

    pub fn lines_from_adapter_data(adapter_data: &AdapterData) -> Vec<Address> {
        std::iter::repeat(adapter_data.start)
            .take(4) // lines are 1-based + 2 header lines + 1st instruction
            .chain(
                adapter_data.line_offsets.iter().scan(adapter_data.start, |addr, &delta| {
                    *addr += delta as u64;
                    Some(*addr)
                }),
            )
            .collect()
    }

    pub fn get_source_text(&self) -> String {
        let source_location: Cow<str> = match self.start_addr.line_entry() {
            Some(le) => format!("{}:{}", le.file_spec().path().display(), le.line()).into(),
            None => "unknown".into(),
        };

        let description: Cow<str> = match self.start_addr.symbol() {
            Some(symbol) => {
                let mut descr = SBStream::new();
                if symbol.get_description(&mut descr) {
                    match str::from_utf8(descr.data()) {
                        Ok(s) => Some(s.to_owned().into()),
                        Err(_) => None,
                    }
                } else {
                    None
                }
            }
            None => None,
        }
        .unwrap_or("No Symbol Info".into());

        let mut text = String::new();
        let _ = writeln!(text, "; {}", description);
        let _ = writeln!(text, "; Source location: {}", source_location);

        const MAX_INSTR_BYTES: usize = 8;
        let mut instr_data = vec![];
        let mut dump = String::new();
        for instr in self.instructions.iter() {
            let load_addr = instr.address().load_address(&self.target);
            instr_data.resize(instr.byte_size(), 0);
            instr.data(&self.target).read_raw_data(0, &mut instr_data).unwrap();
            dump.clear();
            for (i, b) in instr_data.iter().enumerate() {
                if i >= MAX_INSTR_BYTES {
                    let _ = write!(dump, ">");
                    break;
                }
                let _ = write!(dump, "{:02X} ", b);
            }
            let mnemonic = instr.mnemonic(&self.target);
            let operands = instr.operands(&self.target);
            let comment = instr.comment(&self.target);
            let comment_sep = if comment.is_empty() { "" } else { "  ; " };
            #[rustfmt::skip]
            let _ = writeln!(text, "{:08X}: {:<dumpwidth$} {:<6} {}{}{}", //.
                load_addr, dump, mnemonic, operands, comment_sep, comment,
                dumpwidth=MAX_INSTR_BYTES * 3 + 2
            );
        }

        text
    }
}

pub fn disassemble_byte_range(
    start: Address,
    count: usize,
    process: &SBProcess,
) -> Result<Vec<DisassembledInstruction>, Error> {
    let target = process.target();
    let mut buffer = Vec::new();
    buffer.resize(count, 0);
    process.read_memory(start, &mut buffer)?;

    let mut dis_instructions = Vec::new();
    let mut idx = 0;
    while idx < buffer.len() {
        let base_addr = SBAddress::from_load_address(start, &target);
        let instructions = target.get_instructions(&base_addr, &buffer[idx..]);
        if instructions.len() == 0 {
            let dis_instr = DisassembledInstruction {
                address: format!("0x{:X}", start as usize + idx),
                instruction: format!("db 0x{:02x}", buffer[idx]),
                instruction_bytes: Some(format!("{:02X}", buffer[idx])),
                ..Default::default()
            };
            dis_instructions.push(dis_instr);
            idx += 1;
        } else {
            for instr in instructions.iter() {
                dis_instructions.push(sbinstr_to_disinstr(&instr, &target, false));
                idx += instr.byte_size();
            }
        }
    }
    Ok(dis_instructions)
}

pub fn sbinstr_to_disinstr(instr: &SBInstruction, target: &SBTarget, resolve_symbols: bool) -> DisassembledInstruction {
    let mnemonic = instr.mnemonic(target);
    let operands = instr.operands(target);
    let comment = instr.comment(target);
    let comment_sep = if comment.is_empty() { "" } else { "  ; " };
    let instruction_str = format!("{:<6} {}{}{}", mnemonic, operands, comment_sep, comment);
    let mut dis_instr = DisassembledInstruction {
        address: format!("0x{:X}", instr.address().load_address(target)),
        instruction: instruction_str,
        ..Default::default()
    };
    let mut instr_bytes = Vec::new();
    instr_bytes.resize(instr.byte_size(), 0);
    if instr.data(target).read_raw_data(0, &mut instr_bytes).is_ok() {
        let mut bytes_str = String::with_capacity(instr_bytes.len() * 3);
        for b in instr_bytes.iter() {
            let _ = write!(bytes_str, "{:02X} ", b);
        }
        dis_instr.instruction_bytes = Some(bytes_str);
    }

    if resolve_symbols {
        if let Some(symbol) = instr.address().symbol() {
            dis_instr.symbol = Some(symbol.name().into());
        }
    }
    dis_instr
}

#[test]
fn test_adapter_data() {
    let addresses = &[10, 20, 23, 25, 30, 35, 41, 42, 50];
    let adapter_data = AdapterData {
        start: 10,
        end: 55,
        line_offsets: addresses.windows(2).map(|w| (w[1] - w[0]) as u32).collect(),
    };
    let addresses2 = DisassembledRange::lines_from_adapter_data(&adapter_data);
    assert_eq!(addresses, &addresses2[3..]);
}
<commit_msg>Include source info in disassembled instructions<commit_after>use crate::prelude::*;
use serde_derive::*;
use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::Write;
use std::rc::Rc;
use std::str;

use crate::handles::Handle;
use adapter_protocol::{DisassembledInstruction, Source};
use lldb::*;
use superslice::Ext;

struct Ranges {
    pub by_handle: HashMap<Handle, Rc<DisassembledRange>>,
    pub by_address: Vec<Rc<DisassembledRange>>,
}
pub struct AddressSpace {
    target: SBTarget,
    ranges: RefCell<Ranges>,
}

impl AddressSpace {
    pub fn new(target: &SBTarget) -> AddressSpace {
        AddressSpace {
            target: target.clone(),
            ranges: RefCell::new(Ranges {
                by_handle: HashMap::new(),
                by_address: Vec::new(),
            }),
        }
    }

    pub fn find_by_handle(&self, handle: Handle) -> Option<Rc<DisassembledRange>> {
        self.ranges.borrow_mut().by_handle.get(&handle).map(|dasm| dasm.clone())
    }

    fn find_by_address(&self, load_addr: Address) -> Option<Rc<DisassembledRange>> {
        let ranges = self.ranges.borrow_mut();
        let idx = ranges.by_address.upper_bound_by_key(&load_addr, |dasm| dasm.start_load_addr);
        if idx == 0 {
            None
        } else {
            let dasm = &ranges.by_address[idx - 1];
            if dasm.start_load_addr <= load_addr && load_addr < dasm.end_load_addr {
                Some(dasm.clone())
            } else {
                None
            }
        }
    }

    pub fn from_address(&self, load_addr: Address) -> Result<Rc<DisassembledRange>, Error> {
        if let Some(dasm) = self.find_by_address(load_addr) {
            return Ok(dasm);
        }

        let addr = SBAddress::from_load_address(load_addr, &self.target);
        debug!("{:?}", addr);

        let start_addr;
        let end_addr;
        let instructions;
        match addr.symbol() {
            Some(symbol) => {
                start_addr = symbol.start_address();
                end_addr = symbol.end_address();
                instructions = symbol.instructions(&self.target);
            }
            None => {
                // How many instructions to put into DisassembledRange if the address is not in scope of any symbol.
                const NO_SYMBOL_INSTRUCTIONS: u32 = 32;
                start_addr = addr.clone();
                instructions = self.target.read_instructions(&start_addr, NO_SYMBOL_INSTRUCTIONS + 1);
                end_addr = if instructions.len() > 0 {
                    let last_instr = instructions.instruction_at_index((instructions.len() - 1) as u32);
                    last_instr.address()
                } else {
                    start_addr.clone()
                };
            }
        }

        if instructions.len() > 0 {
            Ok(self.add(start_addr, end_addr, instructions))
        } else {
            bail!("Can't read instructions at that address.")
        }
    }

    fn add(
        &self,
        start_addr: SBAddress,
        end_addr: SBAddress,
        instructions: SBInstructionList,
    ) -> Rc<DisassembledRange> {
        let mut ranges = self.ranges.borrow_mut();
        let handle = Handle::new((ranges.by_handle.len() + 1000) as u32).unwrap();
        let instruction_addrs = instructions.iter().map(|i| i.address().load_address(&self.target)).collect();
        let start_load_addr = start_addr.load_address(&self.target);
        let end_load_addr = end_addr.load_address(&self.target);
        let source_name = match start_addr.symbol() {
            Some(symbol) => format!("@{}", symbol.name()),
            None => format!("@{:x}..{:x}", start_load_addr, end_load_addr),
        };
        let dasm = Rc::new(DisassembledRange {
            handle: handle,
            target: self.target.clone(),
            start_addr: start_addr,
            start_load_addr: start_load_addr,
            end_load_addr: end_load_addr,
            source_name: source_name,
            instructions: instructions,
            instruction_addresses: instruction_addrs,
        });
        ranges.by_handle.insert(handle, dasm.clone());
        let idx = ranges.by_address.lower_bound_by_key(&dasm.start_load_addr, |dasm| dasm.start_load_addr);
        ranges.by_address.insert(idx, dasm.clone());
        dasm
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct AdapterData {
    pub start: Address,
    pub end: Address,
    pub line_offsets: Vec<u32>,
}

#[derive(Debug)]
pub struct DisassembledRange {
    handle: Handle,
    target: SBTarget,
    start_addr: SBAddress,
    start_load_addr: Address,
    end_load_addr: Address,
    source_name: String,
    instructions: SBInstructionList,
    instruction_addresses: Vec<Address>,
}

impl DisassembledRange {
    pub fn handle(&self) -> Handle {
        self.handle
    }

    pub fn source_name(&self) -> &str {
        &self.source_name
    }

    pub fn line_num_by_address(&self, load_addr: Address) -> u32 {
        self.instruction_addresses.lower_bound(&load_addr) as u32 + 3
    }

    pub fn address_by_line_num(&self, line: u32) -> Address {
        self.instruction_addresses[line as usize - 3]
    }

    pub fn adapter_data(&self) -> AdapterData {
        let line_offsets = self.instruction_addresses.windows(2).map(|w| (w[1] - w[0]) as u32).collect();
        AdapterData {
            start: self.start_load_addr,
            end: self.end_load_addr,
            line_offsets: line_offsets,
        }
    }

    pub fn lines_from_adapter_data(adapter_data: &AdapterData) -> Vec<Address> {
        std::iter::repeat(adapter_data.start)
            .take(4) // lines are 1-based + 2 header lines + 1st instruction
            .chain(
                adapter_data.line_offsets.iter().scan(adapter_data.start, |addr, &delta| {
                    *addr += delta as u64;
                    Some(*addr)
                }),
            )
            .collect()
    }

    pub fn get_source_text(&self) -> String {
        let source_location: Cow<str> = match self.start_addr.line_entry() {
            Some(le) => format!("{}:{}", le.file_spec().path().display(), le.line()).into(),
            None => "unknown".into(),
        };

        let description: Cow<str> = match self.start_addr.symbol() {
            Some(symbol) => {
                let mut descr = SBStream::new();
                if symbol.get_description(&mut descr) {
                    match str::from_utf8(descr.data()) {
                        Ok(s) => Some(s.to_owned().into()),
                        Err(_) => None,
                    }
                } else {
                    None
                }
            }
            None => None,
        }
        .unwrap_or("No Symbol Info".into());

        let mut text = String::new();
        let _ = writeln!(text, "; {}", description);
        let _ = writeln!(text, "; Source location: {}", source_location);

        const MAX_INSTR_BYTES: usize = 8;
        let mut instr_data = vec![];
        let mut dump = String::new();
        for instr in self.instructions.iter() {
            let load_addr = instr.address().load_address(&self.target);
            instr_data.resize(instr.byte_size(), 0);
            instr.data(&self.target).read_raw_data(0, &mut instr_data).unwrap();
            dump.clear();
            for (i, b) in instr_data.iter().enumerate() {
                if i >= MAX_INSTR_BYTES {
                    let _ = write!(dump, ">");
                    break;
                }
                let _ = write!(dump, "{:02X} ", b);
            }
            let mnemonic = instr.mnemonic(&self.target);
            let operands = instr.operands(&self.target);
            let comment = instr.comment(&self.target);
            let comment_sep = if comment.is_empty() { "" } else { "  ; " };
            #[rustfmt::skip]
            let _ = writeln!(text, "{:08X}: {:<dumpwidth$} {:<6} {}{}{}", //.
                load_addr, dump, mnemonic, operands, comment_sep, comment,
                dumpwidth=MAX_INSTR_BYTES * 3 + 2
            );
        }

        text
    }
}

pub fn disassemble_byte_range(
    start: Address,
    count: usize,
    process: &SBProcess,
) -> Result<Vec<DisassembledInstruction>, Error> {
    let target = process.target();
    let mut buffer = Vec::new();
    buffer.resize(count, 0);
    process.read_memory(start, &mut buffer)?;

    let mut dis_instructions = Vec::new();
    let mut idx = 0;
    while idx < buffer.len() {
        let base_addr = SBAddress::from_load_address(start, &target);
        let instructions = target.get_instructions(&base_addr, &buffer[idx..]);
        if instructions.len() == 0 {
            let dis_instr = DisassembledInstruction {
                address: format!("0x{:X}", start as usize + idx),
                instruction: format!("db 0x{:02x}", buffer[idx]),
                instruction_bytes: Some(format!("{:02X}", buffer[idx])),
                ..Default::default()
            };
            dis_instructions.push(dis_instr);
            idx += 1;
        } else {
            for instr in instructions.iter() {
                dis_instructions.push(sbinstr_to_disinstr(&instr, &target, false));
                idx += instr.byte_size();
            }
        }
    }
    Ok(dis_instructions)
}

pub fn sbinstr_to_disinstr(instr: &SBInstruction, target: &SBTarget, resolve_symbols: bool) -> DisassembledInstruction {
    let mnemonic = instr.mnemonic(target);
    let operands = instr.operands(target);
    let comment = instr.comment(target);
    let comment_sep = if comment.is_empty() { "" } else { "  ; " };
    let address = instr.address();
    let instruction_str = format!("{:<6} {}{}{}", mnemonic, operands, comment_sep, comment);
    let mut dis_instr = DisassembledInstruction {
        address: format!("0x{:X}", address.load_address(target)),
        instruction: instruction_str,
        ..Default::default()
    };
    let mut instr_bytes = Vec::new();
    instr_bytes.resize(instr.byte_size(), 0);
    if instr.data(target).read_raw_data(0, &mut instr_bytes).is_ok() {
        let mut bytes_str = String::with_capacity(instr_bytes.len() * 3);
        for b in instr_bytes.iter() {
            let _ = write!(bytes_str, "{:02X} ", b);
        }
        dis_instr.instruction_bytes = Some(bytes_str);
    }

    if let Some(line_entry) = address.line_entry() {
        dis_instr.location = Some(Source {
            name: Some(line_entry.file_spec().filename().display().to_string()),
            path: Some(line_entry.file_spec().path().display().to_string()),
            ..Default::default()
        });
        dis_instr.line = Some(line_entry.line() as i64);
        dis_instr.column = Some(line_entry.column() as i64);
    }

    if resolve_symbols {
        if let Some(symbol) = instr.address().symbol() {
            dis_instr.symbol = Some(symbol.name().into());
        }
    }
    dis_instr
}

#[test]
fn test_adapter_data() {
    let addresses = &[10, 20, 23, 25, 30, 35, 41, 42, 50];
    let adapter_data = AdapterData {
        start: 10,
        end: 55,
        line_offsets: addresses.windows(2).map(|w| (w[1] - w[0]) as u32).collect(),
    };
    let addresses2 = DisassembledRange::lines_from_adapter_data(&adapter_data);
    assert_eq!(addresses, &addresses2[3..]);
}
<|endoftext|>


<commit_before>
use std::io;
use std::io::{BufWriter, ErrorKind, Write, Seek, SeekFrom, Result, Error};
use std::result;
use self::byteorder::{ByteOrder, WriteBytesExt, LittleEndian};

// decompressed_len returns the length of the decoded block.
pub fn decompressed_len(src: &[u8]) -> Result<usize> {
	src.read_u64::<LittleEndian>()
}

// Decompress reads the decoded form of src into dst and returns the length
// read.
// Returns an error if dst was not large enough to hold the entire decoded
// block.
fn decompress(dst: &[u8], src: &[u8]) -> io::Result<usize> {
	// TODO: Handle Error
	let dLen = decompressed_len(src).unwrap();
	// TODO FIX!!
	// For now, always assume 8 bytes used for src header length
	let s: usize = 8;

	if dst.len() < dLen {
        return Err(Error::new(ErrorKind::InvalidInput, "snappy: destination buffer is too short"));
    }

    let (d, offset, length): (isize, isize, isize);

    while s < src.len() {
    	match src[s] & 0x03 {
    		TAG_LITERAL => {
    			let mut x = src[s] >> 2;

    			match x {
	    			0..59 => s += 1,
    				60 => {
    					s += 2;
    					if s > src.len() {
    						return Err(ErrorKind::InvalidData)
    					};
    					x = src[s-1] as usize;
    				},
    				61 => {
    					s += 3;
    					if s > src.len() {
    						return Err(ErrorKind::InvalidData)
    					};
    					x = (src[s-2] as usize) | ((src[s-1]<<8) as usize);
    				},
    				62 => {
    					s += 4;
    					if s > src.len() {
    						return Err(ErrorKind::InvalidData)
    					};
    					x = (src[s-3] as usize) | ((src[s-2]<<8) as usize) | ((src[s-1]<<16) as usize);
    				},
    				63 => {
    					s += 5;
    					if s > src.len() {
    						return Err(ErrorKind::InvalidData)
    					};
    					x = (src[s-4] as usize) | ((src[s-3]<<8) as usize) | ((src[s-2]<<16) as usize) | ((src[s-1]<<24) as usize);
    				},
    				_
    			}
    			length = (x+1) as isize;

    			if length <= 0 {
			        return Err(Error::new(ErrorKind::InvalidInput, "snappy: unsupported literal length"));
    			}
    			if length > dst.len() - d || length > src.len() - s {
    				return Err(ErrorKind::InvalidData)
    			}

    			// Copy src[s: s+length] to dst[d:0]
    			for (id, is) in dst.split_at_mut(d).1.iter_mut().zip(src.split_at(s).1.split_at(s+length).0.iter()) {
			        *id = *is;
			    }
			    d += length;
			    s += length;
			    continue;
    		}
    	}
    }
}

<commit_msg>Iffy Decompress Port<commit_after>
use std::io;
use std::io::{BufWriter, ErrorKind, Write, Seek, SeekFrom, Result, Error};
use std::result;
use self::byteorder::{ByteOrder, WriteBytesExt, LittleEndian};

// decompressed_len returns the length of the decoded block.
pub fn decompressed_len(src: &[u8]) -> Result<usize> {
	src.read_u64::<LittleEndian>()
}

// Decompress reads the decoded form of src into dst and returns the length
// read.
// Returns an error if dst was not large enough to hold the entire decoded
// block.
fn decompress(dst: &mut [u8], src: &mut [u8]) -> io::Result<usize> {
	// TODO: Handle Error
	let dLen = decompressed_len(src).unwrap();
	// TODO FIX!!
	// For now, always assume 8 bytes used for src header length
	let mut s: usize = 8;

	if dst.len() < dLen {
        return Err(Error::new(ErrorKind::InvalidInput, "snappy: destination buffer is too short"));
    }

    let (d, offset, length): (isize, isize, isize);

    while s < src.len() {
    	match src[s] & 0x03 {

			// Parse a Literal Chunk
    		TAG_LITERAL => {

    			let mut x = src[s] >> 2;
    			match x {
	    			0..59 => s += 1,
    				60 => {
    					s += 2;
    					if s > src.len() {
    						return Err(ErrorKind::InvalidData)
    					};
    					x = src[s-1] as usize;
    				},
    				61 => {
    					s += 3;
    					if s > src.len() {
    						return Err(ErrorKind::InvalidData)
    					};
    					x = (src[s-2] as usize) | ((src[s-1]<<8) as usize);
    				},
    				62 => {
    					s += 4;
    					if s > src.len() {
    						return Err(ErrorKind::InvalidData)
    					};
    					x = (src[s-3] as usize) | ((src[s-2]<<8) as usize) | ((src[s-1]<<16) as usize);
    				},
    				63 => {
    					s += 5;
    					if s > src.len() {
    						return Err(ErrorKind::InvalidData)
    					};
    					x = (src[s-4] as usize) | ((src[s-3]<<8) as usize) | ((src[s-2]<<16) as usize) | ((src[s-1]<<24) as usize);
    				},
    				_ => {}
    			}
    			length = (x+1) as isize;

    			if length <= 0 {
			        return Err(Error::new(ErrorKind::InvalidInput, "snappy: unsupported literal length"));
    			}
    			if length > dst.len() - d || length > src.len() - s {
    				return Err(ErrorKind::InvalidData)
    			}

    			// Copy src[s: s+length] to dst[d:0]
    			for (id, is) in dst.split_at_mut(d).1.iter_mut().zip(src.split_at(s).1.split_at(s+length).0.iter()) {
			        *id = *is;
			    }
			    d += length;
			    s += length;
			    continue;
    		},

    		// Parse a Copy1 Chunk
    		TAG_COPY_1 => {
    			s+= 2;
    			if s > src.len() {
					return Err(ErrorKind::InvalidData)
				};
				length = 4 + (src[s-2] as isize)>>2&0x7;
				offset = ((src[s-2] as isize)&0xe0<<3) | (src[s-1] as isize);
    		},

    		// Parse a Copy2 Chunk
    		TAG_COPY_2 => {
    			s+= 3;
    			if s > src.len() {
					return Err(ErrorKind::InvalidData)
				};
				length = 1 + (src[s-3] as isize)>>2;
				offset = (src[s-2] as isize) | ((src[s-1] as isize)<<8);
    		},

    		// Parse a Copy4
    		TAG_COPY_4 => {
		        return Err(Error::new(ErrorKind::InvalidInput, "snappy: unsupported COPY_4 tag"));
    		},

    		_ => unreachable!()
    	};

    	let end = d + length;
    	if offset > || end > dst.len() {
			return Err(ErrorKind::InvalidData);
    	}
    	while d < end {
    		d += 1;
    		dst[d] = dst[d-offset];
    	}
    }
    if d != dLen {
		return Err(ErrorKind::InvalidData);
    }
    Ok(d)
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;

use rand::*;
use common::*;
use catrank_capnp::*;

pub type RequestBuilder<'a> = SearchResultList::Builder<'a>;
pub type ResponseBuilder<'a> = SearchResultList::Builder<'a>;
pub type Expectation = int;
pub type RequestReader<'a> = SearchResultList::Reader<'a>;
pub type ResponseReader<'a> = SearchResultList::Reader<'a>;

pub struct ScoredResult<'a> {
    score : f64,
    result : SearchResult::Reader<'a>
}

static URL_PREFIX : &'static str = "http://example.com";

pub fn setup_request(rng : &mut FastRand, request : SearchResultList::Builder) -> int {
    let count = rng.nextLessThan(1000) as uint;
    let mut goodCount : int = 0;

    let list = request.init_results(count);

    for i in range(0, count) {
        let result = list[i];
        result.set_score(1000.0 - i as f64);
        let url_size = rng.nextLessThan(100) as uint;

        let url_prefix_length = URL_PREFIX.as_bytes().len();
        let url = result.init_url(url_size + url_prefix_length);

        let bytes = url.as_mut_bytes();
        std::io::BufWriter::new(bytes).write(URL_PREFIX.as_bytes()).unwrap();

        for j in range(0, url_size) {
            bytes[j + url_prefix_length] = (97 + rng.nextLessThan(26)) as u8;
        }

        let isCat = rng.nextLessThan(8) == 0;
        let isDog = rng.nextLessThan(8) == 0;
        if isCat && !isDog {
            goodCount += 1;
        }

        let mut snippet = ~" ";

        let prefix = rng.nextLessThan(20) as uint;
        for _ in range(0, prefix) {
            snippet.push_str(WORDS[rng.nextLessThan(WORDS.len() as u32) as uint]);
        }
        if isCat { snippet.push_str("cat ") }
        if isDog { snippet.push_str("dog ") }

        let suffix = rng.nextLessThan(20) as uint;
        for _ in range(0, suffix) {
            snippet.push_str(WORDS[rng.nextLessThan(WORDS.len() as u32) as uint]);
        }

        result.set_snippet(snippet);
    }

    goodCount
}

pub fn handle_request(request : SearchResultList::Reader,
                     response : SearchResultList::Builder) {
    let mut scoredResults : ~[ScoredResult] = ~[];

    let results = request.get_results();
    for i in range(0, results.size()) {
        let result = results[i];
        let mut score = result.get_score();
        if result.get_snippet().contains(" cat ") {
            score *= 10000.0;
        }
        if result.get_snippet().contains(" dog ") {
            score /= 10000.0;
        }
        scoredResults.push(ScoredResult {score : score, result : result});
    }

    scoredResults.sort_by(|v1, v2| { if v1.score < v2.score { std::cmp::Less } else { std::cmp::Greater } });

    let list = response.init_results(scoredResults.len());
    for i in range(0, list.size()) {
        let item = list[i];
        let result = scoredResults[i];
        item.set_score(result.score);
        item.set_url(result.result.get_url());
        item.set_snippet(result.result.get_snippet());
    }
}

pub fn check_response(response : SearchResultList::Reader, expectedGoodCount : int) -> bool {
    let mut goodCount : int = 0;
    let results = response.get_results();
    for i in range(0, results.size()) {
        let result = results[i];
        if result.get_score() > 1001.0 {
            goodCount += 1;
        } else {
            break;
        }
    }
    return goodCount == expectedGoodCount;
}
<commit_msg>update benchmark to use StrBuf<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;

use rand::*;
use common::*;
use catrank_capnp::*;

pub type RequestBuilder<'a> = SearchResultList::Builder<'a>;
pub type ResponseBuilder<'a> = SearchResultList::Builder<'a>;
pub type Expectation = int;
pub type RequestReader<'a> = SearchResultList::Reader<'a>;
pub type ResponseReader<'a> = SearchResultList::Reader<'a>;

pub struct ScoredResult<'a> {
    score : f64,
    result : SearchResult::Reader<'a>
}

static URL_PREFIX : &'static str = "http://example.com";

pub fn setup_request(rng : &mut FastRand, request : SearchResultList::Builder) -> int {
    let count = rng.nextLessThan(1000) as uint;
    let mut goodCount : int = 0;

    let list = request.init_results(count);

    for i in range(0, count) {
        let result = list[i];
        result.set_score(1000.0 - i as f64);
        let url_size = rng.nextLessThan(100) as uint;

        let url_prefix_length = URL_PREFIX.as_bytes().len();
        let url = result.init_url(url_size + url_prefix_length);

        let bytes = url.as_mut_bytes();
        std::io::BufWriter::new(bytes).write(URL_PREFIX.as_bytes()).unwrap();

        for j in range(0, url_size) {
            bytes[j + url_prefix_length] = (97 + rng.nextLessThan(26)) as u8;
        }

        let isCat = rng.nextLessThan(8) == 0;
        let isDog = rng.nextLessThan(8) == 0;
        if isCat && !isDog {
            goodCount += 1;
        }

        let mut snippet = StrBuf::from_str(" ");

        let prefix = rng.nextLessThan(20) as uint;
        for _ in range(0, prefix) {
            snippet.push_str(WORDS[rng.nextLessThan(WORDS.len() as u32) as uint]);
        }
        if isCat { snippet.push_str("cat ") }
        if isDog { snippet.push_str("dog ") }

        let suffix = rng.nextLessThan(20) as uint;
        for _ in range(0, suffix) {
            snippet.push_str(WORDS[rng.nextLessThan(WORDS.len() as u32) as uint]);
        }

        result.set_snippet(snippet.as_slice());
    }

    goodCount
}

pub fn handle_request(request : SearchResultList::Reader,
                     response : SearchResultList::Builder) {
    let mut scoredResults : ~[ScoredResult] = ~[];

    let results = request.get_results();
    for i in range(0, results.size()) {
        let result = results[i];
        let mut score = result.get_score();
        if result.get_snippet().contains(" cat ") {
            score *= 10000.0;
        }
        if result.get_snippet().contains(" dog ") {
            score /= 10000.0;
        }
        scoredResults.push(ScoredResult {score : score, result : result});
    }

    scoredResults.sort_by(|v1, v2| { if v1.score < v2.score { std::cmp::Less } else { std::cmp::Greater } });

    let list = response.init_results(scoredResults.len());
    for i in range(0, list.size()) {
        let item = list[i];
        let result = scoredResults[i];
        item.set_score(result.score);
        item.set_url(result.result.get_url());
        item.set_snippet(result.result.get_snippet());
    }
}

pub fn check_response(response : SearchResultList::Reader, expectedGoodCount : int) -> bool {
    let mut goodCount : int = 0;
    let results = response.get_results();
    for i in range(0, results.size()) {
        let result = results[i];
        if result.get_score() > 1001.0 {
            goodCount += 1;
        } else {
            break;
        }
    }
    return goodCount == expectedGoodCount;
}
<|endoftext|>


<commit_before>use std::util;
use std::uint;
use std::num::{Zero, One};
use std::iterator::IteratorUtil;
use std::vec;
use extra::treemap::TreeMap;
use nalgebra::traits::norm::Norm;
use nalgebra::traits::division_ring::DivisionRing;
use nalgebra::traits::dim::Dim;
use nalgebra::traits::sub_dot::SubDot;
use nalgebra::traits::scalar_op::{ScalarMul, ScalarDiv};
use narrow::algorithm::simplex::Simplex;

#[deriving(Eq, ToStr, Clone)]
pub struct JohnsonSimplex<V, N>
{
  priv points:              ~[V],
  priv exchange_points:     ~[V],
  priv cofactors:           ~[N]
}

#[deriving(Eq, Clone)]
struct RecursionTemplate
{
  permutation_list: ~[uint],
  offsets:          ~[uint],
  sub_cofactors:    ~[uint],
  num_cofactors:    uint,
  num_leaves:       uint // useful only for printing…
}

// XXX: we use an Either instead of an Option since the compiler will generate
// something buggy with Option.
// static mut templates: Option<~[RecursionTemplate]> = None;
// FIXME: wont work with concurency…
static mut templates: Either<int, ~[RecursionTemplate]> = Left(42);

impl<V: Clone         +
        SubDot<N>    +
        ScalarMul<N> +
        ScalarDiv<N> +
        Zero         +
        Add<V, V>    +
        Dim,
     N: Ord          +
        Clone        +
        Copy         + // FIXME: needed?
        Eq           +
        DivisionRing +
        Ord          +
        Bounded>
JohnsonSimplex<V, N>
{
  pub fn new(initial_point: V) -> JohnsonSimplex<V, N>
  {
    let _dim       = Dim::dim::<V>();
    let expoints   = vec::with_capacity(_dim);
    let mut points = vec::with_capacity(_dim);

    JohnsonSimplex::make_permutation_lists::<V, N>();

    points.push(initial_point);

    let res = JohnsonSimplex {
      points:            points
      , exchange_points: expoints
      , cofactors:       vec::from_elem(
        unsafe {
          match templates
          {
            Right(ref mut l) => l[_dim].num_cofactors,
            Left(_)          => fail!("Recursion template was not intialized.")
          }
        }, Zero::zero())
    };

    res
  }

  fn make_permutation_lists()
  {
    unsafe {
      if templates.is_left()
      { templates = Right(~[]) }

      match templates
      {
        Left(_) => fail!("There seem to be a compiler error for the implementation" +
                         " of mutable static variables."),
        Right(ref mut t) =>
          for uint::iterate(t.len(), Dim::dim::<V>() + 1u) |dim|
          { t.push(JohnsonSimplex::make_permutation_list::<V, N>(dim)) }
      }
    }
  }

  // This is the tricky part of the algorithm. This generates all datas needed
  // to run the johson subalgorithm fastly. This should _not_ be run every time
  // the algorithm is executed. Instead, it should be pre-computed, or computed
  // only once for all. The resulting GC-managed list is intented to be shared
  // between all other simplicis with the same dimension.
  fn make_permutation_list(dim: uint) -> RecursionTemplate
  {
    // FIXME: the permutation list should be computed once for all, at compile
    // time. I dont know how to do that though…

    // The number of points on the biggest subsimplex
    let max_num_points      = dim + 1;

    let mut pts             = ~[]; // the result
    let mut offsets         = ~[];
    let mut sub_cofactors   = ~[];

    // the beginning of the last subsimplices list
    let mut last_dim_begin  = 0;

    // the end of the last subsimplices list
    let mut last_dim_end    = dim + 1 + 1;

    // the number of points of the last subsimplices
    let mut last_num_points = dim + 1;

    let mut map             = TreeMap::new::<~[uint], uint>();

    let mut cofactor_index  = 0;

    for uint::iterate(0, max_num_points) |i|
    { pts.push(i) }

    // initially push the whole simplex (will be removed at the end)
    pts.push(0);

    offsets.push(max_num_points + 1);

    // ... then remove one point each time
    for uint::iterate(0, dim + 1) |i|
    {
      // for each sub-simplex ...
      let mut curr      = last_dim_begin;
      let mut num_added = 0;

      while (curr != last_dim_end)
      {
        // ... iterate on it ...
        for uint::iterate(0, last_num_points) |j|
        {
          // ... and build all the sublist with one last point
          let mut sublist = ~[];

          // then extract the sub-simplex
          for uint::iterate(0, last_num_points) |k|
          {
            // we remove the j'th point
            if pts[curr + j] != pts[curr + k]
            { sublist.push(pts[curr + k]); }
          }

          // keep a trace of the removed point
          sublist.push(pts[curr + j]);

          match map.find(&sublist)
          {
            Some(&v) => sub_cofactors.push(v),
            None     => {
                          for sublist.iter().advance |&e|
                          {
                            pts.push(e);
                            num_added = num_added + 1;
                          }
                          sub_cofactors.push(cofactor_index);
                          map.insert(sublist, cofactor_index);
                          cofactor_index = cofactor_index + 1;
                        }
          }
        }

        let mut parent = ~[];
        for uint::iterate(0, last_num_points + 1) |k|
        { parent.push(pts[curr + k]) }

        match map.find(&parent)
        {
          Some(&p) => sub_cofactors.push(p),
          None => {
            sub_cofactors.push(cofactor_index);
            // There is no need to keep a place for the full simplex cofactor.
            // So we dont increase the cofactor buffer index for the first
            // iteration.
            cofactor_index = cofactor_index + if i == 0 { 0 } else { 1 };
          }
        }

        curr = curr + last_num_points + 1;
      }

      // initialize the next iteration with one less point
      last_dim_begin = last_dim_end ;
      last_dim_end = last_dim_end + num_added;
      offsets.push(last_dim_end);
      last_num_points = last_num_points - 1;
    }

    // cofactor indices for leaves
    for uint::iterate(0, max_num_points) |i|
    { sub_cofactors.push(*map.find(&~[max_num_points - 1 - i]).unwrap()) }

    // end to begin offsets
    offsets.unshift(0u);
    offsets.reverse();
    offsets.pop();

    let rev_offsets = offsets.map(|&e| pts.len() - e);
    let num_leaves = rev_offsets[0];

    // reverse points and cofectors
    pts.reverse();
    sub_cofactors.reverse();

    // remove the full simplex
    let num_pts = pts.len();
    pts.truncate(num_pts - max_num_points - 1);
    sub_cofactors.truncate(num_pts - max_num_points - 1);

    RecursionTemplate {
      offsets:          rev_offsets,
      permutation_list: pts,
      num_cofactors:    sub_cofactors[0] + 1,
      sub_cofactors:    sub_cofactors,
      num_leaves:       num_leaves
    }
  }

  pub fn reset(&mut self, pt: V)
  {
    self.points.clear();
    self.points.push(pt);
  }

  fn do_project_origin(&mut self, reduce: bool) -> V
  {
    // FIXME: for optimization: do special case when there are only 1 point ?
    let _0                   = Zero::zero::<N>();
    let _1                   = One::one::<N>();
    let max_num_pts          = self.points.len();
    let recursion            =
      unsafe {
        match templates
        {
          Left(_) => fail!("There seem to be a compiler error for the implementation" +
                        " of mutable static variables."),
          Right(ref mut t) => &t[max_num_pts - 1]
        }
      };
    let mut curr_num_pts     = 1u;
    let mut curr             = max_num_pts;

    for uint::iterate(0u, max_num_pts) |i|
    { self.cofactors[recursion.num_cofactors - 1 - i] = _1.clone(); }

    /*
     * first loop: compute all the cofactors
     */
    let mut recursion_offsets_skip_2 = recursion.offsets.iter();
    recursion_offsets_skip_2.next(); // Skip the two first entries
    recursion_offsets_skip_2.next();
    for recursion_offsets_skip_2.advance |&end|
    {
      // for each sub-simplex ...
      let mut _i = curr;
      while (_i != end)
      {
        let mut cofactor = Zero::zero::<N>();
        let j_pid        = recursion.permutation_list[curr];
        let k_pid        = recursion.permutation_list[curr + 1u];

        // ... with curr_num_pts points ...
        for uint::iterate(0u, curr_num_pts) |i|
        {
          // ... compute its cofactor.
          let i_pid        = recursion.permutation_list[curr + 1 + i];
          let sub_cofactor = self.cofactors[recursion.sub_cofactors[curr + 1 + i]].clone();
          let delta = sub_cofactor *
                      self.points[k_pid].sub_dot(&self.points[j_pid],
                                                 &self.points[i_pid]);

          cofactor = cofactor + delta;
        }

        self.cofactors[recursion.sub_cofactors[curr]] = cofactor;
        curr = curr + curr_num_pts + 1; // points + removed point + cofactor id

        _i = _i + curr_num_pts + 1;
      }

      curr_num_pts = curr_num_pts + 1;
    }

    /*
     * second loop: find the subsimplex containing the projection
     */
    let _invalid_cofactor = Bounded::max_value::<N>();
    let mut offsets_iter = recursion.offsets.rev_iter();
    offsets_iter.next(); // skip the first offset
    for offsets_iter.advance |&end|
    {
      // for each sub-simplex ...
      let mut _i = curr;
      while (_i != end)
      {
        let mut foundit = true;
        // ... with curr_num_pts points permutations ...
        for uint::iterate(0u, curr_num_pts) |i|
        {
          // ... see if its cofactor is positive
          let cof_id = _i - (i + 1) * curr_num_pts;
          let cof    = self.cofactors[recursion.sub_cofactors[cof_id]].clone();
          if cof > _0
          {
            // invalidate the children cofactor
            if curr_num_pts > 1
            {
              let subcofid = recursion.sub_cofactors[cof_id + 1];

              if self.cofactors[subcofid] > _0
              { self.cofactors[subcofid] = _invalid_cofactor.clone() }
            }

            // dont concider this sub-simplex if it has been invalidated by its
            // parent(s)
            if cof == _invalid_cofactor
            { foundit = false }
          }
          else // we found a negative cofactor: no projection possible here
          { foundit = false }
        }

        if foundit
        {
          // we found a projection!
          // re-run the same iteration but, this time, compute the projection
          let mut total_cof = _0.clone();
          let mut proj      = Zero::zero::<V>();

          for uint::iterate(0u, curr_num_pts) |i|
          {
            // ... see if its cofactor is positive
            let id    = _i - (i + 1) * curr_num_pts;
            let cof   = self.cofactors[recursion.sub_cofactors[id]].clone();

            total_cof = total_cof + cof;
            proj = proj +
              self.points[recursion.permutation_list[id]].scalar_mul(&cof);
          }

          if reduce // we need to reduce the simplex
          {
            // FIXME: is it possible to do that without copy?
            // Maybe with some kind of cross-vector-swap?
            for uint::iterate(0u, curr_num_pts) |i|
            {
              let id = _i - (i + 1) * curr_num_pts;
              self.exchange_points.push(self.points[recursion.permutation_list[id]].clone());
            }

            util::swap(&mut self.exchange_points, &mut self.points);
            self.exchange_points.clear();
          }

          proj.scalar_div_inplace(&total_cof);

          return proj
        }

        _i = _i - curr_num_pts * curr_num_pts;
      }

      curr = end;
      curr_num_pts = curr_num_pts - 1;
    }

    util::unreachable();
  }
}

impl<V: Clone         +
        SubDot<N>    +
        ScalarMul<N> +
        ScalarDiv<N> +
        Zero         +
        Add<V, V>    +
        Norm<N>      +
        Eq           +
        Dim,
     N: Ord          +
        Clone        +
        Copy         + // FIXME: needed?
        Eq           +
        DivisionRing +
        Ord          +
        Bounded>
     Simplex<V, N> for JohnsonSimplex<V, N>
{
  pub fn new(initial_point: V) -> JohnsonSimplex<V, N>
  { JohnsonSimplex::new(initial_point) }

  pub fn dimension(&self) -> uint
  { self.points.len() - 1 }

  pub fn max_sq_len(&self) -> N
  { self.points.iter().transform(|v| v.sqnorm()).max().unwrap() }

  pub fn contains_point(&self, pt: &V) -> bool
  { self.points.iter().any(|v| pt == v) }

  pub fn add_point(&mut self, pt: V)
  {
    assert!(self.points.len() <= Dim::dim::<V>());
    self.points.push(pt)
  }

  pub fn project_origin_and_reduce(&mut self) -> V
  { self.do_project_origin(true) }

  pub fn project_origin(&mut self) -> V
  { self.do_project_origin(false) }
}

impl ToStr for RecursionTemplate
{
  fn to_str(&self) -> ~str
  {
    let mut res  = ~"RecursionTemplate { ";
    let mut curr = self.num_leaves;
    let mut dim  = 1;

    res = res + "num_cofactors: " + self.num_cofactors.to_str();

    let mut recursion_offsets_skip_1 = self.offsets.iter();
    recursion_offsets_skip_1.next(); // Skip the two first entries

    for recursion_offsets_skip_1.advance |&off|
    {
      while (curr != off)
      {
        res = res + "\n(@" + self.sub_cofactors[curr].to_str() + " -> ";

        for uint::iterate(0u, dim) |i|
        {
          res = res + self.permutation_list[i + curr].to_str();
          if i != dim - 1
          { res = res + " "; }
        }

        res = res + " - ";

        for uint::iterate(1u, dim) |i|
        {
          res = res + self.sub_cofactors[i + curr].to_str();
          if i != dim - 1
          { res = res + " "; }
        }

        res  = res + ")";
        curr = curr + dim;
      }

      dim += 1;
    }

    res = res + " }\n";

    res = res + "offsets: " + self.offsets.to_str();

    res
  }
}
<commit_msg>Use TLS instead of a 'static mut' variable to store JohnsonSimplex recursion scheme.<commit_after>use std::util;
use std::uint;
use std::num::{Zero, One};
use std::iterator::IteratorUtil;
use std::vec;
use std::local_data;
use extra::treemap::TreeMap;
use nalgebra::traits::norm::Norm;
use nalgebra::traits::division_ring::DivisionRing;
use nalgebra::traits::dim::Dim;
use nalgebra::traits::sub_dot::SubDot;
use nalgebra::traits::scalar_op::{ScalarMul, ScalarDiv};
use narrow::algorithm::simplex::Simplex;

#[deriving(Eq, ToStr, Clone)]
pub struct JohnsonSimplex<V, N>
{
  priv points:              ~[V],
  priv exchange_points:     ~[V],
  priv cofactors:           ~[N]
}

#[deriving(Eq, Clone)]
struct RecursionTemplate
{
  permutation_list: ~[uint],
  offsets:          ~[uint],
  sub_cofactors:    ~[uint],
  num_cofactors:    uint,
  num_leaves:       uint // useful only for printing…
}

fn key_recursion_template(_: @mut ~[@RecursionTemplate]) { }

impl<V: Clone + SubDot<N> + ScalarMul<N> + ScalarDiv<N> + Zero + Add<V, V> + Dim,
     N: Ord + Clone + Copy + Eq + DivisionRing + Ord + Bounded>
JohnsonSimplex<V, N>
{
  pub fn new(initial_point: V) -> JohnsonSimplex<V, N>
  {
    let _dim       = Dim::dim::<V>();
    let expoints   = vec::with_capacity(_dim);
    let mut points = vec::with_capacity(_dim);

    JohnsonSimplex::make_permutation_lists::<V, N>();

    points.push(initial_point);

    let res = JohnsonSimplex {
      points:            points
      , exchange_points: expoints
      , cofactors:       vec::from_elem(
        unsafe {
          do local_data::get(key_recursion_template) |lopt|
          {
            match lopt
            {
              Some(l) => l[_dim].num_cofactors,
              None    => fail!("Recursion template was not intialized.")
            }
          }
        }
      , Zero::zero())
    };

    res
  }

  fn make_permutation_lists()
  {
    unsafe {
      do local_data::get(key_recursion_template) |lopt|
      {
        if lopt.is_none()
        {
          local_data::set(key_recursion_template, @mut ~[])
        }
      }

      do local_data::get(key_recursion_template) |lopt|
      {
        let template = lopt.unwrap();

        for uint::iterate(template.len(), Dim::dim::<V>() + 1u) |dim|
        { template.push(@JohnsonSimplex::make_permutation_list::<V, N>(dim)) }
      }
    }
  }

  // This is the tricky part of the algorithm. This generates all datas needed
  // to run the johson subalgorithm fastly. This should _not_ be run every time
  // the algorithm is executed. Instead, it should be pre-computed, or computed
  // only once for all. The resulting GC-managed list is intented to be shared
  // between all other simplicis with the same dimension.
  fn make_permutation_list(dim: uint) -> RecursionTemplate
  {
    // FIXME: the permutation list should be computed once for all, at compile
    // time. I dont know how to do that though…

    // The number of points on the biggest subsimplex
    let max_num_points      = dim + 1;

    let mut pts             = ~[]; // the result
    let mut offsets         = ~[];
    let mut sub_cofactors   = ~[];

    // the beginning of the last subsimplices list
    let mut last_dim_begin  = 0;

    // the end of the last subsimplices list
    let mut last_dim_end    = dim + 1 + 1;

    // the number of points of the last subsimplices
    let mut last_num_points = dim + 1;

    let mut map             = TreeMap::new::<~[uint], uint>();

    let mut cofactor_index  = 0;

    for uint::iterate(0, max_num_points) |i|
    { pts.push(i) }

    // initially push the whole simplex (will be removed at the end)
    pts.push(0);

    offsets.push(max_num_points + 1);

    // ... then remove one point each time
    for uint::iterate(0, dim + 1) |i|
    {
      // for each sub-simplex ...
      let mut curr      = last_dim_begin;
      let mut num_added = 0;

      while (curr != last_dim_end)
      {
        // ... iterate on it ...
        for uint::iterate(0, last_num_points) |j|
        {
          // ... and build all the sublist with one last point
          let mut sublist = ~[];

          // then extract the sub-simplex
          for uint::iterate(0, last_num_points) |k|
          {
            // we remove the j'th point
            if pts[curr + j] != pts[curr + k]
            { sublist.push(pts[curr + k]); }
          }

          // keep a trace of the removed point
          sublist.push(pts[curr + j]);

          match map.find(&sublist)
          {
            Some(&v) => sub_cofactors.push(v),
            None     => {
                          for sublist.iter().advance |&e|
                          {
                            pts.push(e);
                            num_added = num_added + 1;
                          }
                          sub_cofactors.push(cofactor_index);
                          map.insert(sublist, cofactor_index);
                          cofactor_index = cofactor_index + 1;
                        }
          }
        }

        let mut parent = ~[];
        for uint::iterate(0, last_num_points + 1) |k|
        { parent.push(pts[curr + k]) }

        match map.find(&parent)
        {
          Some(&p) => sub_cofactors.push(p),
          None => {
            sub_cofactors.push(cofactor_index);
            // There is no need to keep a place for the full simplex cofactor.
            // So we dont increase the cofactor buffer index for the first
            // iteration.
            cofactor_index = cofactor_index + if i == 0 { 0 } else { 1 };
          }
        }

        curr = curr + last_num_points + 1;
      }

      // initialize the next iteration with one less point
      last_dim_begin = last_dim_end ;
      last_dim_end = last_dim_end + num_added;
      offsets.push(last_dim_end);
      last_num_points = last_num_points - 1;
    }

    // cofactor indices for leaves
    for uint::iterate(0, max_num_points) |i|
    { sub_cofactors.push(*map.find(&~[max_num_points - 1 - i]).unwrap()) }

    // end to begin offsets
    offsets.unshift(0u);
    offsets.reverse();
    offsets.pop();

    let rev_offsets = offsets.map(|&e| pts.len() - e);
    let num_leaves = rev_offsets[0];

    // reverse points and cofectors
    pts.reverse();
    sub_cofactors.reverse();

    // remove the full simplex
    let num_pts = pts.len();
    pts.truncate(num_pts - max_num_points - 1);
    sub_cofactors.truncate(num_pts - max_num_points - 1);

    RecursionTemplate {
      offsets:          rev_offsets,
      permutation_list: pts,
      num_cofactors:    sub_cofactors[0] + 1,
      sub_cofactors:    sub_cofactors,
      num_leaves:       num_leaves
    }
  }

  pub fn reset(&mut self, pt: V)
  {
    self.points.clear();
    self.points.push(pt);
  }

  fn do_project_origin(&mut self, reduce: bool) -> V
  {
    // FIXME: for optimization: do special case when there are only 1 point ?
    let _0                   = Zero::zero::<N>();
    let _1                   = One::one::<N>();
    let max_num_pts          = self.points.len();
    let recursion            =
      unsafe {
        do local_data::get(key_recursion_template) |template_opt|
        { template_opt.unwrap()[max_num_pts - 1] }
      };
    let mut curr_num_pts     = 1u;
    let mut curr             = max_num_pts;

    for uint::iterate(0u, max_num_pts) |i|
    { self.cofactors[recursion.num_cofactors - 1 - i] = _1.clone(); }

    /*
     * first loop: compute all the cofactors
     */
    let mut recursion_offsets_skip_2 = recursion.offsets.iter();
    recursion_offsets_skip_2.next(); // Skip the two first entries
    recursion_offsets_skip_2.next();
    for recursion_offsets_skip_2.advance |&end|
    {
      // for each sub-simplex ...
      let mut _i = curr;
      while (_i != end)
      {
        let mut cofactor = Zero::zero::<N>();
        let j_pid        = recursion.permutation_list[curr];
        let k_pid        = recursion.permutation_list[curr + 1u];

        // ... with curr_num_pts points ...
        for uint::iterate(0u, curr_num_pts) |i|
        {
          // ... compute its cofactor.
          let i_pid        = recursion.permutation_list[curr + 1 + i];
          let sub_cofactor = self.cofactors[recursion.sub_cofactors[curr + 1 + i]].clone();
          let delta = sub_cofactor *
                      self.points[k_pid].sub_dot(&self.points[j_pid],
                                                 &self.points[i_pid]);

          cofactor = cofactor + delta;
        }

        self.cofactors[recursion.sub_cofactors[curr]] = cofactor;
        curr = curr + curr_num_pts + 1; // points + removed point + cofactor id

        _i = _i + curr_num_pts + 1;
      }

      curr_num_pts = curr_num_pts + 1;
    }

    /*
     * second loop: find the subsimplex containing the projection
     */
    let _invalid_cofactor = Bounded::max_value::<N>();
    let mut offsets_iter = recursion.offsets.rev_iter();
    offsets_iter.next(); // skip the first offset
    for offsets_iter.advance |&end|
    {
      // for each sub-simplex ...
      let mut _i = curr;
      while (_i != end)
      {
        let mut foundit = true;
        // ... with curr_num_pts points permutations ...
        for uint::iterate(0u, curr_num_pts) |i|
        {
          // ... see if its cofactor is positive
          let cof_id = _i - (i + 1) * curr_num_pts;
          let cof    = self.cofactors[recursion.sub_cofactors[cof_id]].clone();
          if cof > _0
          {
            // invalidate the children cofactor
            if curr_num_pts > 1
            {
              let subcofid = recursion.sub_cofactors[cof_id + 1];

              if self.cofactors[subcofid] > _0
              { self.cofactors[subcofid] = _invalid_cofactor.clone() }
            }

            // dont concider this sub-simplex if it has been invalidated by its
            // parent(s)
            if cof == _invalid_cofactor
            { foundit = false }
          }
          else // we found a negative cofactor: no projection possible here
          { foundit = false }
        }

        if foundit
        {
          // we found a projection!
          // re-run the same iteration but, this time, compute the projection
          let mut total_cof = _0.clone();
          let mut proj      = Zero::zero::<V>();

          for uint::iterate(0u, curr_num_pts) |i|
          {
            // ... see if its cofactor is positive
            let id    = _i - (i + 1) * curr_num_pts;
            let cof   = self.cofactors[recursion.sub_cofactors[id]].clone();

            total_cof = total_cof + cof;
            proj = proj +
              self.points[recursion.permutation_list[id]].scalar_mul(&cof);
          }

          if reduce // we need to reduce the simplex
          {
            // FIXME: is it possible to do that without copy?
            // Maybe with some kind of cross-vector-swap?
            for uint::iterate(0u, curr_num_pts) |i|
            {
              let id = _i - (i + 1) * curr_num_pts;
              self.exchange_points.push(self.points[recursion.permutation_list[id]].clone());
            }

            util::swap(&mut self.exchange_points, &mut self.points);
            self.exchange_points.clear();
          }

          proj.scalar_div_inplace(&total_cof);

          return proj
        }

        _i = _i - curr_num_pts * curr_num_pts;
      }

      curr = end;
      curr_num_pts = curr_num_pts - 1;
    }

    util::unreachable();
  }
}

impl<V: Clone         +
        SubDot<N>    +
        ScalarMul<N> +
        ScalarDiv<N> +
        Zero         +
        Add<V, V>    +
        Norm<N>      +
        Eq           +
        Dim,
     N: Ord          +
        Clone        +
        Copy         + // FIXME: needed?
        Eq           +
        DivisionRing +
        Ord          +
        Bounded>
     Simplex<V, N> for JohnsonSimplex<V, N>
{
  pub fn new(initial_point: V) -> JohnsonSimplex<V, N>
  { JohnsonSimplex::new(initial_point) }

  pub fn dimension(&self) -> uint
  { self.points.len() - 1 }

  pub fn max_sq_len(&self) -> N
  { self.points.iter().transform(|v| v.sqnorm()).max().unwrap() }

  pub fn contains_point(&self, pt: &V) -> bool
  { self.points.iter().any(|v| pt == v) }

  pub fn add_point(&mut self, pt: V)
  {
    assert!(self.points.len() <= Dim::dim::<V>());
    self.points.push(pt)
  }

  pub fn project_origin_and_reduce(&mut self) -> V
  { self.do_project_origin(true) }

  pub fn project_origin(&mut self) -> V
  { self.do_project_origin(false) }
}

impl ToStr for RecursionTemplate
{
  fn to_str(&self) -> ~str
  {
    let mut res  = ~"RecursionTemplate { ";
    let mut curr = self.num_leaves;
    let mut dim  = 1;

    res = res + "num_cofactors: " + self.num_cofactors.to_str();

    let mut recursion_offsets_skip_1 = self.offsets.iter();
    recursion_offsets_skip_1.next(); // Skip the two first entries

    for recursion_offsets_skip_1.advance |&off|
    {
      while (curr != off)
      {
        res = res + "\n(@" + self.sub_cofactors[curr].to_str() + " -> ";

        for uint::iterate(0u, dim) |i|
        {
          res = res + self.permutation_list[i + curr].to_str();
          if i != dim - 1
          { res = res + " "; }
        }

        res = res + " - ";

        for uint::iterate(1u, dim) |i|
        {
          res = res + self.sub_cofactors[i + curr].to_str();
          if i != dim - 1
          { res = res + " "; }
        }

        res  = res + ")";
        curr = curr + dim;
      }

      dim += 1;
    }

    res = res + " }\n";

    res = res + "offsets: " + self.offsets.to_str();

    res
  }
}
<|endoftext|>


<commit_before>pub mod window {
    use cocoa::base::id;
    use cocoa::foundation::NSUInteger;
    use cocoa::appkit::NSWindow;
    use core_graphics::geometry::{CGRect, CGPoint, CGSize};
    use objc::runtime::{BOOL, Class, YES};
    use raw::{AsRaw, FromRaw, FromRawError, IntoRaw};
    use std::error::Error;
    use std::fmt;
    use std::marker;
    use std::ops::{Deref, DerefMut};
    use sys::{MTLClearColor, MTLPixelFormat};
    use winit;
    use winit::os::macos::WindowExt;
    use {ClearColor, Device, PixelFormat, RenderPassDescriptor, Texture};

    pub use winit::{
        CursorState,
        Event,
        MonitorId,
        MouseCursor,
        PollEventsIterator,
        WaitEventsIterator,
        ElementState,
        MouseButton,
        MouseScrollDelta,
        Touch,
        TouchPhase,
        ScanCode,
        VirtualKeyCode
    };

    pub struct WindowBuilder {
        window: winit::WindowBuilder,
        device: Device
    }

    #[derive(Debug)]
    pub enum CreationError {
        ViewCreation(ViewError),
        Winit(winit::CreationError)
    }

    impl fmt::Display for CreationError {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}", self.description())
        }
    }

    impl Error for CreationError {
        fn description(&self) -> &str {
            match *self {
                CreationError::ViewCreation(ref e) => e.description(),
                CreationError::Winit(ref e) => e.description()
            }
        }

        fn cause(&self) -> Option<&Error> {
            match *self {
                CreationError::ViewCreation(ref e) => Some(e),
                CreationError::Winit(ref e) => Some(e)
            }
        }
    }

    impl From<winit::CreationError> for CreationError {
        fn from(error: winit::CreationError) -> Self {
            CreationError::Winit(error)
        }
    }

    impl From<ViewError> for CreationError {
        fn from(error: ViewError) -> Self {
            CreationError::ViewCreation(error)
        }
    }

    impl WindowBuilder {
        /// Initializes a new `WindowBuilder` with default values.
        #[inline]
        pub fn new(device: Device) -> Self {
            WindowBuilder {
                window: winit::WindowBuilder::new(),
                device: device
            }
        }

        /// Requests the window to be of specific dimensions.
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_dimensions(width, height), ..self}
        }

        /// Sets a minimum dimension size for the window
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_min_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_min_dimensions(width, height), ..self}
        }

        /// Sets a maximum dimension size for the window
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_max_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_max_dimensions(width, height), ..self}
        }

        /// Requests a specific title for the window.
        #[inline]
        pub fn with_title(self, title: String) -> WindowBuilder {
            WindowBuilder {window: self.window.with_title(title), ..self}
        }

        /// Requests fullscreen mode.
        ///
        /// If you don't specify dimensions for the window, it will match the monitor's.
        #[inline]
        pub fn with_fullscreen(self, monitor: MonitorId) -> WindowBuilder {
            WindowBuilder {window: self.window.with_fullscreen(monitor), ..self}
        }

        /// Sets whether the window will be initially hidden or visible.
        #[inline]
        pub fn with_visibility(self, visible: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_visibility(visible), ..self}
        }

        /// Sets whether the background of the window should be transparent.
        #[inline]
        pub fn with_transparency(self, transparent: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_transparency(transparent), ..self}
        }

        /// Sets whether the window should have a border, a title bar, etc.
        #[inline]
        pub fn with_decorations(self, decorations: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_decorations(decorations), ..self}
        }

        /// Enables multitouch
        #[inline]
        pub fn with_multitouch(self) -> WindowBuilder {
            WindowBuilder {window: self.window.with_multitouch(), ..self}
        }

        /// Builds the window.
        ///
        /// Error should be very rare and only occur in case of permission denied, incompatible system,
        /// out of memory, etc.
        pub fn build(self) -> Result<Window, CreationError> {
            let window = try!(self.window.build());
            let view = try!(View::new(&window, self.device));

            unsafe {
                let native_window: id = window.get_nswindow() as id;
                native_window.setContentView_(view.mtk_view.0);
            }

            Ok(Window {
                window: window,
                view: view
            })
        }

        /// Builds the window.
        ///
        /// The context is build in a *strict* way. That means that if the backend couldn't give
        /// you what you requested, an `Err` will be returned.
        #[inline]
        pub fn build_strict(self) -> Result<Window, CreationError> {
            self.build()
        }
    }

    pub struct Window {
        window: winit::Window,
        pub view: View
    }

    impl Window {
        pub fn poll_events(&self) -> PollEventsIterator {
            self.window.poll_events()
        }

        pub fn wait_events(&self) -> WaitEventsIterator {
            self.window.wait_events()
        }

        pub fn window(&self) -> Ref<winit::Window> {
            Ref(&self.window)
        }
    }

    pub struct View {
        mtk_view: MtkView
    }

    struct MtkView(id);
    impl_from_into_raw!(MtkView, of class "MTKView");

    impl View {
        fn new(window: &winit::Window, device: Device) -> Result<Self, ViewError> {
            let window_origin = {
                let (x, y) = try!(window.get_position().ok_or(ViewError::no_window()));
                CGPoint { x: x as f64, y: y as f64 }
            };

            let window_size = {
                let (w, h) = try!(window.get_inner_size().ok_or(ViewError::no_window()));
                CGSize { width: w as f64, height: h as f64 }
            };

            let view_frame = CGRect { origin: window_origin, size: window_size };

            let view_object: id = unsafe {
                // Dummy function to ensure that we link against MetalKit
                #[allow(dead_code)]
                #[link(name = "MetalKit", kind = "framework")]
                extern "C" {
                    fn MTKModelIOVertexDescriptorFromMetal(metalDescriptor: id) -> id;
                }

                let view_class = Class::get("MTKView").expect("Could not find MTKView class");
                let view: id = msg_send![view_class, alloc];
                msg_send![view, initWithFrame:view_frame
                                       device:device.into_raw()]
            };

            Ok(View {
                mtk_view: try!(MtkView::from_raw(view_object)),
            })
        }

        fn raw_view(&self) -> id {
            self.mtk_view.0
        }

        pub fn device<'a>(&self) -> Option<PhantomRef<'a, Device>> {
            let device = unsafe {
                Device::from_raw(msg_send![*self.mtk_view.as_raw(), device])
            };
            device.ok().map(|d| PhantomRef(d, marker::PhantomData))
        }

        pub fn device_mut<'a>(&mut self) -> Option<PhantomRefMut<'a, Device>> {
            let device = unsafe {
                Device::from_raw(msg_send![*self.mtk_view.as_raw(), device])
            };
            device.ok().map(|d| PhantomRefMut(d, marker::PhantomData))
        }

        pub fn clear_color(&self) -> ClearColor {
            let color: MTLClearColor = unsafe {
                msg_send![*self.mtk_view.as_raw(), clearColor]
            };
            color.into()
        }

        pub fn set_clear_color<C: Into<MTLClearColor>>(&mut self, clear_color: C) {
            unsafe { msg_send![*self.mtk_view.as_raw(), setClearColor:clear_color.into()] }
        }

        pub fn clear_depth(&self) -> f64 {
            unsafe { msg_send![*self.mtk_view.as_raw(), clearDepth] }
        }

        pub fn set_clear_depth(&mut self, clear_depth: f64) {
            unsafe { msg_send![*self.mtk_view.as_raw(), setClearDepth:clear_depth] }
        }

        pub fn clear_stencil(&self) -> u32 {
            unsafe { msg_send![*self.mtk_view.as_raw(), clearStencil] }
        }

        pub fn set_clear_stencil(&mut self, clear_stencil: u32) {
            unsafe { msg_send![*self.mtk_view.as_raw(), setClearStencil:clear_stencil] }
        }

        pub fn color_pixel_format(&self) -> PixelFormat {
            let pixel_format: MTLPixelFormat = unsafe {
                msg_send![*self.mtk_view.as_raw(), colorPixelFormat]
            };
            pixel_format.into()
        }

        pub fn set_color_pixel_format<P: Into<MTLPixelFormat>>(&mut self, color_pixel_format: P) {
            unsafe { msg_send![*self.mtk_view.as_raw(), setColorPixelFormat:color_pixel_format.into()] }
        }

        pub fn depth_stencil_pixel_format(&self) -> PixelFormat {
            let pixel_format: MTLPixelFormat = unsafe {
                msg_send![*self.mtk_view.as_raw(), depthStencilPixelFormat]
            };
            pixel_format.into()
        }

        pub fn set_depth_stencil_pixel_format<P: Into<MTLPixelFormat>>(&mut self, depth_stencil_pixel_format: P) {
            unsafe { msg_send![*self.mtk_view.as_raw(), setDepthStencilPixelFormat:depth_stencil_pixel_format.into()] }
        }

        pub fn sample_count(&self) -> usize {
            let sample_count: NSUInteger = unsafe {
                msg_send![*self.mtk_view.as_raw(), sampleCount]
            };
            sample_count as usize
        }

        pub fn set_sample_count(&mut self, sample_count: usize) {
            let sample_count = sample_count as NSUInteger;
            unsafe { msg_send![*self.mtk_view.as_raw(), setSampleCount:sample_count] }
        }

        pub fn current_render_pass_descriptor(&self) -> Option<PhantomRef<RenderPassDescriptor>> {
            let descriptor: id = unsafe { msg_send![self.raw_view(), currentRenderPassDescriptor] };
            FromRaw::from_raw(descriptor).ok().map(|d| PhantomRef(d, marker::PhantomData))
        }

        pub fn current_depth_stencil_texture(&self) -> Option<PhantomRef<Texture>> {
            let texture: id = unsafe { msg_send![self.raw_view(), depthStencilTexture] };
            FromRaw::from_raw(texture).ok().map(|t| PhantomRef(t, marker::PhantomData))
        }

        pub fn multisample_color_texture(&self) -> Option<PhantomRef<Texture>> {
            let texture: id = unsafe { msg_send![self.raw_view(), multisampleColorTexture] };
            FromRaw::from_raw(texture).ok().map(|t| PhantomRef(t, marker::PhantomData))
        }

        pub fn preferred_frames_per_second(&self) -> usize {
            let fps: NSUInteger = unsafe { msg_send![self.raw_view(), sampleCount] };
            fps as usize
        }

        pub fn set_preferred_frames_per_second(&self, preferred_fps: usize) {
            let preferred_fps = preferred_fps as NSUInteger;
            unsafe { msg_send![self.raw_view(), setPreferredFramesPerSecond:preferred_fps] }
        }

        pub fn is_paused(&self) -> bool {
            let is_paused: BOOL = unsafe { msg_send![self.raw_view(), isPaused] };
            is_paused == YES
        }

        pub fn draw(&self) {
            unsafe { msg_send![self.raw_view(), draw] }
        }
    }

    #[derive(Clone, Debug)]
    pub struct ViewError(ViewErrorInner);

    #[derive(Clone, Debug)]
    enum ViewErrorInner {
        NoWindow,
        CreateError(FromRawError)
    }

    impl ViewError {
        fn no_window() -> Self {
            ViewError(ViewErrorInner::NoWindow)
        }
    }

    impl fmt::Display for ViewError {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}", self.description())
        }
    }

    impl Error for ViewError {
        fn description(&self) -> &str {
            match self.0 {
                ViewErrorInner::NoWindow => "The native window no longer exists",
                ViewErrorInner::CreateError(_) => "There was an issue creating the view",
            }
        }

        fn cause(&self) -> Option<&Error> {
            if let ViewErrorInner::CreateError(ref e) = self.0 {
                Some(e)
            } else {
                None
            }
        }
    }

    impl From<FromRawError> for ViewError {
        fn from(error: FromRawError) -> Self {
            ViewError(ViewErrorInner::CreateError(error))
        }
    }

    pub struct Ref<'a, T: 'a>(&'a T);

    impl<'a, T> Deref for Ref<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            self.0
        }
    }

    pub struct PhantomRef<'a, T: 'a>(T, marker::PhantomData<&'a ()>);

    impl<'a, T> Deref for PhantomRef<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }

    pub struct PhantomRefMut<'a, T: 'a>(T, marker::PhantomData<&'a mut ()>);

    impl<'a, T> Deref for PhantomRefMut<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }

    impl<'a, T> DerefMut for PhantomRefMut<'a, T> {
        fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
            &mut self.0
        }
    }
}
<commit_msg>Remove trailing spaces<commit_after>pub mod window {
    use cocoa::base::id;
    use cocoa::foundation::NSUInteger;
    use cocoa::appkit::NSWindow;
    use core_graphics::geometry::{CGRect, CGPoint, CGSize};
    use objc::runtime::{BOOL, Class, YES};
    use raw::{AsRaw, FromRaw, FromRawError, IntoRaw};
    use std::error::Error;
    use std::fmt;
    use std::marker;
    use std::ops::{Deref, DerefMut};
    use sys::{MTLClearColor, MTLPixelFormat};
    use winit;
    use winit::os::macos::WindowExt;
    use {ClearColor, Device, PixelFormat, RenderPassDescriptor, Texture};

    pub use winit::{
        CursorState,
        Event,
        MonitorId,
        MouseCursor,
        PollEventsIterator,
        WaitEventsIterator,
        ElementState,
        MouseButton,
        MouseScrollDelta,
        Touch,
        TouchPhase,
        ScanCode,
        VirtualKeyCode
    };

    pub struct WindowBuilder {
        window: winit::WindowBuilder,
        device: Device
    }

    #[derive(Debug)]
    pub enum CreationError {
        ViewCreation(ViewError),
        Winit(winit::CreationError)
    }

    impl fmt::Display for CreationError {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}", self.description())
        }
    }

    impl Error for CreationError {
        fn description(&self) -> &str {
            match *self {
                CreationError::ViewCreation(ref e) => e.description(),
                CreationError::Winit(ref e) => e.description()
            }
        }

        fn cause(&self) -> Option<&Error> {
            match *self {
                CreationError::ViewCreation(ref e) => Some(e),
                CreationError::Winit(ref e) => Some(e)
            }
        }
    }

    impl From<winit::CreationError> for CreationError {
        fn from(error: winit::CreationError) -> Self {
            CreationError::Winit(error)
        }
    }

    impl From<ViewError> for CreationError {
        fn from(error: ViewError) -> Self {
            CreationError::ViewCreation(error)
        }
    }

    impl WindowBuilder {
        /// Initializes a new `WindowBuilder` with default values.
        #[inline]
        pub fn new(device: Device) -> Self {
            WindowBuilder {
                window: winit::WindowBuilder::new(),
                device: device
            }
        }

        /// Requests the window to be of specific dimensions.
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_dimensions(width, height), ..self}
        }

        /// Sets a minimum dimension size for the window
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_min_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_min_dimensions(width, height), ..self}
        }

        /// Sets a maximum dimension size for the window
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_max_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_max_dimensions(width, height), ..self}
        }

        /// Requests a specific title for the window.
        #[inline]
        pub fn with_title(self, title: String) -> WindowBuilder {
            WindowBuilder {window: self.window.with_title(title), ..self}
        }

        /// Requests fullscreen mode.
        ///
        /// If you don't specify dimensions for the window, it will match the monitor's.
        #[inline]
        pub fn with_fullscreen(self, monitor: MonitorId) -> WindowBuilder {
            WindowBuilder {window: self.window.with_fullscreen(monitor), ..self}
        }

        /// Sets whether the window will be initially hidden or visible.
        #[inline]
        pub fn with_visibility(self, visible: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_visibility(visible), ..self}
        }

        /// Sets whether the background of the window should be transparent.
        #[inline]
        pub fn with_transparency(self, transparent: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_transparency(transparent), ..self}
        }

        /// Sets whether the window should have a border, a title bar, etc.
        #[inline]
        pub fn with_decorations(self, decorations: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_decorations(decorations), ..self}
        }

        /// Enables multitouch
        #[inline]
        pub fn with_multitouch(self) -> WindowBuilder {
            WindowBuilder {window: self.window.with_multitouch(), ..self}
        }

        /// Builds the window.
        ///
        /// Error should be very rare and only occur in case of permission denied, incompatible system,
        /// out of memory, etc.
        pub fn build(self) -> Result<Window, CreationError> {
            let window = try!(self.window.build());
            let view = try!(View::new(&window, self.device));

            unsafe {
                let native_window: id = window.get_nswindow() as id;
                native_window.setContentView_(view.mtk_view.0);
            }

            Ok(Window {
                window: window,
                view: view
            })
        }

        /// Builds the window.
        ///
        /// The context is build in a *strict* way. That means that if the backend couldn't give
        /// you what you requested, an `Err` will be returned.
        #[inline]
        pub fn build_strict(self) -> Result<Window, CreationError> {
            self.build()
        }
    }

    pub struct Window {
        window: winit::Window,
        pub view: View
    }

    impl Window {
        pub fn poll_events(&self) -> PollEventsIterator {
            self.window.poll_events()
        }

        pub fn wait_events(&self) -> WaitEventsIterator {
            self.window.wait_events()
        }

        pub fn window(&self) -> Ref<winit::Window> {
            Ref(&self.window)
        }
    }

    pub struct View {
        mtk_view: MtkView
    }

    struct MtkView(id);
    impl_from_into_raw!(MtkView, of class "MTKView");

    impl View {
        fn new(window: &winit::Window, device: Device) -> Result<Self, ViewError> {
            let window_origin = {
                let (x, y) = try!(window.get_position().ok_or(ViewError::no_window()));
                CGPoint { x: x as f64, y: y as f64 }
            };

            let window_size = {
                let (w, h) = try!(window.get_inner_size().ok_or(ViewError::no_window()));
                CGSize { width: w as f64, height: h as f64 }
            };

            let view_frame = CGRect { origin: window_origin, size: window_size };

            let view_object: id = unsafe {
                // Dummy function to ensure that we link against MetalKit
                #[allow(dead_code)]
                #[link(name = "MetalKit", kind = "framework")]
                extern "C" {
                    fn MTKModelIOVertexDescriptorFromMetal(metalDescriptor: id) -> id;
                }

                let view_class = Class::get("MTKView").expect("Could not find MTKView class");
                let view: id = msg_send![view_class, alloc];
                msg_send![view, initWithFrame:view_frame
                                       device:device.into_raw()]
            };

            Ok(View {
                mtk_view: try!(MtkView::from_raw(view_object)),
            })
        }

        fn raw_view(&self) -> id {
            self.mtk_view.0
        }

        pub fn device<'a>(&self) -> Option<PhantomRef<'a, Device>> {
            let device = unsafe {
                Device::from_raw(msg_send![*self.mtk_view.as_raw(), device])
            };
            device.ok().map(|d| PhantomRef(d, marker::PhantomData))
        }

        pub fn device_mut<'a>(&mut self) -> Option<PhantomRefMut<'a, Device>> {
            let device = unsafe {
                Device::from_raw(msg_send![*self.mtk_view.as_raw(), device])
            };
            device.ok().map(|d| PhantomRefMut(d, marker::PhantomData))
        }

        pub fn clear_color(&self) -> ClearColor {
            let color: MTLClearColor = unsafe {
                msg_send![*self.mtk_view.as_raw(), clearColor]
            };
            color.into()
        }

        pub fn set_clear_color<C: Into<MTLClearColor>>(&mut self, clear_color: C) {
            unsafe { msg_send![*self.mtk_view.as_raw(), setClearColor:clear_color.into()] }
        }

        pub fn clear_depth(&self) -> f64 {
            unsafe { msg_send![*self.mtk_view.as_raw(), clearDepth] }
        }

        pub fn set_clear_depth(&mut self, clear_depth: f64) {
            unsafe { msg_send![*self.mtk_view.as_raw(), setClearDepth:clear_depth] }
        }

        pub fn clear_stencil(&self) -> u32 {
            unsafe { msg_send![*self.mtk_view.as_raw(), clearStencil] }
        }

        pub fn set_clear_stencil(&mut self, clear_stencil: u32) {
            unsafe { msg_send![*self.mtk_view.as_raw(), setClearStencil:clear_stencil] }
        }

        pub fn color_pixel_format(&self) -> PixelFormat {
            let pixel_format: MTLPixelFormat = unsafe {
                msg_send![*self.mtk_view.as_raw(), colorPixelFormat]
            };
            pixel_format.into()
        }

        pub fn set_color_pixel_format<P: Into<MTLPixelFormat>>(&mut self, color_pixel_format: P) {
            unsafe { msg_send![*self.mtk_view.as_raw(), setColorPixelFormat:color_pixel_format.into()] }
        }

        pub fn depth_stencil_pixel_format(&self) -> PixelFormat {
            let pixel_format: MTLPixelFormat = unsafe {
                msg_send![*self.mtk_view.as_raw(), depthStencilPixelFormat]
            };
            pixel_format.into()
        }

        pub fn set_depth_stencil_pixel_format<P: Into<MTLPixelFormat>>(&mut self, depth_stencil_pixel_format: P) {
            unsafe { msg_send![*self.mtk_view.as_raw(), setDepthStencilPixelFormat:depth_stencil_pixel_format.into()] }
        }

        pub fn sample_count(&self) -> usize {
            let sample_count: NSUInteger = unsafe {
                msg_send![*self.mtk_view.as_raw(), sampleCount]
            };
            sample_count as usize
        }

        pub fn set_sample_count(&mut self, sample_count: usize) {
            let sample_count = sample_count as NSUInteger;
            unsafe { msg_send![*self.mtk_view.as_raw(), setSampleCount:sample_count] }
        }

        pub fn current_render_pass_descriptor(&self) -> Option<PhantomRef<RenderPassDescriptor>> {
            let descriptor: id = unsafe { msg_send![self.raw_view(), currentRenderPassDescriptor] };
            FromRaw::from_raw(descriptor).ok().map(|d| PhantomRef(d, marker::PhantomData))
        }

        pub fn current_depth_stencil_texture(&self) -> Option<PhantomRef<Texture>> {
            let texture: id = unsafe { msg_send![self.raw_view(), depthStencilTexture] };
            FromRaw::from_raw(texture).ok().map(|t| PhantomRef(t, marker::PhantomData))
        }

        pub fn multisample_color_texture(&self) -> Option<PhantomRef<Texture>> {
            let texture: id = unsafe { msg_send![self.raw_view(), multisampleColorTexture] };
            FromRaw::from_raw(texture).ok().map(|t| PhantomRef(t, marker::PhantomData))
        }

        pub fn preferred_frames_per_second(&self) -> usize {
            let fps: NSUInteger = unsafe { msg_send![self.raw_view(), sampleCount] };
            fps as usize
        }

        pub fn set_preferred_frames_per_second(&self, preferred_fps: usize) {
            let preferred_fps = preferred_fps as NSUInteger;
            unsafe { msg_send![self.raw_view(), setPreferredFramesPerSecond:preferred_fps] }
        }

        pub fn is_paused(&self) -> bool {
            let is_paused: BOOL = unsafe { msg_send![self.raw_view(), isPaused] };
            is_paused == YES
        }

        pub fn draw(&self) {
            unsafe { msg_send![self.raw_view(), draw] }
        }
    }

    #[derive(Clone, Debug)]
    pub struct ViewError(ViewErrorInner);

    #[derive(Clone, Debug)]
    enum ViewErrorInner {
        NoWindow,
        CreateError(FromRawError)
    }

    impl ViewError {
        fn no_window() -> Self {
            ViewError(ViewErrorInner::NoWindow)
        }
    }

    impl fmt::Display for ViewError {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}", self.description())
        }
    }

    impl Error for ViewError {
        fn description(&self) -> &str {
            match self.0 {
                ViewErrorInner::NoWindow => "The native window no longer exists",
                ViewErrorInner::CreateError(_) => "There was an issue creating the view",
            }
        }

        fn cause(&self) -> Option<&Error> {
            if let ViewErrorInner::CreateError(ref e) = self.0 {
                Some(e)
            } else {
                None
            }
        }
    }

    impl From<FromRawError> for ViewError {
        fn from(error: FromRawError) -> Self {
            ViewError(ViewErrorInner::CreateError(error))
        }
    }

    pub struct Ref<'a, T: 'a>(&'a T);

    impl<'a, T> Deref for Ref<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            self.0
        }
    }

    pub struct PhantomRef<'a, T: 'a>(T, marker::PhantomData<&'a ()>);

    impl<'a, T> Deref for PhantomRef<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }

    pub struct PhantomRefMut<'a, T: 'a>(T, marker::PhantomData<&'a mut ()>);

    impl<'a, T> Deref for PhantomRefMut<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }

    impl<'a, T> DerefMut for PhantomRefMut<'a, T> {
        fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
            &mut self.0
        }
    }
}
<|endoftext|>