<commit_before>use definitions::program::{Instruction, Program, Target, Value};
use definitions::typedef::*;
use error::*;
use std::cmp::Ordering;

const STACK_COUNT: usize = 2;
const REGISTER_COUNT: usize = 4;

/// The whole state of the VM
pub struct VM {
    /// The instructions that are currently executed
    image_data: Vec<Instruction>,
    /// The current program counter
    pc: Address,
    data_stacks: [Vec<Value>; STACK_COUNT],
    data_registers: [Value; REGISTER_COUNT],
    /// A register for holding infomation about a recent comparison
    cmp_reg: Option<Ordering>,
    call_stack: Vec<Address>,
    /// A boolean lock used for jumps
    skip_advance: bool,
}

impl VM {
    /// Creates a new VM state for executing programs
    pub fn new() -> VM {
        VM {
            image_data: Vec::new(),
            pc: 0,
            data_stacks: [Vec::new(), Vec::new()],
            data_registers: [Value::Nil, Value::Nil, Value::Nil, Value::Nil],
            cmp_reg: None,
            call_stack: Vec::new(),
            skip_advance: false,
        }
    }

    // # Maintainance functions

    /// Executes the given program
    pub fn exec(&mut self, program: Program) -> VMResult<()> {
        self.reset();
        self.load_program(program);

        while self.pc < self.image_data.len() {
            let current_instruction = self.image_data[self.pc].clone();

            match current_instruction {
                Instruction::Halt => break,

                Instruction::Add(dest, src) => self.add(dest, src)?,
                Instruction::Sub(dest, src) => self.sub(dest, src)?,
                Instruction::Div(dest, src) => self.div(dest, src)?,
                Instruction::Mul(dest, src) => self.mul(dest, src)?,
                Instruction::Mod(dest, src) => self.modulo(dest, src)?,

                Instruction::Cmp(target_a, target_b) => self.cmp(target_a, target_b)?,
                Instruction::Jmp(addr) => self.jmp(addr),
                Instruction::JmpLt(addr) => self.jmp_lt(addr),
                Instruction::JmpGt(addr) => self.jmp_gt(addr),
                Instruction::JmpEq(addr) => self.jmp_eq(addr),

                Instruction::Push(dest, value) => self.push(dest, value),
                Instruction::Mov(dest, src) => self.mov(dest, src)?,
                Instruction::Swp(target_a, target_b) => self.swp(target_a, target_b)?,

                Instruction::Call(addr) => self.call(addr),
                Instruction::Ret => self.ret()?,
            }

            self.advance_pc();
        }

        Ok(())
    }

    /// Loads the instructions of the given program to the VM's state
    fn load_program(&mut self, program: Program) {
        self.image_data = program.instructions;
    }

    /// Resets the VM to a clean state
    fn reset(&mut self) {
        *self = VM::new();
    }

    fn reset_cmp(&mut self) {
        self.cmp_reg = None;
    }

    /// Advances the program counter
    fn advance_pc(&mut self) {
        if !self.skip_advance {
            self.pc += 1;
        } else {
            self.skip_advance = false;
        }
    }

    /// Return the value at the specified target. The value will be consumed
    /// from the target.
    fn pop(&mut self, target: &Target) -> VMResult<Value> {
        match target {
            &Target::Register(index) => {
                let value = self.data_registers[index].clone();
                self.data_registers[index] = Value::Nil;

                Ok(value)
            }
            &Target::Stack(index) => {
                if let Some(value) = self.data_stacks[index].pop() {
                    Ok(value)
                } else {
                    bail!("unable to pop value off an empty stack");
                }
            }
        }
    }

    // # Instruction functions

    /// Adds the value of the src target to the value of the dest target
    fn add(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let dest_value = self.pop(&dest)?;
        let src_value = self.pop(&src)?;

        self.push(dest, dest_value + src_value);

        Ok(())
    }

    /// Subtracts the value of the src target from the value of the dest target
    fn sub(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let dest_value = self.pop(&dest)?;
        let src_value = self.pop(&src)?;

        self.push(dest, dest_value - src_value);

        Ok(())
    }

    /// Divides the value of the dest target through the value of the src target
    fn div(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let dest_value = self.pop(&dest)?;
        let src_value = self.pop(&src)?;

        self.push(dest, dest_value / src_value);

        Ok(())
    }

    /// Multiplies the value of the dest target with the value of the src target
    fn mul(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let dest_value = self.pop(&dest)?;
        let src_value = self.pop(&src)?;

        self.push(dest, dest_value * src_value);

        Ok(())
    }

    /// Applies the modulo operator on the value of the dest target using the
    /// value of the src target
    fn modulo(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let dest_value = self.pop(&dest)?;
        let src_value = self.pop(&src)?;

        self.push(dest, dest_value * src_value);

        Ok(())
    }

    /// Compares the top values of the two targets and saves the result to
    /// `self.cmp_reg`
    fn cmp(&mut self, target_a: Target, target_b: Target) -> VMResult<()> {
        self.reset_cmp();

        let target_a_value = self.pop(&target_a)?;
        let target_b_value = self.pop(&target_b)?;

        if target_a_value < target_b_value {
            self.cmp_reg = Some(Ordering::Less);
        } else if target_a_value > target_b_value {
            self.cmp_reg = Some(Ordering::Greater);
        } else if target_a_value == target_b_value {
            self.cmp_reg = Some(Ordering::Equal);
        }

        Ok(())
    }

    /// Jumps unconditionally to the specified address
    fn jmp(&mut self, addr: Address) {
        self.pc = addr;
        self.skip_advance = true;
    }

    /// Jumps if the last compare got the result `Some(Ordering::Less)`
    fn jmp_lt(&mut self, addr: Address) {
        if self.cmp_reg == Some(Ordering::Less) {
            self.jmp(addr);
            self.reset_cmp();
        }
    }

    /// Jumps if the last compare got the result `Some(Ordering::Greater)`
    fn jmp_gt(&mut self, addr: Address) {
        if self.cmp_reg == Some(Ordering::Greater) {
            self.jmp(addr);
            self.reset_cmp();
        }
    }

    /// Jumps if the last compare got the result `Some(Ordering::Equal)`
    fn jmp_eq(&mut self, addr: Address) {
        if self.cmp_reg == Some(Ordering::Equal) {
            self.jmp(addr);
            self.reset_cmp();
        }
    }

    /// Pushes the given value to the given target
    fn push(&mut self, dest: Target, value: Value) {
        match dest {
            Target::Register(index) => self.data_registers[index] = value,
            Target::Stack(index) => self.data_stacks[index].push(value),
        }
    }

    /// Moves the top value of the src target to the dest target
    fn mov(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let src_value = self.pop(&src)?;
        self.push(dest, src_value);

        Ok(())
    }

    /// Swaps the top values of the targets
    fn swp(&mut self, target_a: Target, target_b: Target) -> VMResult<()> {
        let a_value = self.pop(&target_a)?;
        let b_value = self.pop(&target_b)?;

        self.push(target_a, b_value);
        self.push(target_b, a_value);

        Ok(())
    }

    /// Calls the function at the specified address saving the return address
    /// to the call stack
    fn call(&mut self, addr: Address) {
        self.call_stack.push(self.pc + 1);
        self.jmp(addr);
    }

    /// Returns from an ongoing function call
    fn ret(&mut self) -> VMResult<()> {
        if self.call_stack.is_empty() {
            bail!("unable to return from an empty call stack");
        }

        let retur_addr = self.call_stack.pop().unwrap();

        self.jmp(retur_addr);

        Ok(())
    }
}
<commit_msg>Small renamings<commit_after>use definitions::program::{Instruction, Program, Target, Value};
use definitions::typedef::*;
use error::*;
use std::cmp::Ordering;

const STACK_COUNT: usize = 2;
const REGISTER_COUNT: usize = 4;

/// The whole state of the VM
pub struct VM {
    /// The instructions that are currently executed
    image_data: Vec<Instruction>,
    /// The current program counter
    pc: Address,
    data_stacks: [Vec<Value>; STACK_COUNT],
    data_registers: [Value; REGISTER_COUNT],
    /// A register for holding infomation about a recent comparison
    cmp_register: Option<Ordering>,
    call_stack: Vec<Address>,
    /// A boolean used for lock the program counter
    pc_locked: bool,
}

impl VM {
    /// Creates a new VM state for executing programs
    pub fn new() -> VM {
        VM {
            image_data: Vec::new(),
            pc: 0,
            data_stacks: [Vec::new(), Vec::new()],
            data_registers: [Value::Nil, Value::Nil, Value::Nil, Value::Nil],
            cmp_register: None,
            call_stack: Vec::new(),
            pc_locked: false,
        }
    }

    // # Maintainance functions

    /// Executes the given program
    pub fn exec(&mut self, program: Program) -> VMResult<()> {
        self.reset();
        self.load_program(program);

        while self.pc < self.image_data.len() {
            let current_instruction = self.image_data[self.pc].clone();

            match current_instruction {
                Instruction::Halt => break,

                Instruction::Add(dest, src) => self.add(dest, src)?,
                Instruction::Sub(dest, src) => self.sub(dest, src)?,
                Instruction::Div(dest, src) => self.div(dest, src)?,
                Instruction::Mul(dest, src) => self.mul(dest, src)?,
                Instruction::Mod(dest, src) => self.modulo(dest, src)?,

                Instruction::Cmp(target_a, target_b) => self.cmp(target_a, target_b)?,
                Instruction::Jmp(addr) => self.jmp(addr),
                Instruction::JmpLt(addr) => self.jmp_lt(addr),
                Instruction::JmpGt(addr) => self.jmp_gt(addr),
                Instruction::JmpEq(addr) => self.jmp_eq(addr),

                Instruction::Push(dest, value) => self.push(dest, value),
                Instruction::Mov(dest, src) => self.mov(dest, src)?,
                Instruction::Swp(target_a, target_b) => self.swp(target_a, target_b)?,

                Instruction::Call(addr) => self.call(addr),
                Instruction::Ret => self.ret()?,
            }

            self.advance_pc();
        }

        Ok(())
    }

    /// Loads the instructions of the given program to the VM's state
    fn load_program(&mut self, program: Program) {
        self.image_data = program.instructions;
    }

    /// Resets the VM to a clean state
    fn reset(&mut self) {
        *self = VM::new();
    }

    fn reset_cmp(&mut self) {
        self.cmp_register = None;
    }

    /// Advances the program counter
    fn advance_pc(&mut self) {
        if self.pc_locked {
            self.pc_locked = false;
        } else {
            self.pc += 1;
        }
    }

    /// Return the value at the specified target. The value will be consumed
    /// from the target.
    fn pop(&mut self, target: &Target) -> VMResult<Value> {
        match target {
            &Target::Register(index) => {
                let value = self.data_registers[index].clone();
                self.data_registers[index] = Value::Nil;

                Ok(value)
            }
            &Target::Stack(index) => {
                if let Some(value) = self.data_stacks[index].pop() {
                    Ok(value)
                } else {
                    bail!("unable to pop value off an empty stack");
                }
            }
        }
    }

    // # Instruction functions

    /// Adds the value of the src target to the value of the dest target
    fn add(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let dest_value = self.pop(&dest)?;
        let src_value = self.pop(&src)?;

        self.push(dest, dest_value + src_value);

        Ok(())
    }

    /// Subtracts the value of the src target from the value of the dest target
    fn sub(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let dest_value = self.pop(&dest)?;
        let src_value = self.pop(&src)?;

        self.push(dest, dest_value - src_value);

        Ok(())
    }

    /// Divides the value of the dest target through the value of the src target
    fn div(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let dest_value = self.pop(&dest)?;
        let src_value = self.pop(&src)?;

        self.push(dest, dest_value / src_value);

        Ok(())
    }

    /// Multiplies the value of the dest target with the value of the src target
    fn mul(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let dest_value = self.pop(&dest)?;
        let src_value = self.pop(&src)?;

        self.push(dest, dest_value * src_value);

        Ok(())
    }

    /// Applies the modulo operator on the value of the dest target using the
    /// value of the src target
    fn modulo(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let dest_value = self.pop(&dest)?;
        let src_value = self.pop(&src)?;

        self.push(dest, dest_value * src_value);

        Ok(())
    }

    /// Compares the top values of the two targets and saves the result to
    /// `self.cmp_register`
    fn cmp(&mut self, target_a: Target, target_b: Target) -> VMResult<()> {
        self.reset_cmp();

        let target_a_value = self.pop(&target_a)?;
        let target_b_value = self.pop(&target_b)?;

        if target_a_value < target_b_value {
            self.cmp_register = Some(Ordering::Less);
        } else if target_a_value > target_b_value {
            self.cmp_register = Some(Ordering::Greater);
        } else if target_a_value == target_b_value {
            self.cmp_register = Some(Ordering::Equal);
        }

        Ok(())
    }

    /// Jumps unconditionally to the specified address
    fn jmp(&mut self, addr: Address) {
        self.pc = addr;
        self.pc_locked = true;
    }

    /// Jumps if the last compare got the result `Some(Ordering::Less)`
    fn jmp_lt(&mut self, addr: Address) {
        if self.cmp_register == Some(Ordering::Less) {
            self.jmp(addr);
            self.reset_cmp();
        }
    }

    /// Jumps if the last compare got the result `Some(Ordering::Greater)`
    fn jmp_gt(&mut self, addr: Address) {
        if self.cmp_register == Some(Ordering::Greater) {
            self.jmp(addr);
            self.reset_cmp();
        }
    }

    /// Jumps if the last compare got the result `Some(Ordering::Equal)`
    fn jmp_eq(&mut self, addr: Address) {
        if self.cmp_register == Some(Ordering::Equal) {
            self.jmp(addr);
            self.reset_cmp();
        }
    }

    /// Pushes the given value to the given target
    fn push(&mut self, dest: Target, value: Value) {
        match dest {
            Target::Register(index) => self.data_registers[index] = value,
            Target::Stack(index) => self.data_stacks[index].push(value),
        }
    }

    /// Moves the top value of the src target to the dest target
    fn mov(&mut self, dest: Target, src: Target) -> VMResult<()> {
        let src_value = self.pop(&src)?;
        self.push(dest, src_value);

        Ok(())
    }

    /// Swaps the top values of the targets
    fn swp(&mut self, target_a: Target, target_b: Target) -> VMResult<()> {
        let a_value = self.pop(&target_a)?;
        let b_value = self.pop(&target_b)?;

        self.push(target_a, b_value);
        self.push(target_b, a_value);

        Ok(())
    }

    /// Calls the function at the specified address saving the return address
    /// to the call stack
    fn call(&mut self, addr: Address) {
        self.call_stack.push(self.pc + 1);
        self.jmp(addr);
    }

    /// Returns from an ongoing function call
    fn ret(&mut self) -> VMResult<()> {
        if self.call_stack.is_empty() {
            bail!("unable to return from an empty call stack");
        }

        let retur_addr = self.call_stack.pop().unwrap();

        self.jmp(retur_addr);

        Ok(())
    }
}
<|endoftext|>


<commit_before>// extern crate libc;

// use libc::types;
use std::io::File;
use std::mem;
use std::os;

// https://stackoverflow.com/questions/24633784/is-there-a-gzip-library-available-for-rust

// #[link(name = "z")]
// extern {
//     fn gzopen(path: *const types::os::arch::c95::c_char,
//               mode: *const types::os::arch::c95::c_char)
//               -> types::common::c95::c_void;
// }

// #[link(name = "z")]
// extern {
//     fn gzread(file: types::common::c95::c_void,
//               buf:  types::common::c95::c_void,
//               len:  uint)
//               -> int;
// }

// #[link(name = "z")]
// extern {
//     fn gzclose(file: types::common::c95::c_void) -> int;
// }

fn pointer_size() -> uint {
    let tmp = 0u8;
    let boxed = box tmp;
    mem::size_of_val(&boxed)
}

fn main() {
    let args = os::args();
    if args.len() != 2 {
        println!("usage: read_blend_file /path/to/file.blend");
    } else {
        let slice: &str = args[1].as_slice();
        println!("open \"{}\" ...", slice);
        {
            // read 12 bytes from the Blender file
            let path = Path::new(slice);
            let display = path.display();
            let mut file = match File::open(&path) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(file) => file,
            };
            let mut buf = [0u8, ..12];
            match file.read(buf) {
                Err(why) => fail!("couldn't read {}: {}", display, why.desc),
                Ok(_) => (),
            }
            // pack those 12 bytes into a string ...
            let mut header = String::new();
            for n in range(0u, 12) {
                header.push(buf[n] as char);
            }
            // ... to be able to compare them
            let slice = header.as_slice();
            let blender: &str = slice.slice(0, 7); // first 7 chars
            if blender == "BLENDER" {
                println!("INFO: a Blender file.");
                let ptr_size = pointer_size();
                println!("size of pointer in bytes: {}", ptr_size);
                println!("Header (12 chars): {}", header);
                let mut ptr_size_differs = false;
                if buf[7] as char == '_' {
                    // 32-bit pointers expected
                    if ptr_size != 4 {
                        ptr_size_differs = true;
                    }
                    println!("32-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                } else {
                    // 64-bit pointers expected
                    if ptr_size != 8 {
                        ptr_size_differs = true;
                    }
                    println!("64-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                }
                // little endian or big endian?
                let mut l_endian;
                let endian_test = 1u16; // value one stored in two bytes
                if endian_test.to_le() != endian_test {
                    l_endian = false;
                } else {
                    // if we are on a little endian machine to_le() is a no-op
                    l_endian = true;
                }
                println!("l_endian = {}", l_endian);
                let mut switch_endian;
                if buf[8] as char == 'v' {
                    // file stores little endian
                    if !l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                } else {
                    // file stores big endian
                    if l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                }
                println!("switch_endian = {}", switch_endian);
                // get the version number
                let mut num = String::new();
                for n in range(9u, 12) {
                    num.push(buf[n] as char);
                }
                println!("num = {}", num);
                // assumes 64-bit pointers (in file as well as on platform)
                loop {
                    // read_file_dna
                    let mut bhead8 = [0u8, ..24]; // 4 * int + 64-bit pointer
                    match file.read(bhead8) {
                        Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                        Ok(_) => (),
                    }
                    // pack those 24 bytes into a string ...
                    let mut bhead = String::new();
                    for n in range(0u, 24) {
                        bhead.push(bhead8[n] as char);
                    }
                    let slice = bhead.as_slice();
                    let code: &str = slice.slice(0, 4); // first 4 chars
                    println!("code = {}", code);
                    let mut len: uint = 0;
                    len += (bhead8[4] as uint) <<  0;
                    len += (bhead8[5] as uint) <<  8;
                    len += (bhead8[6] as uint) << 16;
                    len += (bhead8[7] as uint) << 24;
                    println!("len = {}", len);
                    file.read_exact(len);
                    if code == "ENDB" && len == 0 {
                        break;
                    }
                }
            } else {
                println!("ERROR: not a Blender file.");
            }
        } // file gets closed here
    }
}
<commit_msg>Remove comments about zlib.<commit_after>use std::io::File;
use std::mem;
use std::os;

// https://stackoverflow.com/questions/24633784/is-there-a-gzip-library-available-for-rust

fn pointer_size() -> uint {
    let tmp = 0u8;
    let boxed = box tmp;
    mem::size_of_val(&boxed)
}

fn main() {
    let args = os::args();
    if args.len() != 2 {
        println!("usage: read_blend_file /path/to/file.blend");
    } else {
        let slice: &str = args[1].as_slice();
        println!("open \"{}\" ...", slice);
        {
            // read 12 bytes from the Blender file
            let path = Path::new(slice);
            let display = path.display();
            let mut file = match File::open(&path) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(file) => file,
            };
            let mut buf = [0u8, ..12];
            match file.read(buf) {
                Err(why) => fail!("couldn't read {}: {}", display, why.desc),
                Ok(_) => (),
            }
            // pack those 12 bytes into a string ...
            let mut header = String::new();
            for n in range(0u, 12) {
                header.push(buf[n] as char);
            }
            // ... to be able to compare them
            let slice = header.as_slice();
            let blender: &str = slice.slice(0, 7); // first 7 chars
            if blender == "BLENDER" {
                println!("INFO: a Blender file.");
                let ptr_size = pointer_size();
                println!("size of pointer in bytes: {}", ptr_size);
                println!("Header (12 chars): {}", header);
                let mut ptr_size_differs = false;
                if buf[7] as char == '_' {
                    // 32-bit pointers expected
                    if ptr_size != 4 {
                        ptr_size_differs = true;
                    }
                    println!("32-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                } else {
                    // 64-bit pointers expected
                    if ptr_size != 8 {
                        ptr_size_differs = true;
                    }
                    println!("64-bit pointers in file, pointer size differs? {}", ptr_size_differs);
                }
                // little endian or big endian?
                let mut l_endian;
                let endian_test = 1u16; // value one stored in two bytes
                if endian_test.to_le() != endian_test {
                    l_endian = false;
                } else {
                    // if we are on a little endian machine to_le() is a no-op
                    l_endian = true;
                }
                println!("l_endian = {}", l_endian);
                let mut switch_endian;
                if buf[8] as char == 'v' {
                    // file stores little endian
                    if !l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                } else {
                    // file stores big endian
                    if l_endian {
                        switch_endian = true;
                    } else {
                        switch_endian = false;
                    }
                }
                println!("switch_endian = {}", switch_endian);
                // get the version number
                let mut num = String::new();
                for n in range(9u, 12) {
                    num.push(buf[n] as char);
                }
                println!("num = {}", num);
                // assumes 64-bit pointers (in file as well as on platform)
                loop {
                    // read_file_dna
                    let mut bhead8 = [0u8, ..24]; // 4 * int + 64-bit pointer
                    match file.read(bhead8) {
                        Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                        Ok(_) => (),
                    }
                    // pack those 24 bytes into a string ...
                    let mut bhead = String::new();
                    for n in range(0u, 24) {
                        bhead.push(bhead8[n] as char);
                    }
                    let slice = bhead.as_slice();
                    let code: &str = slice.slice(0, 4); // first 4 chars
                    println!("code = {}", code);
                    let mut len: uint = 0;
                    len += (bhead8[4] as uint) <<  0;
                    len += (bhead8[5] as uint) <<  8;
                    len += (bhead8[6] as uint) << 16;
                    len += (bhead8[7] as uint) << 24;
                    println!("len = {}", len);
                    file.read_exact(len);
                    if code == "ENDB" && len == 0 {
                        break;
                    }
                }
            } else {
                println!("ERROR: not a Blender file.");
            }
        } // file gets closed here
    }
}
<|endoftext|>


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

use enums;
use parse;

use format_from_id;
use is_builtin;
use location_decoration;
use name_from_id;

pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> (String, String) {
    let (execution, id, ep_name, interface) = match instruction {
        &parse::Instruction::EntryPoint {
            ref execution,
            id,
            ref name,
            ref interface,
            ..
        } => {
            (execution, id, name, interface)
        },
        _ => unreachable!(),
    };

    let capitalized_ep_name: String = ep_name
        .chars()
        .take(1)
        .flat_map(|c| c.to_uppercase())
        .chain(ep_name.chars().skip(1))
        .collect();

    let interface_structs =
        write_interface_structs(doc,
                                &capitalized_ep_name,
                                interface,
                                match *execution {
                                    enums::ExecutionModel::ExecutionModelTessellationControl =>
                                        true,
                                    enums::ExecutionModel::ExecutionModelTessellationEvaluation =>
                                        true,
                                    enums::ExecutionModel::ExecutionModelGeometry => true,
                                    _ => false,
                                },
                                match *execution {
                                    enums::ExecutionModel::ExecutionModelTessellationControl =>
                                        true,
                                    _ => false,
                                });

    let (ty, f_call) = {
        if let enums::ExecutionModel::ExecutionModelGLCompute = *execution {
            (format!("::vulkano::pipeline::shader::ComputeEntryPoint<(), Layout>"),
            format!("compute_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as \
                    *const _), Layout(ShaderStages {{ compute: true, .. ShaderStages::none() \
                    }}))"))

        } else {
            let ty = match *execution {
                enums::ExecutionModel::ExecutionModelVertex => {
                    "::vulkano::pipeline::shader::GraphicsShaderType::Vertex".to_owned()
                },

                enums::ExecutionModel::ExecutionModelTessellationControl => {
                    "::vulkano::pipeline::shader::GraphicsShaderType::TessellationControl".to_owned()
                },

                enums::ExecutionModel::ExecutionModelTessellationEvaluation => {
                    "::vulkano::pipeline::shader::GraphicsShaderType::TessellationEvaluation".to_owned()
                },

                enums::ExecutionModel::ExecutionModelGeometry => {
                    let mut execution_mode = None;

                    for instruction in doc.instructions.iter() {
                        if let &parse::Instruction::ExecutionMode { target_id, ref mode, .. } = instruction {
                            if target_id != id {
                                continue;
                            }
                            execution_mode = match mode {
                                &enums::ExecutionMode::ExecutionModeInputPoints => Some("Points"),
                                &enums::ExecutionMode::ExecutionModeInputLines => Some("Lines"),
                                &enums::ExecutionMode::ExecutionModeInputLinesAdjacency => Some("LinesWithAdjacency"),
                                &enums::ExecutionMode::ExecutionModeTriangles => Some("Triangles"),
                                &enums::ExecutionMode::ExecutionModeInputTrianglesAdjacency => Some("TrianglesWithAdjacency"),
                                _ => continue,
                            };
                            break;
                        }
                    }

                    format!("::vulkano::pipeline::shader::GraphicsShaderType::Geometry(
                        ::vulkano::pipeline::shader::GeometryShaderExecutionMode::{0}
                    )", execution_mode.unwrap())
                },

                enums::ExecutionModel::ExecutionModelFragment => {
                    "::vulkano::pipeline::shader::GraphicsShaderType::Fragment".to_owned()
                },

                enums::ExecutionModel::ExecutionModelGLCompute => {
                    unreachable!()
                },

                enums::ExecutionModel::ExecutionModelKernel => panic!("Kernels are not supported"),
            };

            let t = format!("::vulkano::pipeline::shader::GraphicsEntryPoint<(), {0}Input, \
                                {0}Output, Layout>",
                            capitalized_ep_name);
            let f = format!("graphics_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() \
                                as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ vertex: \
                                true, .. ShaderStages::none() }}), {1})",
                            capitalized_ep_name, ty);

            (t, f)
        }
    };

    let entry_point = format!(
        r#"
    /// Returns a logical struct describing the entry point named `{ep_name}`.
    #[inline]
    #[allow(unsafe_code)]
    pub fn {ep_name}_entry_point(&self) -> {ty} {{
        unsafe {{
            #[allow(dead_code)]
            static NAME: [u8; {ep_name_lenp1}] = [{encoded_ep_name}, 0];     // "{ep_name}"
            self.shader.{f_call}
        }}
    }}
            "#,
        ep_name = ep_name,
        ep_name_lenp1 = ep_name.chars().count() + 1,
        ty = ty,
        encoded_ep_name = ep_name
            .chars()
            .map(|c| (c as u32).to_string())
            .collect::<Vec<String>>()
            .join(", "),
        f_call = f_call
    );

    (interface_structs, entry_point)
}

fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interface: &[u32],
                           ignore_first_array_in: bool, ignore_first_array_out: bool)
                           -> String {
    let mut input_elements = Vec::new();
    let mut output_elements = Vec::new();

    // Filling `input_elements` and `output_elements`.
    for interface in interface.iter() {
        for i in doc.instructions.iter() {
            match i {
                &parse::Instruction::Variable {
                    result_type_id,
                    result_id,
                    ref storage_class,
                    ..
                } if &result_id == interface => {
                    if is_builtin(doc, result_id) {
                        continue;
                    }

                    let (to_write, ignore_first_array) = match storage_class {
                        &enums::StorageClass::StorageClassInput => (&mut input_elements,
                                                                    ignore_first_array_in),
                        &enums::StorageClass::StorageClassOutput => (&mut output_elements,
                                                                     ignore_first_array_out),
                        _ => continue,
                    };

                    let name = name_from_id(doc, result_id);
                    if name == "__unnamed" {
                        continue;
                    } // FIXME: hack

                    let loc = match location_decoration(doc, result_id) {
                        Some(l) => l,
                        None => panic!("Attribute `{}` (id {}) is missing a location",
                                       name,
                                       result_id),
                    };

                    to_write
                        .push((loc, name, format_from_id(doc, result_type_id, ignore_first_array)));
                },
                _ => (),
            }
        }
    }

    write_interface_struct(&format!("{}Input", capitalized_ep_name), &input_elements) +
        &write_interface_struct(&format!("{}Output", capitalized_ep_name), &output_elements)
}

fn write_interface_struct(struct_name: &str, attributes: &[(u32, String, (String, usize))])
                          -> String {
    // Checking for overlapping elements.
    for (offset, &(loc, ref name, (_, loc_len))) in attributes.iter().enumerate() {
        for &(loc2, ref name2, (_, loc_len2)) in attributes.iter().skip(offset + 1) {
            if loc == loc2 || (loc < loc2 && loc + loc_len as u32 > loc2) ||
                (loc2 < loc && loc2 + loc_len2 as u32 > loc)
            {
                panic!("The locations of attributes `{}` (start={}, size={}) \
                        and `{}` (start={}, size={}) overlap",
                       name,
                       loc,
                       loc_len,
                       name2,
                       loc2,
                       loc_len2);
            }
        }
    }

    let body = attributes
        .iter()
        .enumerate()
        .map(|(num, &(loc, ref name, (ref ty, num_locs)))| {
            assert!(num_locs >= 1);

            format!(
                "if self.num == {} {{
            self.num += 1;

            return Some(::vulkano::pipeline::shader::ShaderInterfaceDefEntry {{
                location: {} .. {},
                format: ::vulkano::format::Format::{},
                name: Some(::std::borrow::Cow::Borrowed(\"{}\"))
            }});
        }}",
                num,
                loc,
                loc as usize + num_locs,
                ty,
                name
            )
        })
        .collect::<Vec<_>>()
        .join("");

    format!(
        "
        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
        pub struct {name};

        \
         #[allow(unsafe_code)]
        unsafe impl ::vulkano::pipeline::shader::ShaderInterfaceDef for \
         {name} {{
            type Iter = {name}Iter;
            fn elements(&self) -> {name}Iter {{
                \
         {name}Iter {{ num: 0 }}
            }}
        }}

        #[derive(Debug, Copy, Clone)]
        \
         pub struct {name}Iter {{ num: u16 }}
        impl Iterator for {name}Iter {{
            type \
         Item = ::vulkano::pipeline::shader::ShaderInterfaceDefEntry;

            #[inline]
            \
         fn next(&mut self) -> Option<Self::Item> {{
                {body}
                None
            \
         }}

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {{
                \
         let len = ({len} - self.num) as usize;
                (len, Some(len))
            }}
        \
         }}

        impl ExactSizeIterator for {name}Iter {{}}
    ",
        name = struct_name,
        body = body,
        len = attributes.len()
    )
}
<commit_msg>Fix #772 (#724)<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use enums;
use parse;

use format_from_id;
use is_builtin;
use location_decoration;
use name_from_id;

pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> (String, String) {
    let (execution, id, ep_name, interface) = match instruction {
        &parse::Instruction::EntryPoint {
            ref execution,
            id,
            ref name,
            ref interface,
            ..
        } => {
            (execution, id, name, interface)
        },
        _ => unreachable!(),
    };

    let capitalized_ep_name: String = ep_name
        .chars()
        .take(1)
        .flat_map(|c| c.to_uppercase())
        .chain(ep_name.chars().skip(1))
        .collect();

    let interface_structs =
        write_interface_structs(doc,
                                &capitalized_ep_name,
                                interface,
                                match *execution {
                                    enums::ExecutionModel::ExecutionModelTessellationControl =>
                                        true,
                                    enums::ExecutionModel::ExecutionModelTessellationEvaluation =>
                                        true,
                                    enums::ExecutionModel::ExecutionModelGeometry => true,
                                    _ => false,
                                },
                                match *execution {
                                    enums::ExecutionModel::ExecutionModelTessellationControl =>
                                        true,
                                    _ => false,
                                });

    let (ty, f_call) = {
        if let enums::ExecutionModel::ExecutionModelGLCompute = *execution {
            (format!("::vulkano::pipeline::shader::ComputeEntryPoint<(), Layout>"),
            format!("compute_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as \
                    *const _), Layout(ShaderStages {{ compute: true, .. ShaderStages::none() \
                    }}))"))

        } else {
            let ty = match *execution {
                enums::ExecutionModel::ExecutionModelVertex => {
                    "::vulkano::pipeline::shader::GraphicsShaderType::Vertex".to_owned()
                },

                enums::ExecutionModel::ExecutionModelTessellationControl => {
                    "::vulkano::pipeline::shader::GraphicsShaderType::TessellationControl".to_owned()
                },

                enums::ExecutionModel::ExecutionModelTessellationEvaluation => {
                    "::vulkano::pipeline::shader::GraphicsShaderType::TessellationEvaluation".to_owned()
                },

                enums::ExecutionModel::ExecutionModelGeometry => {
                    let mut execution_mode = None;

                    for instruction in doc.instructions.iter() {
                        if let &parse::Instruction::ExecutionMode { target_id, ref mode, .. } = instruction {
                            if target_id != id {
                                continue;
                            }
                            execution_mode = match mode {
                                &enums::ExecutionMode::ExecutionModeInputPoints => Some("Points"),
                                &enums::ExecutionMode::ExecutionModeInputLines => Some("Lines"),
                                &enums::ExecutionMode::ExecutionModeInputLinesAdjacency => Some("LinesWithAdjacency"),
                                &enums::ExecutionMode::ExecutionModeTriangles => Some("Triangles"),
                                &enums::ExecutionMode::ExecutionModeInputTrianglesAdjacency => Some("TrianglesWithAdjacency"),
                                _ => continue,
                            };
                            break;
                        }
                    }

                    format!("::vulkano::pipeline::shader::GraphicsShaderType::Geometry(
                        ::vulkano::pipeline::shader::GeometryShaderExecutionMode::{0}
                    )", execution_mode.unwrap())
                },

                enums::ExecutionModel::ExecutionModelFragment => {
                    "::vulkano::pipeline::shader::GraphicsShaderType::Fragment".to_owned()
                },

                enums::ExecutionModel::ExecutionModelGLCompute => {
                    unreachable!()
                },

                enums::ExecutionModel::ExecutionModelKernel => panic!("Kernels are not supported"),
            };

            let stage = match *execution {
                enums::ExecutionModel::ExecutionModelVertex => {
                    "ShaderStages { vertex: true, .. ShaderStages::none() }"
                },
                enums::ExecutionModel::ExecutionModelTessellationControl => {
                    "ShaderStages { tessellation_control: true, .. ShaderStages::none() }"
                },
                enums::ExecutionModel::ExecutionModelTessellationEvaluation => {
                    "ShaderStages { tessellation_evaluation: true, .. ShaderStages::none() }"
                },
                enums::ExecutionModel::ExecutionModelGeometry => {
                    "ShaderStages { geometry: true, .. ShaderStages::none() }"
                },
                enums::ExecutionModel::ExecutionModelFragment => {
                    "ShaderStages { fragment: true, .. ShaderStages::none() }"
                },
                enums::ExecutionModel::ExecutionModelGLCompute => unreachable!(),
                enums::ExecutionModel::ExecutionModelKernel => unreachable!(),
            };

            let t = format!("::vulkano::pipeline::shader::GraphicsEntryPoint<(), {0}Input, \
                                {0}Output, Layout>",
                            capitalized_ep_name);
            let f = format!("graphics_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() \
                                as *const _), {0}Input, {0}Output, Layout({2}), {1})",
                            capitalized_ep_name, ty, stage);

            (t, f)
        }
    };

    let entry_point = format!(
        r#"
    /// Returns a logical struct describing the entry point named `{ep_name}`.
    #[inline]
    #[allow(unsafe_code)]
    pub fn {ep_name}_entry_point(&self) -> {ty} {{
        unsafe {{
            #[allow(dead_code)]
            static NAME: [u8; {ep_name_lenp1}] = [{encoded_ep_name}, 0];     // "{ep_name}"
            self.shader.{f_call}
        }}
    }}
            "#,
        ep_name = ep_name,
        ep_name_lenp1 = ep_name.chars().count() + 1,
        ty = ty,
        encoded_ep_name = ep_name
            .chars()
            .map(|c| (c as u32).to_string())
            .collect::<Vec<String>>()
            .join(", "),
        f_call = f_call
    );

    (interface_structs, entry_point)
}

fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interface: &[u32],
                           ignore_first_array_in: bool, ignore_first_array_out: bool)
                           -> String {
    let mut input_elements = Vec::new();
    let mut output_elements = Vec::new();

    // Filling `input_elements` and `output_elements`.
    for interface in interface.iter() {
        for i in doc.instructions.iter() {
            match i {
                &parse::Instruction::Variable {
                    result_type_id,
                    result_id,
                    ref storage_class,
                    ..
                } if &result_id == interface => {
                    if is_builtin(doc, result_id) {
                        continue;
                    }

                    let (to_write, ignore_first_array) = match storage_class {
                        &enums::StorageClass::StorageClassInput => (&mut input_elements,
                                                                    ignore_first_array_in),
                        &enums::StorageClass::StorageClassOutput => (&mut output_elements,
                                                                     ignore_first_array_out),
                        _ => continue,
                    };

                    let name = name_from_id(doc, result_id);
                    if name == "__unnamed" {
                        continue;
                    } // FIXME: hack

                    let loc = match location_decoration(doc, result_id) {
                        Some(l) => l,
                        None => panic!("Attribute `{}` (id {}) is missing a location",
                                       name,
                                       result_id),
                    };

                    to_write
                        .push((loc, name, format_from_id(doc, result_type_id, ignore_first_array)));
                },
                _ => (),
            }
        }
    }

    write_interface_struct(&format!("{}Input", capitalized_ep_name), &input_elements) +
        &write_interface_struct(&format!("{}Output", capitalized_ep_name), &output_elements)
}

fn write_interface_struct(struct_name: &str, attributes: &[(u32, String, (String, usize))])
                          -> String {
    // Checking for overlapping elements.
    for (offset, &(loc, ref name, (_, loc_len))) in attributes.iter().enumerate() {
        for &(loc2, ref name2, (_, loc_len2)) in attributes.iter().skip(offset + 1) {
            if loc == loc2 || (loc < loc2 && loc + loc_len as u32 > loc2) ||
                (loc2 < loc && loc2 + loc_len2 as u32 > loc)
            {
                panic!("The locations of attributes `{}` (start={}, size={}) \
                        and `{}` (start={}, size={}) overlap",
                       name,
                       loc,
                       loc_len,
                       name2,
                       loc2,
                       loc_len2);
            }
        }
    }

    let body = attributes
        .iter()
        .enumerate()
        .map(|(num, &(loc, ref name, (ref ty, num_locs)))| {
            assert!(num_locs >= 1);

            format!(
                "if self.num == {} {{
            self.num += 1;

            return Some(::vulkano::pipeline::shader::ShaderInterfaceDefEntry {{
                location: {} .. {},
                format: ::vulkano::format::Format::{},
                name: Some(::std::borrow::Cow::Borrowed(\"{}\"))
            }});
        }}",
                num,
                loc,
                loc as usize + num_locs,
                ty,
                name
            )
        })
        .collect::<Vec<_>>()
        .join("");

    format!(
        "
        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
        pub struct {name};

        \
         #[allow(unsafe_code)]
        unsafe impl ::vulkano::pipeline::shader::ShaderInterfaceDef for \
         {name} {{
            type Iter = {name}Iter;
            fn elements(&self) -> {name}Iter {{
                \
         {name}Iter {{ num: 0 }}
            }}
        }}

        #[derive(Debug, Copy, Clone)]
        \
         pub struct {name}Iter {{ num: u16 }}
        impl Iterator for {name}Iter {{
            type \
         Item = ::vulkano::pipeline::shader::ShaderInterfaceDefEntry;

            #[inline]
            \
         fn next(&mut self) -> Option<Self::Item> {{
                {body}
                None
            \
         }}

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {{
                \
         let len = ({len} - self.num) as usize;
                (len, Some(len))
            }}
        \
         }}

        impl ExactSizeIterator for {name}Iter {{}}
    ",
        name = struct_name,
        body = body,
        len = attributes.len()
    )
}
<|endoftext|>


<commit_before>use std::fs::{File, PathExt};
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::process::Command;

use telemetry::{Meter, Point, latitude_longitude_to_point};
use waypoint_generator::WaypointGenerator;

/**
 * Loads and returns waypoints from a KML file.
 */
#[allow(dead_code)]
pub struct KmlWaypointGenerator {
    waypoints: Vec<Point>,
    current_waypoint: u32,
}

impl KmlWaypointGenerator {
    #[allow(dead_code)]
    pub fn new(file_name: &str) -> KmlWaypointGenerator {
        KmlWaypointGenerator {
            waypoints: KmlWaypointGenerator::load_waypoints(file_name),
            current_waypoint: 0
        }
    }
    fn load_waypoints(file_name: &str) -> Vec<Point> {
        let path = Path::new(file_name);
        if !path.exists() || !path.is_file() {
            panic!("File does not exist: {}", file_name);
        }

        // A KML file is a zip archive containing a single file named "doc.kml"
        // that is an XML file
        let temp_directory = "/tmp/waypoints";
        let zip_io_result = Command::new("unzip")
            .arg(file_name)
            .arg("-d")  // Output directory
            .arg(temp_directory)
            .spawn();
        let mut zip_child = match zip_io_result {
            Ok(child) => (child),
            Err(e) => panic!("Failed to unzip file: {}", e),
        };

        match zip_child.wait() {
            Ok(_) => (),
            Err(e) => panic!("Failed to unzip file: {}", e),
        };

        let mut waypoints = Vec::<Point>::new();
        let file_path = Path::new("/tmp/waypoints/doc.kml");
        let file = match File::open(&file_path) {
            Ok(f) => f,
            Err(_) => panic!("Couldn't open doc.kml"),
        };
        let xml_file = BufReader::new(file);
        let mut coordinates_open_tag = false;
        // We should use a real XML parser here, but Google Earth saves the
        // <coordinates> tag on one line, then the coordinates on the next,
        // then the closing </coordinates> tag on the next, so we'll just rely
        // on that fact
        for line_option in xml_file.lines() {
            match line_option {
                Ok(line) => {
                    if line.as_slice().contains("<coordinates>") {
                        coordinates_open_tag = true;
                    } else if coordinates_open_tag {
                        let mut latitude = 0.0f64;
                        let mut longitude = 0.0f64;
                        for long_lat_alt in line.as_slice().words() {
                            let mut iterator = long_lat_alt.split(',');
                            let mut success = true;
                            match iterator.next() {
                                Some(longitude_str) => {
                                    let parsed_longitude = longitude_str.parse::<f64>();
                                    match parsed_longitude {
                                        Ok(longitude_) => longitude = longitude_,
                                        Err(e) => {
                                            println!("Unable to parse longitude: '{}', {}", longitude_str, e);
                                            success = false;
                                        },
                                    }
                                },
                                None => println!("No longitude"),
                            }

                            match iterator.next() {
                                Some(latitude_str) => {
                                    let parsed_latitude = latitude_str.parse::<f64>();
                                    match parsed_latitude {
                                        Ok(latitude_) => latitude = latitude_,
                                        Err(e) => {
                                            println!(
                                                "Unable to parse latitude: '{}', {}",
                                                 latitude_str,
                                                 e);
                                            success = false;
                                        },
                                    }
                                }
                                None => println!("No latitude"),
                            }

                            if success {
                                waypoints.push(latitude_longitude_to_point(latitude, longitude));
                            }
                        }
                        break;
                    }
                }
                Err(e) => println!("error {}", e),
            }
        }
        waypoints
    }
}

impl WaypointGenerator for KmlWaypointGenerator {
    #[allow(unused_variables)]
    fn get_current_waypoint(&self, point: &Point) -> Point {
        // TODO
        Point { x: 0.0, y: 0.0 }
    }

    #[allow(unused_variables)]
    fn get_current_raw_waypoint(&self, point: &Point) -> Point {
        // TODO
        Point { x: 0.0, y: 0.0 }
    }

    fn next(&mut self) {
        // TODO
    }

    #[allow(unused_variables)]
    fn reached(&self, point: &Point) -> bool {
        // TODO
        return false;
    }

    fn done(&self) -> bool {
        // TODO
        return false;
    }

    #[allow(unused_variables)]
    fn reach_distance(&self) -> Meter {
        1.0
    }
}
<commit_msg>Remove directory before unzipping<commit_after>use std::fs::{File, PathExt, remove_dir_all};
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::process::Command;

use telemetry::{Meter, Point, latitude_longitude_to_point};
use waypoint_generator::WaypointGenerator;

/**
 * Loads and returns waypoints from a KML file.
 */
#[allow(dead_code)]
pub struct KmlWaypointGenerator {
    waypoints: Vec<Point>,
    current_waypoint: u32,
}

impl KmlWaypointGenerator {
    #[allow(dead_code)]
    pub fn new(file_name: &str) -> KmlWaypointGenerator {
        KmlWaypointGenerator {
            waypoints: KmlWaypointGenerator::load_waypoints(file_name),
            current_waypoint: 0
        }
    }
    fn load_waypoints(file_name: &str) -> Vec<Point> {
        let path = Path::new(file_name);
        if !path.exists() || !path.is_file() {
            panic!("File does not exist: {}", file_name);
        }

        // A KML file is a zip archive containing a single file named "doc.kml"
        // that is an XML file
        let temp_directory = "/tmp/waypoints";
        remove_dir_all(temp_directory);
        let zip_io_result = Command::new("unzip")
            .arg(file_name)
            .arg("-d")  // Output directory
            .arg(temp_directory)
            .spawn();
        let mut zip_child = match zip_io_result {
            Ok(child) => (child),
            Err(e) => panic!("Failed to unzip file: {}", e),
        };

        match zip_child.wait() {
            Ok(_) => (),
            Err(e) => panic!("Failed to unzip file: {}", e),
        };

        let mut waypoints = Vec::<Point>::new();
        let file_path = Path::new("/tmp/waypoints/doc.kml");
        let file = match File::open(&file_path) {
            Ok(f) => f,
            Err(_) => panic!("Couldn't open doc.kml"),
        };
        let xml_file = BufReader::new(file);
        let mut coordinates_open_tag = false;
        // We should use a real XML parser here, but Google Earth saves the
        // <coordinates> tag on one line, then the coordinates on the next,
        // then the closing </coordinates> tag on the next, so we'll just rely
        // on that fact
        for line_option in xml_file.lines() {
            match line_option {
                Ok(line) => {
                    if line.as_slice().contains("<coordinates>") {
                        coordinates_open_tag = true;
                    } else if coordinates_open_tag {
                        let mut latitude = 0.0f64;
                        let mut longitude = 0.0f64;
                        for long_lat_alt in line.as_slice().words() {
                            let mut iterator = long_lat_alt.split(',');
                            let mut success = true;
                            match iterator.next() {
                                Some(longitude_str) => {
                                    let parsed_longitude = longitude_str.parse::<f64>();
                                    match parsed_longitude {
                                        Ok(longitude_) => longitude = longitude_,
                                        Err(e) => {
                                            println!("Unable to parse longitude: '{}', {}", longitude_str, e);
                                            success = false;
                                        },
                                    }
                                },
                                None => println!("No longitude"),
                            }

                            match iterator.next() {
                                Some(latitude_str) => {
                                    let parsed_latitude = latitude_str.parse::<f64>();
                                    match parsed_latitude {
                                        Ok(latitude_) => latitude = latitude_,
                                        Err(e) => {
                                            println!(
                                                "Unable to parse latitude: '{}', {}",
                                                 latitude_str,
                                                 e);
                                            success = false;
                                        },
                                    }
                                }
                                None => println!("No latitude"),
                            }

                            if success {
                                waypoints.push(latitude_longitude_to_point(latitude, longitude));
                            }
                        }
                        break;
                    }
                }
                Err(e) => println!("error {}", e),
            }
        }
        waypoints
    }
}

impl WaypointGenerator for KmlWaypointGenerator {
    #[allow(unused_variables)]
    fn get_current_waypoint(&self, point: &Point) -> Point {
        // TODO
        Point { x: 0.0, y: 0.0 }
    }

    #[allow(unused_variables)]
    fn get_current_raw_waypoint(&self, point: &Point) -> Point {
        // TODO
        Point { x: 0.0, y: 0.0 }
    }

    fn next(&mut self) {
        // TODO
    }

    #[allow(unused_variables)]
    fn reached(&self, point: &Point) -> bool {
        // TODO
        return false;
    }

    fn done(&self) -> bool {
        // TODO
        return false;
    }

    #[allow(unused_variables)]
    fn reach_distance(&self) -> Meter {
        1.0
    }
}
<|endoftext|>


<commit_before><commit_msg>Add extern crate to prelude<commit_after>extern crate native-tls;<|endoftext|>


<commit_before>//! Matrix-spec compliant server names.
use std::{convert::TryFrom, fmt, mem, rc::Rc, str::FromStr, sync::Arc};

use ruma_identifiers_validation::server_name::validate;

/// A Matrix-spec compliant server name.
#[repr(transparent)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(transparent, crate = "serde"))]
pub struct ServerName(str);

/// An owned server name.
pub type ServerNameBox = Box<ServerName>;

impl ServerName {
    #[allow(clippy::transmute_ptr_to_ptr)]
    fn from_borrowed(s: &str) -> &Self {
        unsafe { mem::transmute(s) }
    }

    fn from_owned(s: Box<str>) -> Box<Self> {
        unsafe { mem::transmute(s) }
    }

    fn into_owned(self: Box<Self>) -> Box<str> {
        unsafe { mem::transmute(self) }
    }

    /// Creates a string slice from this `ServerName`.
    pub fn as_str(&self) -> &str {
        &self.0
    }

    /// Creates a byte slice from this `ServerName`.
    pub fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

impl fmt::Debug for ServerName {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

impl Clone for Box<ServerName> {
    fn clone(&self) -> Self {
        (**self).to_owned()
    }
}

impl ToOwned for ServerName {
    type Owned = Box<ServerName>;

    fn to_owned(&self) -> Self::Owned {
        Self::from_owned(self.0.into())
    }
}

impl From<&ServerName> for Box<ServerName> {
    fn from(s: &ServerName) -> Self {
        s.to_owned()
    }
}

impl From<&ServerName> for Rc<ServerName> {
    fn from(s: &ServerName) -> Self {
        let rc = Rc::<str>::from(s.as_str());
        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const ServerName) }
    }
}

impl From<&ServerName> for Arc<ServerName> {
    fn from(s: &ServerName) -> Self {
        let arc = Arc::<str>::from(s.as_str());
        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const ServerName) }
    }
}

fn try_from<S>(server_name: S) -> Result<Box<ServerName>, crate::Error>
where
    S: AsRef<str> + Into<Box<str>>,
{
    validate(server_name.as_ref())?;
    Ok(ServerName::from_owned(server_name.into()))
}

impl AsRef<str> for ServerName {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl AsRef<str> for Box<ServerName> {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl From<Box<ServerName>> for String {
    fn from(s: Box<ServerName>) -> Self {
        s.into_owned().into()
    }
}

impl<'a> TryFrom<&'a str> for &'a ServerName {
    type Error = crate::Error;

    fn try_from(server_name: &'a str) -> Result<Self, Self::Error> {
        validate(server_name)?;
        Ok(ServerName::from_borrowed(server_name))
    }
}

impl FromStr for Box<ServerName> {
    type Err = crate::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        try_from(s)
    }
}

impl TryFrom<&str> for Box<ServerName> {
    type Error = crate::Error;

    fn try_from(s: &str) -> Result<Self, Self::Error> {
        try_from(s)
    }
}

impl TryFrom<String> for Box<ServerName> {
    type Error = crate::Error;

    fn try_from(s: String) -> Result<Self, Self::Error> {
        try_from(s)
    }
}

impl fmt::Display for ServerName {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Box<ServerName> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        crate::deserialize_id(deserializer, "An IP address or hostname")
    }
}

partial_eq_string!(ServerName);
partial_eq_string!(Box<ServerName>);

#[cfg(test)]
mod tests {
    use std::convert::TryFrom;

    use super::ServerName;

    #[test]
    fn ipv4_host() {
        assert!(<&ServerName>::try_from("127.0.0.1").is_ok());
    }

    #[test]
    fn ipv4_host_and_port() {
        assert!(<&ServerName>::try_from("1.1.1.1:12000").is_ok());
    }

    #[test]
    fn ipv6() {
        assert!(<&ServerName>::try_from("[::1]").is_ok());
    }

    #[test]
    fn ipv6_with_port() {
        assert!(<&ServerName>::try_from("[1234:5678::abcd]:5678").is_ok());
    }

    #[test]
    fn dns_name() {
        assert!(<&ServerName>::try_from("example.com").is_ok());
    }

    #[test]
    fn dns_name_with_port() {
        assert!(<&ServerName>::try_from("ruma.io:8080").is_ok());
    }

    #[test]
    fn empty_string() {
        assert!(<&ServerName>::try_from("").is_err());
    }

    #[test]
    fn invalid_ipv6() {
        assert!(<&ServerName>::try_from("[test::1]").is_err());
    }

    #[test]
    fn ipv4_with_invalid_port() {
        assert!(<&ServerName>::try_from("127.0.0.1:").is_err());
    }

    #[test]
    fn ipv6_with_invalid_port() {
        assert!(<&ServerName>::try_from("[fe80::1]:100000").is_err());
        assert!(<&ServerName>::try_from("[fe80::1]!").is_err());
    }

    #[test]
    fn dns_name_with_invalid_port() {
        assert!(<&ServerName>::try_from("matrix.org:hello").is_err());
    }
}
<commit_msg>identifiers: Use fewer transmutes for ServerName<commit_after>//! Matrix-spec compliant server names.
use std::{convert::TryFrom, fmt, mem, rc::Rc, str::FromStr, sync::Arc};

use ruma_identifiers_validation::server_name::validate;

/// A Matrix-spec compliant server name.
#[repr(transparent)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(transparent, crate = "serde"))]
pub struct ServerName(str);

/// An owned server name.
pub type ServerNameBox = Box<ServerName>;

impl ServerName {
    #[allow(clippy::transmute_ptr_to_ptr)]
    fn from_borrowed(s: &str) -> &Self {
        unsafe { mem::transmute(s) }
    }

    fn from_owned(s: Box<str>) -> Box<Self> {
        unsafe { Box::from_raw(Box::into_raw(s) as _) }
    }

    fn into_owned(self: Box<Self>) -> Box<str> {
        unsafe { Box::from_raw(Box::into_raw(self) as _) }
    }

    /// Creates a string slice from this `ServerName`.
    pub fn as_str(&self) -> &str {
        &self.0
    }

    /// Creates a byte slice from this `ServerName`.
    pub fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

impl fmt::Debug for ServerName {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.as_str())
    }
}

impl Clone for Box<ServerName> {
    fn clone(&self) -> Self {
        (**self).to_owned()
    }
}

impl ToOwned for ServerName {
    type Owned = Box<ServerName>;

    fn to_owned(&self) -> Self::Owned {
        Self::from_owned(self.0.into())
    }
}

impl From<&ServerName> for Box<ServerName> {
    fn from(s: &ServerName) -> Self {
        s.to_owned()
    }
}

impl From<&ServerName> for Rc<ServerName> {
    fn from(s: &ServerName) -> Self {
        let rc = Rc::<str>::from(s.as_str());
        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const ServerName) }
    }
}

impl From<&ServerName> for Arc<ServerName> {
    fn from(s: &ServerName) -> Self {
        let arc = Arc::<str>::from(s.as_str());
        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const ServerName) }
    }
}

fn try_from<S>(server_name: S) -> Result<Box<ServerName>, crate::Error>
where
    S: AsRef<str> + Into<Box<str>>,
{
    validate(server_name.as_ref())?;
    Ok(ServerName::from_owned(server_name.into()))
}

impl AsRef<str> for ServerName {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl AsRef<str> for Box<ServerName> {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

impl From<Box<ServerName>> for String {
    fn from(s: Box<ServerName>) -> Self {
        s.into_owned().into()
    }
}

impl<'a> TryFrom<&'a str> for &'a ServerName {
    type Error = crate::Error;

    fn try_from(server_name: &'a str) -> Result<Self, Self::Error> {
        validate(server_name)?;
        Ok(ServerName::from_borrowed(server_name))
    }
}

impl FromStr for Box<ServerName> {
    type Err = crate::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        try_from(s)
    }
}

impl TryFrom<&str> for Box<ServerName> {
    type Error = crate::Error;

    fn try_from(s: &str) -> Result<Self, Self::Error> {
        try_from(s)
    }
}

impl TryFrom<String> for Box<ServerName> {
    type Error = crate::Error;

    fn try_from(s: String) -> Result<Self, Self::Error> {
        try_from(s)
    }
}

impl fmt::Display for ServerName {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Box<ServerName> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        crate::deserialize_id(deserializer, "An IP address or hostname")
    }
}

partial_eq_string!(ServerName);
partial_eq_string!(Box<ServerName>);

#[cfg(test)]
mod tests {
    use std::convert::TryFrom;

    use super::ServerName;

    #[test]
    fn ipv4_host() {
        assert!(<&ServerName>::try_from("127.0.0.1").is_ok());
    }

    #[test]
    fn ipv4_host_and_port() {
        assert!(<&ServerName>::try_from("1.1.1.1:12000").is_ok());
    }

    #[test]
    fn ipv6() {
        assert!(<&ServerName>::try_from("[::1]").is_ok());
    }

    #[test]
    fn ipv6_with_port() {
        assert!(<&ServerName>::try_from("[1234:5678::abcd]:5678").is_ok());
    }

    #[test]
    fn dns_name() {
        assert!(<&ServerName>::try_from("example.com").is_ok());
    }

    #[test]
    fn dns_name_with_port() {
        assert!(<&ServerName>::try_from("ruma.io:8080").is_ok());
    }

    #[test]
    fn empty_string() {
        assert!(<&ServerName>::try_from("").is_err());
    }

    #[test]
    fn invalid_ipv6() {
        assert!(<&ServerName>::try_from("[test::1]").is_err());
    }

    #[test]
    fn ipv4_with_invalid_port() {
        assert!(<&ServerName>::try_from("127.0.0.1:").is_err());
    }

    #[test]
    fn ipv6_with_invalid_port() {
        assert!(<&ServerName>::try_from("[fe80::1]:100000").is_err());
        assert!(<&ServerName>::try_from("[fe80::1]!").is_err());
    }

    #[test]
    fn dns_name_with_invalid_port() {
        assert!(<&ServerName>::try_from("matrix.org:hello").is_err());
    }
}
<|endoftext|>