<commit_before>// Refactoring part00.rs to using expressions and inherent methods for the NumberOrNothing algebric data type

enum NumberOrNothing {
	Number(i32),
	Nothing,
}

impl NumberOrNothing {
	fn print_min(self){
		match self {
			Nothing => println!("The list is empty"),
			Number(min) => println!("The minimum from the list is {}",min),
		}
	}
	fn print_sum(self){
		match self {
			Nothing => println!("No elements in list"),
			Number(min) => println!("The sum is {}",min),
		}
	}
}

use self::NumberOrNothing::{Number,Nothing};

//fn sqr(a:i32) -> i32 {a*a}
//fn abs(a:i32) -> i32 { if a>=0 {a} else {-a} }

fn vec_min(vec:Vec<i32>) -> NumberOrNothing {

	//min_i32 is a clousure
	let min_i32 = |a,b| { if a > b {b} else {a} };

	let mut min = Nothing;
	for el in vec {

		match min {
			Nothing => {min = Number(el);},
			Number(n) => {let new_min = min_i32(n,el);min = Number(new_min);},
		}

	}
	min
}

// Exercise 01.1 -----------------------------------------------

fn vec_sum(vec:Vec<i32>) -> NumberOrNothing {
	match vec.len() {
		0 => {Nothing}
		_ => {let mut sum = 0; for i in vec {sum+=i;} Number(sum) }
	}
}
//-------------------------------------------------Exercise 01.1

// Exercise 01.2 -----------------------------------------------

fn vec_print(vec:Vec<i32>) {
	for e in vec {
		println!("{}",e);
	}
}
//-------------------------------------------------Exercise 01.2

fn read_vec(rang:u32) -> Vec<i32> {
	match rang {
		0 => {vec![]},
		_ => {vec![87,4,7,6,5,9,453]},
	}
}

pub fn main(){
	let vec_list = read_vec(8);
	let min = vec_min(vec_list);
	vec_sum(vec![5,4,3,4]).print_sum();
	vec_print(vec![8,9,3,5]);
	min.print_min();
}

<commit_msg>Update part01.rs<commit_after>// Refactoring part00.rs to using expressions and inherent methods for the NumberOrNothing algebric data type

enum NumberOrNothing {
	Number(i32),
	Nothing,
}

impl NumberOrNothing {
	fn print_min(self){
		match self {
			Nothing => println!("The list is empty"),
			Number(min) => println!("The minimum from the list is {}",min),
		}
	}
	fn print_sum(self){
		match self {
			Nothing => println!("No elements in list"),
			Number(min) => println!("The sum is {}",min),
		}
	}
}

use self::NumberOrNothing::{Number,Nothing};

fn vec_min(vec:Vec<i32>) -> NumberOrNothing {

	//min_i32 is a clousure
	let min_i32 = |a,b| { if a > b {b} else {a} };

	let mut min = Nothing;
	for el in vec {

		match min {
			Nothing => {min = Number(el);},
			Number(n) => {let new_min = min_i32(n,el);min = Number(new_min);},
		}

	}
	min
}

// Exercise 01.1 -----------------------------------------------

fn vec_sum(vec:Vec<i32>) -> NumberOrNothing {
	match vec.len() {
		0 => {Nothing}
		_ => {let mut sum = 0; for i in vec {sum+=i;} Number(sum) }
	}
}
//-------------------------------------------------Exercise 01.1

// Exercise 01.2 -----------------------------------------------

fn vec_print(vec:Vec<i32>) {
	for e in vec {
		println!("{}",e);
	}
}
//-------------------------------------------------Exercise 01.2

fn read_vec(rang:u32) -> Vec<i32> {
	match rang {
		0 => {vec![]},
		_ => {vec![87,4,7,6,5,9,453]},
	}
}

pub fn main(){
	let vec_list = read_vec(8);
	let min = vec_min(vec_list);
	vec_sum(vec![5,4,3,4]).print_sum();
	vec_print(vec![8,9,3,5]);
	min.print_min();
}

<|endoftext|>


<commit_before>// Initial Rust implementation.

use std::time::Instant;
use std::thread;
use std::sync::mpsc::channel;
use std::env;

fn main() {

    let mut num_steps: i64;
    let mut num_threads: i64;
    let step: f64;
    let mut s: f64;
    let my_pi: f64;
    let arguments = std::env::args();

    num_steps = 100000000;

// Check OMP_NUM_THREADS.  If it doesn't exist, default to threads = 1.
    match env::var("OMP_NUM_THREADS") {
        Ok(val) => num_threads=val.parse::<i64>().unwrap(),
        Err(_) => num_threads = 1,
    }

// Arguments are an iterator which is a PITA.
    let mut index = 0;
    for argument in arguments {
        if index == 1 {
            num_steps = argument.parse::<i64>().unwrap();
        }

// Treat second argument as a number of threads that overrides OMP_NUM_THREADS.
        if index == 2 {
            num_threads = argument.parse::<i64>().unwrap();
        }
        index = index + 1;
    }

    print!("Calculating PI using:\n");
    print!("  {} slices\n", num_steps.to_string());
    print!("  {} threads\n", num_threads.to_string());

    let start = Instant::now();

    let (transmit, receive) = channel();

    s = 0.0;
    step = 1.0/num_steps as f64;

    for rank in 0..num_threads {
        let transmit = transmit.clone();
        thread::spawn(move|| {
            let mut s = 0.0;
            let chunkstart = rank * num_steps / num_threads;
            let chunkend = (rank + 1) * num_steps / num_threads;
// Uncomment to check parallelisation:
//            print!("Thread: {} ", rank);
//            print!("Start: {} ", chunkstart);
//            print!("End: {} ", chunkend-1);
//            print!("Length: {}\n", chunkend - chunkstart);
            for i in chunkstart..chunkend {
                let x = ((i as f64) + 0.5)* step;
                s = s + (4.0/(1.0 + (x*x)));
            }
            transmit.send(s).unwrap();
        });
    }

// Gather results.
    for _ in 0..num_threads {
        let r = receive.recv().unwrap();
        s = s + r;
    }

    my_pi = s * step;

    let stop = Instant::now();

    print!("Obtained value of PI: {}\n", my_pi);
    print!("Time Elapsed: {}.", stop.duration_since(start).as_secs());
    print!("{} seconds\n", stop.duration_since(start).subsec_nanos());

}<commit_msg>Increase default number of steps of Rust example to 10^9<commit_after>// Initial Rust implementation.

use std::time::Instant;
use std::thread;
use std::sync::mpsc::channel;
use std::env;

fn main() {

    let mut num_steps: i64;
    let mut num_threads: i64;
    let step: f64;
    let mut s: f64;
    let my_pi: f64;
    let arguments = std::env::args();

    num_steps = 1000000000;

// Check OMP_NUM_THREADS.  If it doesn't exist, default to threads = 1.
    match env::var("OMP_NUM_THREADS") {
        Ok(val) => num_threads=val.parse::<i64>().unwrap(),
        Err(_) => num_threads = 1,
    }

// Arguments are an iterator which is a PITA.
    let mut index = 0;
    for argument in arguments {
        if index == 1 {
            num_steps = argument.parse::<i64>().unwrap();
        }

// Treat second argument as a number of threads that overrides OMP_NUM_THREADS.
        if index == 2 {
            num_threads = argument.parse::<i64>().unwrap();
        }
        index = index + 1;
    }

    print!("Calculating PI using:\n");
    print!("  {} slices\n", num_steps.to_string());
    print!("  {} threads\n", num_threads.to_string());

    let start = Instant::now();

    let (transmit, receive) = channel();

    s = 0.0;
    step = 1.0/num_steps as f64;

    for rank in 0..num_threads {
        let transmit = transmit.clone();
        thread::spawn(move|| {
            let mut s = 0.0;
            let chunkstart = rank * num_steps / num_threads;
            let chunkend = (rank + 1) * num_steps / num_threads;
// Uncomment to check parallelisation:
//            print!("Thread: {} ", rank);
//            print!("Start: {} ", chunkstart);
//            print!("End: {} ", chunkend-1);
//            print!("Length: {}\n", chunkend - chunkstart);
            for i in chunkstart..chunkend {
                let x = ((i as f64) + 0.5)* step;
                s = s + (4.0/(1.0 + (x*x)));
            }
            transmit.send(s).unwrap();
        });
    }

// Gather results.
    for _ in 0..num_threads {
        let r = receive.recv().unwrap();
        s = s + r;
    }

    my_pi = s * step;

    let stop = Instant::now();

    print!("Obtained value of PI: {}\n", my_pi);
    print!("Time Elapsed: {}.", stop.duration_since(start).as_secs());
    print!("{} seconds\n", stop.duration_since(start).subsec_nanos());

}<|endoftext|>


<commit_before>// STD Dependencies -----------------------------------------------------------
use std::fmt;

// Discord Dependencies -------------------------------------------------------
use discord::model::{Attachment, MessageId, ChannelId, UserId, ServerId};

// Message Content Abstraction ------------------------------------------------
pub enum MessageContent {
    Command(String, Vec<String>, Message),
    Upload(Attachment, Message)
}

// Message Abstraction --------------------------------------------------------
#[derive(Debug, Copy, Clone)]
pub struct Message {
    pub id: MessageId,
    pub user_id: UserId,
    pub channel_id: ChannelId,
    pub server_id: ServerId,
    server_is_unique: bool
}

// Public Interface -----------------------------------------------------------
impl Message {

    pub fn from_parts(
        id: MessageId,
        user_id: UserId,
        channel_id: ChannelId,
        server_id: ServerId,
        server_is_unique: bool

    ) -> Message {
        Message {
            id: id,
            user_id: user_id,
            channel_id: channel_id,
            server_id: server_id,
            server_is_unique: server_is_unique
        }
    }

    pub fn parse_contents(
        self,
        content: String,
        attachments: Vec<Attachment>

    ) -> Vec<MessageContent> {

        info!("{} parsing contents...", self);

        if content.starts_with('!') {

            let mut split = content.split(' ');
            let command_name = split.next().unwrap_or("!");

            vec![MessageContent::Command(
                command_name[1..].to_string(),
                split.map(|s| s.to_string()).collect(),
                self
            )]

        } else {
            attachments.into_iter().map(|attachment| {
                MessageContent::Upload(attachment, self)

            }).collect()
        }

    }

    pub fn has_unique_server(&self) -> bool {
        self.server_is_unique
    }

}

// Traits ---------------------------------------------------------------------
impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.has_unique_server() {
            write!(
                f,
                "[Server Message #{} from #{} in #{}(public) for #{}]",
                self.id, self.user_id, self.channel_id, self.server_id
            )

        } else {
            write!(
                f,
                "[Other Message #{} from #{} in #{}]",
                self.id, self.user_id, self.channel_id
            )
        }
    }
}

<commit_msg>Fix parsing empty command names.<commit_after>// STD Dependencies -----------------------------------------------------------
use std::fmt;

// Discord Dependencies -------------------------------------------------------
use discord::model::{Attachment, MessageId, ChannelId, UserId, ServerId};

// Message Content Abstraction ------------------------------------------------
pub enum MessageContent {
    Command(String, Vec<String>, Message),
    Upload(Attachment, Message)
}

// Message Abstraction --------------------------------------------------------
#[derive(Debug, Copy, Clone)]
pub struct Message {
    pub id: MessageId,
    pub user_id: UserId,
    pub channel_id: ChannelId,
    pub server_id: ServerId,
    server_is_unique: bool
}

// Public Interface -----------------------------------------------------------
impl Message {

    pub fn from_parts(
        id: MessageId,
        user_id: UserId,
        channel_id: ChannelId,
        server_id: ServerId,
        server_is_unique: bool

    ) -> Message {
        Message {
            id: id,
            user_id: user_id,
            channel_id: channel_id,
            server_id: server_id,
            server_is_unique: server_is_unique
        }
    }

    pub fn parse_contents(
        self,
        content: String,
        attachments: Vec<Attachment>

    ) -> Vec<MessageContent> {

        info!("{} parsing contents...", self);

        if content.starts_with('!') {

            let mut split = content.trim().split(' ');
            let command = split.next().unwrap_or("!");
            let command_name = command[1..].to_string();

            if command_name.is_empty() {
                vec![]

            } else {
                vec![MessageContent::Command(
                    command_name,
                    split.map(|s| s.to_string()).filter(|s| !s.is_empty()).collect(),
                    self
                )]
            }

        } else {
            attachments.into_iter().map(|attachment| {
                MessageContent::Upload(attachment, self)

            }).collect()
        }

    }

    pub fn has_unique_server(&self) -> bool {
        self.server_is_unique
    }

}

// Traits ---------------------------------------------------------------------
impl fmt::Display for Message {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.has_unique_server() {
            write!(
                f,
                "[Server Message #{} from #{} in #{}(public) for #{}]",
                self.id, self.user_id, self.channel_id, self.server_id
            )

        } else {
            write!(
                f,
                "[Other Message #{} from #{} in #{}]",
                self.id, self.user_id, self.channel_id
            )
        }
    }
}

<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

/// Fielf of View

use std::f32::consts::{PI, PI_2};
use std::num::{Float};
use cgmath::{EuclideanVector};
use common::types::{MapPos, ZFloat};
use map::{Map, Terrain, spiral_iter};
use geom;

struct Shadow {
    left: ZFloat,
    right: ZFloat,
}

fn is_tile_visible(angle: ZFloat, shadows: &Vec<Shadow>) -> bool {
    for shadow in shadows.iter() {
        if shadow.left < angle && shadow.right > angle {
            return false;
        }
    }
    true
}

fn is_obstacle(terrain: &Terrain) -> bool {
    match terrain {
        &Terrain::Trees => true,
        _ => false,
    }
}

// TODO: precalculate all 'atan2' and 'asin' stuff
pub fn fov(map: &Map<Terrain>, fow: &mut Map<bool>, origin: &MapPos) {
    let mut shadows: Vec<Shadow> = vec!();
    let origin3d = geom::map_pos_to_world_pos(origin);
    let range = 7; // TODO
    for pos in spiral_iter(origin, range) {
        if !map.is_inboard(&pos) {
            continue;
        }
        let pos3d = geom::map_pos_to_world_pos(&pos);
        let diff = pos3d - origin3d;
        let distance = diff.length();
        let angle = Float::atan2(diff.x, diff.y); // TODO: optimize
        if is_tile_visible(angle, &shadows) {
            *fow.tile_mut(&pos) = true;
        }
        if is_obstacle(map.tile(&pos)) {
            let obstacle_radius = geom::HEX_IN_RADIUS * 1.1;
            let a = (obstacle_radius / distance).asin();
            let shadow = Shadow{left: angle - a, right: angle + a};
            if shadow.right > PI {
                shadows.push(Shadow{left: -PI, right: shadow.right - PI_2});
            }
            shadows.push(shadow);
        }
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>fov.rs: Fixed unit`s ability to see its won tile<commit_after>// See LICENSE file for copyright and license details.

/// Fielf of View

use std::f32::consts::{PI, PI_2};
use std::num::{Float};
use cgmath::{EuclideanVector};
use common::types::{MapPos, ZFloat};
use map::{Map, Terrain, spiral_iter};
use geom;

struct Shadow {
    left: ZFloat,
    right: ZFloat,
}

fn is_tile_visible(angle: ZFloat, shadows: &Vec<Shadow>) -> bool {
    for shadow in shadows.iter() {
        if shadow.left < angle && shadow.right > angle {
            return false;
        }
    }
    true
}

fn is_obstacle(terrain: &Terrain) -> bool {
    match terrain {
        &Terrain::Trees => true,
        _ => false,
    }
}

// TODO: precalculate all 'atan2' and 'asin' stuff
pub fn fov(map: &Map<Terrain>, fow: &mut Map<bool>, origin: &MapPos) {
    *fow.tile_mut(origin) = true;
    let mut shadows: Vec<Shadow> = vec!();
    let origin3d = geom::map_pos_to_world_pos(origin);
    let range = 7; // TODO
    for pos in spiral_iter(origin, range) {
        if !map.is_inboard(&pos) {
            continue;
        }
        let pos3d = geom::map_pos_to_world_pos(&pos);
        let diff = pos3d - origin3d;
        let distance = diff.length();
        let angle = Float::atan2(diff.x, diff.y); // TODO: optimize
        if is_tile_visible(angle, &shadows) {
            *fow.tile_mut(&pos) = true;
        }
        if is_obstacle(map.tile(&pos)) {
            let obstacle_radius = geom::HEX_IN_RADIUS * 1.1;
            let a = (obstacle_radius / distance).asin();
            let shadow = Shadow{left: angle - a, right: angle + a};
            if shadow.right > PI {
                shadows.push(Shadow{left: -PI, right: shadow.right - PI_2});
            }
            shadows.push(shadow);
        }
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>extern crate bindgen;
extern crate pkg_config;

use std::env;
use std::path::PathBuf;
use std::process::Command;

// Automatically write bindings to libsass
#[allow(dead_code)]
fn write_bindings() {
    let bindings = bindgen::Builder::default()
        .header("libsass/include/sass.h")
        // https://github.com/servo/rust-bindgen/issues/550
        .hide_type("max_align_t")
        .generate()
        .expect("Unable to generate bindings");

    // Write the bindings to the $OUT_DIR/bindings.rs file.
    let out_path = PathBuf::from("src");
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}

fn get_libsass_folder() -> PathBuf {
    env::current_dir().unwrap().join("libsass")
}

// linux/unix
#[cfg(not(target_env="msvc"))]
fn compile() {
    let target = env::var("TARGET").expect("TARGET not found");
    let src = get_libsass_folder();
    let r = Command::new("make").current_dir(&src).output().expect("error running make");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!("cargo:rustc-link-search=native={}", src.join("lib").display());
    println!("cargo:rustc-link-lib=static=sass");
    println!("cargo:rustc-link-lib=dylib={}", if target.contains("darwin") { "c++" } else { "stdc++" });
}

// windows
#[cfg(target_env="msvc")]
fn compile() {
    let src = get_libsass_folder();
    let r = Command::new("msbuild")
        .args(&["win\\libsass.sln", "/p:LIBSASS_STATIC_LIB=1", "/p:Configuration=Release"])
        .current_dir(&src)
        .output()
        .expect("error running msbuild");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!("cargo:rustc-link-search=native={}", src.join("win").join("bin").display());
    println!("cargo:rustc-link-lib=static=libsass");
    println!("cargo:rustc-link-lib=dylib=c++");
}

fn main() {
    // Uncomment the line below to generate bindings. Doesn't work on CI as it
    // requires additional tooling
    // write_bindings();

    // Is it already built?
    if let Ok(_) = pkg_config::find_library("sass") {
        println!("Sass lib already exists");
        println!("or libsass? {:?}", pkg_config::find_library("libsass"));
        return;
    }

    compile();
}
<commit_msg>Do git submodule as part of build.rs<commit_after>extern crate bindgen;
extern crate pkg_config;

use std::env;
use std::path::PathBuf;
use std::process::Command;

// Automatically write bindings to libsass
#[allow(dead_code)]
fn write_bindings() {
    let bindings = bindgen::Builder::default()
        .header("libsass/include/sass.h")
        // https://github.com/servo/rust-bindgen/issues/550
        .hide_type("max_align_t")
        .generate()
        .expect("Unable to generate bindings");

    // Write the bindings to the $OUT_DIR/bindings.rs file.
    let out_path = PathBuf::from("src");
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}

fn get_libsass_folder() -> PathBuf {
    env::current_dir().unwrap().join("libsass")
}

// linux/unix
#[cfg(not(target_env="msvc"))]
fn compile() {
    let target = env::var("TARGET").expect("TARGET not found");
    let src = get_libsass_folder();
    let r = Command::new("make").current_dir(&src).output().expect("error running make");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!("cargo:rustc-link-search=native={}", src.join("lib").display());
    println!("cargo:rustc-link-lib=static=sass");
    println!("cargo:rustc-link-lib=dylib={}", if target.contains("darwin") { "c++" } else { "stdc++" });
}

// windows
#[cfg(target_env="msvc")]
fn compile() {
    let src = get_libsass_folder();
    let r = Command::new("msbuild")
        .args(&["win\\libsass.sln", "/p:LIBSASS_STATIC_LIB=1", "/p:Configuration=Release"])
        .current_dir(&src)
        .output()
        .expect("error running msbuild");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!("cargo:rustc-link-search=native={}", src.join("win").join("bin").display());
    println!("cargo:rustc-link-lib=static=libsass");
    println!("cargo:rustc-link-lib=dylib=c++");
}

fn main() {
    // Uncomment the line below to generate bindings. Doesn't work on CI as it
    // requires additional tooling
    // write_bindings();

    // Is it already built?
    if let Ok(_) = pkg_config::find_library("sass") {
        println!("Sass lib already exists");
        println!("or libsass? {:?}", pkg_config::find_library("libsass"));
        return;
    }

    let _ = Command::new("git").args(&["submodule", "update", "--init"]).status();

    compile();
}
<|endoftext|>


<commit_before>// Copyright (c) 2014, 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate libc;

use std::collections::VecDeque;
use std::cmp;
use std::ffi::CString;
use std::io;
use std::iter::repeat;
use std::mem;
use std::sync::Arc;

use bindings::bpf;
use packet::Packet;
use packet::ethernet::{EthernetPacket, MutableEthernetPacket};
use datalink::{DataLinkChannelIterator, DataLinkChannelType, DataLinkReceiver, DataLinkSender};
use datalink::DataLinkChannelType::{Layer2, Layer3};
use internal;
use util::NetworkInterface;

// NOTE buffer must be word aligned.
#[inline]
pub fn datalink_channel(network_interface: &NetworkInterface,
                        write_buffer_size: usize,
                        read_buffer_size: usize,
                        channel_type: DataLinkChannelType)
    -> io::Result<(Box<DataLinkSender>, Box<DataLinkReceiver>)> {
    #[cfg(target_os = "freebsd")]
    fn get_fd() -> libc::c_int {
        unsafe {
            libc::open(CString::new(&b"/dev/bpf"[..]).unwrap().as_ptr(),
                       libc::O_RDWR,
                       0)
        }
    }

    #[cfg(target_os = "macos")]
    fn get_fd() -> libc::c_int {
        // FIXME This is an arbitrary number of attempts
        for i in 0..1_000isize {
            let fd = unsafe {
                let file_name = format!("/dev/bpf{}", i);
                libc::open(CString::new(file_name.as_bytes()).unwrap().as_ptr(),
                           libc::O_RDWR,
                           0)
            };
            if fd != -1 {
                return fd;
            }
        }

        -1
    }

    #[cfg(target_os = "freebsd")]
    fn set_feedback(fd: libc::c_int) -> io::Result<()> {
        let one: libc::c_uint = 1;
        if unsafe { bpf::ioctl(fd, bpf::BIOCFEEDBACK, &one) } == -1 {
            let err = io::Error::last_os_error();
            unsafe {
                libc::close(fd);
            }
            return Err(err);
        }
        Ok(())
    }

    #[cfg(target_os = "macos")]
    fn set_feedback(_fd: libc::c_int) -> io::Result<()> {
        Ok(())
    }

    match channel_type {
        Layer2 => (),
        Layer3(_) => unimplemented!(),
    }

    let fd = get_fd();
    if fd == -1 {
        return Err(io::Error::last_os_error());
    }
    let mut iface: bpf::ifreq = unsafe { mem::zeroed() };
    let mut i = 0;
    for c in network_interface.name.bytes() {
        iface.ifr_name[i] = c as i8;
        i += 1;
    }

    let buflen = read_buffer_size as libc::c_uint;
    // NOTE Buffer length must be set before binding to an interface
    //      otherwise this will return Invalid Argument
    if unsafe { bpf::ioctl(fd, bpf::BIOCSBLEN, &buflen) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            libc::close(fd);
        }
        return Err(err);
    }

    // Set the interface to use
    if unsafe { bpf::ioctl(fd, bpf::BIOCSETIF, &iface) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            libc::close(fd);
        }
        return Err(err);
    }

    // Return from read as soon as packets are available - don't wait to fill the
    // buffer
    let one: libc::c_uint = 1;
    if unsafe { bpf::ioctl(fd, bpf::BIOCIMMEDIATE, &one) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            libc::close(fd);
        }
        return Err(err);
    }

    let mut header_size = 0;

    // Get the device type
    let mut dlt: libc::c_uint = 0;
    if unsafe { bpf::ioctl(fd, bpf::BIOCGDLT, &mut dlt) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            libc::close(fd);
        }
        return Err(err);
    }

    // The loopback device does weird things
    // FIXME This should really just be another L2 packet header type
    if dlt == bpf::DLT_NULL {
        header_size = 4;

        // Allow packets to be read back after they are written
        if let Err(e) = set_feedback(fd) {
            return Err(e);
        }

    } else {
        // Don't fill in source MAC
        if unsafe { bpf::ioctl(fd, bpf::BIOCSHDRCMPLT, &one) } == -1 {
            let err = io::Error::last_os_error();
            unsafe {
                libc::close(fd);
            }
            return Err(err);
        }
    }

    let fd = Arc::new(internal::FileDesc { fd: fd });
    let sender = Box::new(DataLinkSenderImpl {
        fd: fd.clone(),
        write_buffer: repeat(0u8).take(write_buffer_size).collect(),
        header_size: header_size,
    });
    let receiver = Box::new(DataLinkReceiverImpl {
        fd: fd,
        read_buffer: repeat(0u8).take(read_buffer_size).collect(),
        header_size: header_size,
    });

    Ok((sender, receiver))
}

pub struct DataLinkSenderImpl {
    fd: Arc<internal::FileDesc>,
    write_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkSender for DataLinkSenderImpl {
    #[inline]
    fn build_and_send(&mut self,
                      num_packets: usize,
                      packet_size: usize,
                      func: &mut FnMut(MutableEthernetPacket))
        -> Option<io::Result<()>> {
        let len = num_packets * (packet_size + self.header_size);
        if len >= self.write_buffer.len() {
            None
        } else {
            let min = cmp::min(self.write_buffer.len(), len);
            for chunk in self.write_buffer[..min].chunks_mut(packet_size + self.header_size) {
                // If we're sending on the loopback device, the first 4 bytes must be set to
                // AF_INET
                if self.header_size == 4 {
                    unsafe {
                        *(chunk.as_mut_ptr() as *mut u32) = libc::AF_INET as u32;
                    }
                }
                {
                    let eh = MutableEthernetPacket::new(&mut chunk[self.header_size..]).unwrap();
                    func(eh);
                }
                match unsafe {
                    libc::write(self.fd.fd,
                                chunk.as_ptr() as *const libc::c_void,
                                chunk.len() as libc::size_t)
                } {
                    len if len == -1 => return Some(Err(io::Error::last_os_error())),
                    _ => (),
                }
            }
            Some(Ok(()))
        }
    }

    #[inline]
    fn send_to(&mut self,
               packet: &EthernetPacket,
               _dst: Option<NetworkInterface>)
        -> Option<io::Result<()>> {
        match unsafe {
            libc::write(self.fd.fd,
                        packet.packet().as_ptr() as *const libc::c_void,
                        packet.packet().len() as libc::size_t)
        } {
            len if len == -1 => Some(Err(io::Error::last_os_error())),
            _ => Some(Ok(())),
        }
    }
}

pub struct DataLinkReceiverImpl {
    fd: Arc<internal::FileDesc>,
    read_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkReceiver for DataLinkReceiverImpl {
    fn iter<'a>(&'a mut self) -> Box<DataLinkChannelIterator + 'a> {
        let buflen = self.read_buffer.len();
        Box::new(DataLinkChannelIteratorImpl {
            pc: self,
            // Enough room for minimally sized packets without reallocating
            packets: VecDeque::with_capacity(buflen / 64),
        })
    }
}

pub struct DataLinkChannelIteratorImpl<'a> {
    pc: &'a mut DataLinkReceiverImpl,
    packets: VecDeque<(usize, usize)>,
}

impl<'a> DataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> {
    fn next(&mut self) -> io::Result<EthernetPacket> {
        if self.packets.is_empty() {
            let buflen = match unsafe {
                libc::read(self.pc.fd.fd,
                           self.pc.read_buffer.as_ptr() as *mut libc::c_void,
                           self.pc.read_buffer.len() as libc::size_t)
            } {
                len if len > 0 => len,
                _ => return Err(io::Error::last_os_error()),
            };
            let mut ptr = self.pc.read_buffer.as_mut_ptr();
            let end = unsafe { self.pc.read_buffer.as_ptr().offset(buflen as isize) };
            while (ptr as *const u8) < end {
                unsafe {
                    let packet: *const bpf::bpf_hdr = mem::transmute(ptr);
                    let start = ptr as isize + (*packet).bh_hdrlen as isize -
                                self.pc.read_buffer.as_ptr() as isize;
                    self.packets.push_back((start as usize + self.pc.header_size,
                                            (*packet).bh_caplen as usize - self.pc.header_size));
                    let offset = (*packet).bh_hdrlen as isize + (*packet).bh_caplen as isize;
                    ptr = ptr.offset(bpf::BPF_WORDALIGN(offset));
                }
            }
        }
        let (start, len) = self.packets.pop_front().unwrap();
        Ok(EthernetPacket::new(&self.pc.read_buffer[start..start + len]).unwrap())
    }
}
<commit_msg>Use Iterator::enumerate instead of explicit counter loop, as suggested by clippy<commit_after>// Copyright (c) 2014, 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate libc;

use std::collections::VecDeque;
use std::cmp;
use std::ffi::CString;
use std::io;
use std::iter::repeat;
use std::mem;
use std::sync::Arc;

use bindings::bpf;
use packet::Packet;
use packet::ethernet::{EthernetPacket, MutableEthernetPacket};
use datalink::{DataLinkChannelIterator, DataLinkChannelType, DataLinkReceiver, DataLinkSender};
use datalink::DataLinkChannelType::{Layer2, Layer3};
use internal;
use util::NetworkInterface;

// NOTE buffer must be word aligned.
#[inline]
pub fn datalink_channel(network_interface: &NetworkInterface,
                        write_buffer_size: usize,
                        read_buffer_size: usize,
                        channel_type: DataLinkChannelType)
    -> io::Result<(Box<DataLinkSender>, Box<DataLinkReceiver>)> {
    #[cfg(target_os = "freebsd")]
    fn get_fd() -> libc::c_int {
        unsafe {
            libc::open(CString::new(&b"/dev/bpf"[..]).unwrap().as_ptr(),
                       libc::O_RDWR,
                       0)
        }
    }

    #[cfg(target_os = "macos")]
    fn get_fd() -> libc::c_int {
        // FIXME This is an arbitrary number of attempts
        for i in 0..1_000isize {
            let fd = unsafe {
                let file_name = format!("/dev/bpf{}", i);
                libc::open(CString::new(file_name.as_bytes()).unwrap().as_ptr(),
                           libc::O_RDWR,
                           0)
            };
            if fd != -1 {
                return fd;
            }
        }

        -1
    }

    #[cfg(target_os = "freebsd")]
    fn set_feedback(fd: libc::c_int) -> io::Result<()> {
        let one: libc::c_uint = 1;
        if unsafe { bpf::ioctl(fd, bpf::BIOCFEEDBACK, &one) } == -1 {
            let err = io::Error::last_os_error();
            unsafe {
                libc::close(fd);
            }
            return Err(err);
        }
        Ok(())
    }

    #[cfg(target_os = "macos")]
    fn set_feedback(_fd: libc::c_int) -> io::Result<()> {
        Ok(())
    }

    match channel_type {
        Layer2 => (),
        Layer3(_) => unimplemented!(),
    }

    let fd = get_fd();
    if fd == -1 {
        return Err(io::Error::last_os_error());
    }
    let mut iface: bpf::ifreq = unsafe { mem::zeroed() };
    for (i, c) in network_interface.name.bytes().enumerate() {
        iface.ifr_name[i] = c as i8;
    }

    let buflen = read_buffer_size as libc::c_uint;
    // NOTE Buffer length must be set before binding to an interface
    //      otherwise this will return Invalid Argument
    if unsafe { bpf::ioctl(fd, bpf::BIOCSBLEN, &buflen) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            libc::close(fd);
        }
        return Err(err);
    }

    // Set the interface to use
    if unsafe { bpf::ioctl(fd, bpf::BIOCSETIF, &iface) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            libc::close(fd);
        }
        return Err(err);
    }

    // Return from read as soon as packets are available - don't wait to fill the
    // buffer
    let one: libc::c_uint = 1;
    if unsafe { bpf::ioctl(fd, bpf::BIOCIMMEDIATE, &one) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            libc::close(fd);
        }
        return Err(err);
    }

    let mut header_size = 0;

    // Get the device type
    let mut dlt: libc::c_uint = 0;
    if unsafe { bpf::ioctl(fd, bpf::BIOCGDLT, &mut dlt) } == -1 {
        let err = io::Error::last_os_error();
        unsafe {
            libc::close(fd);
        }
        return Err(err);
    }

    // The loopback device does weird things
    // FIXME This should really just be another L2 packet header type
    if dlt == bpf::DLT_NULL {
        header_size = 4;

        // Allow packets to be read back after they are written
        if let Err(e) = set_feedback(fd) {
            return Err(e);
        }

    } else {
        // Don't fill in source MAC
        if unsafe { bpf::ioctl(fd, bpf::BIOCSHDRCMPLT, &one) } == -1 {
            let err = io::Error::last_os_error();
            unsafe {
                libc::close(fd);
            }
            return Err(err);
        }
    }

    let fd = Arc::new(internal::FileDesc { fd: fd });
    let sender = Box::new(DataLinkSenderImpl {
        fd: fd.clone(),
        write_buffer: repeat(0u8).take(write_buffer_size).collect(),
        header_size: header_size,
    });
    let receiver = Box::new(DataLinkReceiverImpl {
        fd: fd,
        read_buffer: repeat(0u8).take(read_buffer_size).collect(),
        header_size: header_size,
    });

    Ok((sender, receiver))
}

pub struct DataLinkSenderImpl {
    fd: Arc<internal::FileDesc>,
    write_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkSender for DataLinkSenderImpl {
    #[inline]
    fn build_and_send(&mut self,
                      num_packets: usize,
                      packet_size: usize,
                      func: &mut FnMut(MutableEthernetPacket))
        -> Option<io::Result<()>> {
        let len = num_packets * (packet_size + self.header_size);
        if len >= self.write_buffer.len() {
            None
        } else {
            let min = cmp::min(self.write_buffer.len(), len);
            for chunk in self.write_buffer[..min].chunks_mut(packet_size + self.header_size) {
                // If we're sending on the loopback device, the first 4 bytes must be set to
                // AF_INET
                if self.header_size == 4 {
                    unsafe {
                        *(chunk.as_mut_ptr() as *mut u32) = libc::AF_INET as u32;
                    }
                }
                {
                    let eh = MutableEthernetPacket::new(&mut chunk[self.header_size..]).unwrap();
                    func(eh);
                }
                match unsafe {
                    libc::write(self.fd.fd,
                                chunk.as_ptr() as *const libc::c_void,
                                chunk.len() as libc::size_t)
                } {
                    len if len == -1 => return Some(Err(io::Error::last_os_error())),
                    _ => (),
                }
            }
            Some(Ok(()))
        }
    }

    #[inline]
    fn send_to(&mut self,
               packet: &EthernetPacket,
               _dst: Option<NetworkInterface>)
        -> Option<io::Result<()>> {
        match unsafe {
            libc::write(self.fd.fd,
                        packet.packet().as_ptr() as *const libc::c_void,
                        packet.packet().len() as libc::size_t)
        } {
            len if len == -1 => Some(Err(io::Error::last_os_error())),
            _ => Some(Ok(())),
        }
    }
}

pub struct DataLinkReceiverImpl {
    fd: Arc<internal::FileDesc>,
    read_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkReceiver for DataLinkReceiverImpl {
    fn iter<'a>(&'a mut self) -> Box<DataLinkChannelIterator + 'a> {
        let buflen = self.read_buffer.len();
        Box::new(DataLinkChannelIteratorImpl {
            pc: self,
            // Enough room for minimally sized packets without reallocating
            packets: VecDeque::with_capacity(buflen / 64),
        })
    }
}

pub struct DataLinkChannelIteratorImpl<'a> {
    pc: &'a mut DataLinkReceiverImpl,
    packets: VecDeque<(usize, usize)>,
}

impl<'a> DataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> {
    fn next(&mut self) -> io::Result<EthernetPacket> {
        if self.packets.is_empty() {
            let buflen = match unsafe {
                libc::read(self.pc.fd.fd,
                           self.pc.read_buffer.as_ptr() as *mut libc::c_void,
                           self.pc.read_buffer.len() as libc::size_t)
            } {
                len if len > 0 => len,
                _ => return Err(io::Error::last_os_error()),
            };
            let mut ptr = self.pc.read_buffer.as_mut_ptr();
            let end = unsafe { self.pc.read_buffer.as_ptr().offset(buflen as isize) };
            while (ptr as *const u8) < end {
                unsafe {
                    let packet: *const bpf::bpf_hdr = mem::transmute(ptr);
                    let start = ptr as isize + (*packet).bh_hdrlen as isize -
                                self.pc.read_buffer.as_ptr() as isize;
                    self.packets.push_back((start as usize + self.pc.header_size,
                                            (*packet).bh_caplen as usize - self.pc.header_size));
                    let offset = (*packet).bh_hdrlen as isize + (*packet).bh_caplen as isize;
                    ptr = ptr.offset(bpf::BPF_WORDALIGN(offset));
                }
            }
        }
        let (start, len) = self.packets.pop_front().unwrap();
        Ok(EthernetPacket::new(&self.pc.read_buffer[start..start + len]).unwrap())
    }
}
<|endoftext|>


<commit_before>use crate::definitions::{Clamp, Image};
use crate::drawing::Canvas;
use conv::ValueInto;
use image::{GenericImage, ImageBuffer, Pixel};
use std::f32;
use std::i32;

use crate::pixelops::weighted_sum;
use rusttype::{point, Font, PositionedGlyph, Rect, Scale};
use std::cmp::max;

fn layout_glyphs(
    scale: Scale,
    font: &Font,
    text: &str,
    mut f: impl FnMut(PositionedGlyph, Rect<i32>),
) -> (i32, i32) {
    let v_metrics = font.v_metrics(scale);

    let (mut w, mut h) = (0, 0);

    for g in font.layout(text, scale, point(0.0, v_metrics.ascent)) {
        if let Some(bb) = g.pixel_bounding_box() {
            w = max(w, bb.max.x);
            h = max(h, bb.max.y);
            f(g, bb);
        }
    }

    (w, h)
}

/// Get the width and height of the given text, rendered with the given font and scale. Note that this function *does not* support newlines, you must do this manually.
pub fn text_size(scale: Scale, font: &Font, text: &str) -> (i32, i32) {
    layout_glyphs(scale, font, text, |_, _| {})
}

/// Draws colored text on an image in place. `scale` is augmented font scaling on both the x and y axis (in pixels). Note that this function *does not* support newlines, you must do this manually.
pub fn draw_text_mut<'a, C>(
    canvas: &'a mut C,
    color: C::Pixel,
    x: i32,
    y: i32,
    scale: Scale,
    font: &'a Font<'a>,
    text: &'a str,
) where
    C: Canvas,
    <C::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32>,
{
    let image_width = canvas.width() as i32;
    let image_height = canvas.height() as i32;

    layout_glyphs(scale, font, text, |g, bb| {
        g.draw(|gx, gy, gv| {
            let gx = gx as i32 + bb.min.x;
            let gy = gy as i32 + bb.min.y;

            let image_x = gx + x;
            let image_y = gy + y;

            if (0..image_width).contains(&image_x) && (0..image_height).contains(&image_y) {
                let pixel = canvas.get_pixel(image_x as u32, image_y as u32);
                let weighted_color = weighted_sum(pixel, color, 1.0 - gv, gv);
                canvas.draw_pixel(image_x as u32, image_y as u32, weighted_color);
            }
        })
    });
}

/// Draws colored text on an image in place. `scale` is augmented font scaling on both the x and y axis (in pixels). Note that this function *does not* support newlines, you must do this manually.
pub fn draw_text<'a, I>(
    image: &'a mut I,
    color: I::Pixel,
    x: i32,
    y: i32,
    scale: Scale,
    font: &'a Font<'a>,
    text: &'a str,
) -> Image<I::Pixel>
where
    I: GenericImage,
    <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32>,
    I::Pixel: 'static,
{
    let mut out = ImageBuffer::new(image.width(), image.height());
    out.copy_from(image, 0, 0).unwrap();
    draw_text_mut(&mut out, color, x, y, scale, font, text);
    out
}
<commit_msg>Update text.rs (#480)<commit_after>use crate::definitions::{Clamp, Image};
use crate::drawing::Canvas;
use conv::ValueInto;
use image::{GenericImage, ImageBuffer, Pixel};
use std::f32;
use std::i32;

use crate::pixelops::weighted_sum;
use rusttype::{point, Font, PositionedGlyph, Rect, Scale};
use std::cmp::max;

fn layout_glyphs(
    scale: Scale,
    font: &Font,
    text: &str,
    mut f: impl FnMut(PositionedGlyph, Rect<i32>),
) -> (i32, i32) {
    let v_metrics = font.v_metrics(scale);

    let (mut w, mut h) = (0, 0);

    for g in font.layout(text, scale, point(0.0, v_metrics.ascent)) {
        if let Some(bb) = g.pixel_bounding_box() {
            w = max(w, bb.max.x);
            h = max(h, bb.max.y);
            f(g, bb);
        }
    }

    (w, h)
}

/// Get the width and height of the given text, rendered with the given font and scale. Note that this function *does not* support newlines, you must do this manually.
pub fn text_size(scale: Scale, font: &Font, text: &str) -> (i32, i32) {
    layout_glyphs(scale, font, text, |_, _| {})
}

/// Draws colored text on an image in place. `scale` is augmented font scaling on both the x and y axis (in pixels). Note that this function *does not* support newlines, you must do this manually.
pub fn draw_text_mut<'a, C>(
    canvas: &'a mut C,
    color: C::Pixel,
    x: i32,
    y: i32,
    scale: Scale,
    font: &'a Font<'a>,
    text: &'a str,
) where
    C: Canvas,
    <C::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32>,
{
    let image_width = canvas.width() as i32;
    let image_height = canvas.height() as i32;

    layout_glyphs(scale, font, text, |g, bb| {
        g.draw(|gx, gy, gv| {
            let gx = gx as i32 + bb.min.x;
            let gy = gy as i32 + bb.min.y;

            let image_x = gx + x;
            let image_y = gy + y;

            if (0..image_width).contains(&image_x) && (0..image_height).contains(&image_y) {
                let pixel = canvas.get_pixel(image_x as u32, image_y as u32);
                let weighted_color = weighted_sum(pixel, color, 1.0 - gv, gv);
                canvas.draw_pixel(image_x as u32, image_y as u32, weighted_color);
            }
        })
    });
}

/// Draws colored text on a new copy of the image. `scale` is augmented font scaling on both the x and y axis (in pixels). Note that this function *does not* support newlines, you must do this manually.
pub fn draw_text<'a, I>(
    image: &'a mut I,
    color: I::Pixel,
    x: i32,
    y: i32,
    scale: Scale,
    font: &'a Font<'a>,
    text: &'a str,
) -> Image<I::Pixel>
where
    I: GenericImage,
    <I::Pixel as Pixel>::Subpixel: ValueInto<f32> + Clamp<f32>,
    I::Pixel: 'static,
{
    let mut out = ImageBuffer::new(image.width(), image.height());
    out.copy_from(image, 0, 0).unwrap();
    draw_text_mut(&mut out, color, x, y, scale, font, text);
    out
}
<|endoftext|>


<commit_before>#[repr(packed)]
pub struct ElfSectionTag {
    tag_type: u32,
    size: u32,
    num: u16,
    entsize: u16,
    shndx: u16,
    reserved: u16,
    first_section: ElfSectionHeader
}

impl ElfSectionTag {
    pub fn elf_sections(&'static self) -> ElfSectionIter {
        ElfSectionIter {
            current_section: &self.first_section,
            section_index: 0,
            total_sections: self.num as u32,
            entry_size: self.entsize as u64
        }
    }

    pub fn section_count(&self) -> usize {
        self.num as usize
    }

    pub fn size(&self) -> usize {
        self.size as usize
    }
}

#[repr(C)]
pub struct ElfSectionHeader {
    sh_name: u32,
    sh_type: u32,
    sh_flags: u64,
    sh_addr: u64,
    sh_offset: u64,
    sh_size: u64,
    sh_link: u32,
    sh_info: u32,
    sh_addralign: u64,
    sh_entsize: u64
}

impl ElfSectionHeader {
    pub fn name(&self) -> usize {
        self.sh_name as usize
    }

    pub fn section_type(&self) -> usize {
        self.sh_type as usize
    }

    pub fn start_address(&self) -> usize {
        self.sh_addr as usize
    }

    pub fn end_address(&self) -> usize {
        (self.sh_addr + self.sh_size) as usize
    }

    pub fn size(&self) -> usize {
        self.sh_size as usize
    }

    pub fn flags(&self) -> usize {
        self.sh_flags as usize
    }
}

pub struct ElfSectionIter {
    current_section: &'static ElfSectionHeader,
    section_index: u32,
    total_sections: u32,
    entry_size: u64
}

impl Iterator for ElfSectionIter {
    type Item = &'static ElfSectionHeader;

    fn next(&mut self) -> Option<Self::Item> {
        if self.section_index >= self.total_sections {
            return None;
        } else {
            let section = self.current_section;
            let next_section_addr =
                (self.current_section as *const ElfSectionHeader as u64) + self.entry_size;
            let next_section = unsafe {
                &*(next_section_addr as *const ElfSectionHeader)
            };

            self.current_section = next_section;
            self.section_index += 1;

            Some(section)
        }
    }
}
<commit_msg>Adjust representation of Elf section tags in memory.<commit_after>// The size of an ELF header tag, in bytes. This was calculated
// from reading the ELF format specification.
const ELF_SECTION_HEADER_SIZE: u64 = 56;

#[repr(C, packed)]
pub struct ElfSectionTag {
    tag_type: u32,
    size: u32,
    num: u16,
    entsize: u16,
    shndx: u16,
    reserved: u16,
    first_section: ElfSectionHeader
}

impl ElfSectionTag {
    pub fn elf_sections(&'static self) -> ElfSectionIter {
        ElfSectionIter {
            current_section: &self.first_section,
            section_index: 0,
            total_sections: self.num as u32,
            entry_size: self.entsize as u64
        }
    }

    pub fn section_count(&self) -> usize {
        self.num as usize
    }

    pub fn size(&self) -> usize {
        self.size as usize
    }

    pub fn entry_size(&self) -> usize {
        self.entsize as usize
    }
}

#[repr(C)]
pub struct ElfSectionHeader {
    sh_name: u32,
    sh_type: u32,
    sh_flags: u64,
    sh_addr: u64,
    sh_offset: u64,
    sh_size: u64,
    sh_link: u32,
    sh_info: u32,
    sh_addralign: u64,
    sh_entsize: u64
}

impl ElfSectionHeader {
    pub fn name(&self) -> usize {
        self.sh_name as usize
    }

    pub fn section_type(&self) -> usize {
        self.sh_type as usize
    }

    pub fn start_address(&self) -> usize {
        self.sh_addr as usize
    }

    pub fn end_address(&self) -> usize {
        (self.sh_addr + self.sh_size) as usize
    }

    pub fn size(&self) -> usize {
        self.sh_size as usize
    }

    pub fn flags(&self) -> usize {
        self.sh_flags as usize
    }

    pub fn entry_size(&self) -> usize {
        self.sh_entsize as usize
    }
}

pub struct ElfSectionIter {
    current_section: &'static ElfSectionHeader,
    section_index: u32,
    total_sections: u32,
    entry_size: u64
}

impl Iterator for ElfSectionIter {
    type Item = &'static ElfSectionHeader;

    fn next(&mut self) -> Option<Self::Item> {
        if self.section_index >= self.total_sections {
            return None;
        } else {
            let section = self.current_section;
            let next_section_addr =
                (self.current_section as *const ElfSectionHeader as u64) + self.entry_size;
            let next_section = unsafe {
                &*(next_section_addr as *const ElfSectionHeader)
            };

            self.current_section = next_section;
            self.section_index += 1;

            Some(section)
        }
    }
}
<|endoftext|>


<commit_before>#![allow(missing_doc)]
#![allow(dead_code)]

//! A first person camera.

use std::num::{One, Zero};
use input::{Button, Keyboard};
use input::keyboard;
use {
    input,
    Camera,
};

bitflags!(flags Keys: u8 {
    static MoveForward = 0b00000001,
    static MoveBack    = 0b00000010,
    static StrafeLeft  = 0b00000100,
    static StrafeRight = 0b00001000,
    static FlyUp       = 0b00010000,
    static FlyDown     = 0b00100000
})

/// First person camera settings.
pub struct FirstPersonSettings<T=f32> {
    /// Which button to press to move forward.
    pub move_forward_button: input::Button,
    /// Which button to press to move backward.
    pub move_backward_button: input::Button,
    /// Which button to press to strafe left.
    pub strafe_left_button: input::Button,
    /// Which button to press to strafe right.
    pub strafe_right_button: input::Button,
    /// Which button to press to fly up.
    pub fly_up_button: input::Button,
    /// Which button to press to fly down.
    pub fly_down_button: input::Button,
    /// Which button to press to move faster.
    pub move_faster_button: input::Button,
    /// The horizontal movement speed.
    ///
    /// This is measured in units per second.
    pub speed_horizontal: T,
    /// The vertical movement speed.
    ///
    /// This is measured in units per second.
    pub speed_vertical: T,
}

impl<T: One> FirstPersonSettings<T> {
    /// Creates new first person camera settings with wasd defaults.
    pub fn keyboard_wasd() -> FirstPersonSettings<T> {
        FirstPersonSettings {
            move_forward_button: Keyboard(keyboard::W),
            move_backward_button: Keyboard(keyboard::S),
            strafe_left_button: Keyboard(keyboard::A),
            strafe_right_button: Keyboard(keyboard::D),
            fly_up_button: Keyboard(keyboard::Space),
            fly_down_button: Keyboard(keyboard::LShift),
            move_faster_button: Keyboard(keyboard::LCtrl),
            speed_horizontal: One::one(),
            speed_vertical: One::one(),
        }
    }

    /// Creates a new first person camera settings with esdf defaults.
    pub fn keyboard_esdf() -> FirstPersonSettings<T> {
        FirstPersonSettings {
            move_forward_button: Keyboard(keyboard::E),
            move_backward_button: Keyboard(keyboard::D),
            strafe_left_button: Keyboard(keyboard::S),
            strafe_right_button: Keyboard(keyboard::F),
            fly_up_button: Keyboard(keyboard::Space),
            fly_down_button: Keyboard(keyboard::Z),
            move_faster_button: Keyboard(keyboard::LShift),
            speed_horizontal: One::one(),
            speed_vertical: One::one(),
        }
    }
}

/// Models a flying first person camera.
pub struct FirstPerson<T=f32> {
    /// The first person camera settings.
    pub settings: FirstPersonSettings<T>,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The direction we are heading.
    pub direction: [T, ..3],
    /// The position of the camera.
    pub position: [T, ..3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
    /// The keys that are pressed.
    keys: Keys,
}

impl<T: Float + FromPrimitive + Copy + FloatMath> FirstPerson<T> {
    /// Creates a new first person camera.
    pub fn new(
        position: [T, ..3],
        settings: FirstPersonSettings<T>
    ) -> FirstPerson<T> {
        let _0: T = Zero::zero();
        FirstPerson {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            position: position,
            velocity: One::one(),
        }
    }

    /// Computes camera.
    pub fn camera(&self, dt: f64) -> Camera<T> {
        let dt: T = FromPrimitive::from_f64(dt).unwrap();
        let dh = dt * self.velocity * self.settings.speed_horizontal;
        let [dx, dy, dz] = self.direction;
        let (s, c) = (self.yaw.sin(), self.yaw.cos());
        let mut camera = Camera::new(
            self.position[0] + (s * dx - c * dz) * dh,
            self.position[1] + dy * dt * self.settings.speed_vertical,
            self.position[2] + (s * dz + c * dx) * dh
        );
        camera.set_yaw_pitch(self.yaw, self.pitch);
        camera
    }

    /// Updates the position.
    pub fn update(&mut self, dt: f64) {
        let cam = self.camera(dt);
        self.position = cam.position;
    }

    /// Handles game event and updates camera.
    pub fn input(&mut self, e: &input::InputEvent) {
        let &FirstPerson {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
            ..
        } = self;

        let pi: T = Float::pi();
        let sqrt2: T = Float::sqrt2();
        let _0: T = Zero::zero();
        let _1: T = One::one();
        let _2: T = FromPrimitive::from_int(2).unwrap();
        let _3: T = FromPrimitive::from_int(3).unwrap();
        let _4: T = FromPrimitive::from_int(4).unwrap();
        let _360: T = FromPrimitive::from_int(360).unwrap();
        match *e {
            input::Move(input::MouseRelative(dx, dy)) => {
                let dx: T = FromPrimitive::from_f64(dx).unwrap();
                let dy: T = FromPrimitive::from_f64(dy).unwrap();
                *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
                *pitch = *pitch + dy / _360 * pi / _4;
                *pitch = (*pitch).min(pi / _2).max(-pi / _2);
            },
            input::Press(button) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |k, x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                    keys.insert(k);
                };
                match button {
                    x if x == settings.move_forward_button => set(MoveForward, -_1, dy, dz),
                    x if x == settings.move_backward_button => set(MoveBack, _1, dy, dz),
                    x if x == settings.strafe_left_button => set(StrafeLeft, dx, dy, _1),
                    x if x == settings.strafe_right_button => set(StrafeRight, dx, dy, -_1),
                    x if x == settings.fly_up_button => set(FlyUp, dx, _1, dz),
                    x if x == settings.fly_down_button => set(FlyDown, dx, -_1, dz),
                    x if x == settings.move_faster_button => *velocity = _2,
                    _ => {}
                }
            },
            input::Release(button) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                };
                let release = |key, rev_key, rev_val| {
                    keys.remove(key);
                    if keys.contains(rev_key) { rev_val } else { _0 }
                };
                match button {
                    x if x == settings.move_forward_button => set(release(MoveForward, MoveBack, _1), dy, dz),
                    x if x == settings.move_backward_button => set(release(MoveBack, MoveForward, -_1), dy, dz),
                    x if x == settings.strafe_left_button => set(dx, dy, release(StrafeLeft, StrafeRight, -_1)),
                    x if x == settings.strafe_right_button => set(dx, dy, release(StrafeRight, StrafeLeft, _1)),
                    x if x == settings.fly_up_button => set(dx, release(FlyUp, FlyDown, -_1), dz),
                    x if x == settings.fly_down_button => set(dx, release(FlyDown, FlyUp, _1), dz),
                    x if x == settings.move_faster_button => *velocity = _1,
                    _ => {}
                }
            },
            _ => {},
        }
    }
}

<commit_msg>Upgraded to latest Rust<commit_after>#![allow(missing_doc)]
#![allow(dead_code)]

//! A first person camera.

use std::num::{One, Zero};
use input::{Button, Keyboard};
use input::keyboard;
use {
    input,
    Camera,
};

bitflags!(flags Keys: u8 {
    const MoveForward   = 0b00000001,
    const MoveBack      = 0b00000010,
    const StrafeLeft    = 0b00000100,
    const StrafeRight   = 0b00001000,
    const FlyUp         = 0b00010000,
    const FlyDown       = 0b00100000
})

/// First person camera settings.
pub struct FirstPersonSettings<T=f32> {
    /// Which button to press to move forward.
    pub move_forward_button: input::Button,
    /// Which button to press to move backward.
    pub move_backward_button: input::Button,
    /// Which button to press to strafe left.
    pub strafe_left_button: input::Button,
    /// Which button to press to strafe right.
    pub strafe_right_button: input::Button,
    /// Which button to press to fly up.
    pub fly_up_button: input::Button,
    /// Which button to press to fly down.
    pub fly_down_button: input::Button,
    /// Which button to press to move faster.
    pub move_faster_button: input::Button,
    /// The horizontal movement speed.
    ///
    /// This is measured in units per second.
    pub speed_horizontal: T,
    /// The vertical movement speed.
    ///
    /// This is measured in units per second.
    pub speed_vertical: T,
}

impl<T: One> FirstPersonSettings<T> {
    /// Creates new first person camera settings with wasd defaults.
    pub fn keyboard_wasd() -> FirstPersonSettings<T> {
        FirstPersonSettings {
            move_forward_button: Keyboard(keyboard::W),
            move_backward_button: Keyboard(keyboard::S),
            strafe_left_button: Keyboard(keyboard::A),
            strafe_right_button: Keyboard(keyboard::D),
            fly_up_button: Keyboard(keyboard::Space),
            fly_down_button: Keyboard(keyboard::LShift),
            move_faster_button: Keyboard(keyboard::LCtrl),
            speed_horizontal: One::one(),
            speed_vertical: One::one(),
        }
    }

    /// Creates a new first person camera settings with esdf defaults.
    pub fn keyboard_esdf() -> FirstPersonSettings<T> {
        FirstPersonSettings {
            move_forward_button: Keyboard(keyboard::E),
            move_backward_button: Keyboard(keyboard::D),
            strafe_left_button: Keyboard(keyboard::S),
            strafe_right_button: Keyboard(keyboard::F),
            fly_up_button: Keyboard(keyboard::Space),
            fly_down_button: Keyboard(keyboard::Z),
            move_faster_button: Keyboard(keyboard::LShift),
            speed_horizontal: One::one(),
            speed_vertical: One::one(),
        }
    }
}

/// Models a flying first person camera.
pub struct FirstPerson<T=f32> {
    /// The first person camera settings.
    pub settings: FirstPersonSettings<T>,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The direction we are heading.
    pub direction: [T, ..3],
    /// The position of the camera.
    pub position: [T, ..3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
    /// The keys that are pressed.
    keys: Keys,
}

impl<T: Float + FromPrimitive + Copy + FloatMath> FirstPerson<T> {
    /// Creates a new first person camera.
    pub fn new(
        position: [T, ..3],
        settings: FirstPersonSettings<T>
    ) -> FirstPerson<T> {
        let _0: T = Zero::zero();
        FirstPerson {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            position: position,
            velocity: One::one(),
        }
    }

    /// Computes camera.
    pub fn camera(&self, dt: f64) -> Camera<T> {
        let dt: T = FromPrimitive::from_f64(dt).unwrap();
        let dh = dt * self.velocity * self.settings.speed_horizontal;
        let [dx, dy, dz] = self.direction;
        let (s, c) = (self.yaw.sin(), self.yaw.cos());
        let mut camera = Camera::new(
            self.position[0] + (s * dx - c * dz) * dh,
            self.position[1] + dy * dt * self.settings.speed_vertical,
            self.position[2] + (s * dz + c * dx) * dh
        );
        camera.set_yaw_pitch(self.yaw, self.pitch);
        camera
    }

    /// Updates the position.
    pub fn update(&mut self, dt: f64) {
        let cam = self.camera(dt);
        self.position = cam.position;
    }

    /// Handles game event and updates camera.
    pub fn input(&mut self, e: &input::InputEvent) {
        let &FirstPerson {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
            ..
        } = self;

        let pi: T = Float::pi();
        let sqrt2: T = Float::sqrt2();
        let _0: T = Zero::zero();
        let _1: T = One::one();
        let _2: T = FromPrimitive::from_int(2).unwrap();
        let _3: T = FromPrimitive::from_int(3).unwrap();
        let _4: T = FromPrimitive::from_int(4).unwrap();
        let _360: T = FromPrimitive::from_int(360).unwrap();
        match *e {
            input::Move(input::MouseRelative(dx, dy)) => {
                let dx: T = FromPrimitive::from_f64(dx).unwrap();
                let dy: T = FromPrimitive::from_f64(dy).unwrap();
                *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
                *pitch = *pitch + dy / _360 * pi / _4;
                *pitch = (*pitch).min(pi / _2).max(-pi / _2);
            },
            input::Press(button) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |k, x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                    keys.insert(k);
                };
                match button {
                    x if x == settings.move_forward_button => set(MoveForward, -_1, dy, dz),
                    x if x == settings.move_backward_button => set(MoveBack, _1, dy, dz),
                    x if x == settings.strafe_left_button => set(StrafeLeft, dx, dy, _1),
                    x if x == settings.strafe_right_button => set(StrafeRight, dx, dy, -_1),
                    x if x == settings.fly_up_button => set(FlyUp, dx, _1, dz),
                    x if x == settings.fly_down_button => set(FlyDown, dx, -_1, dz),
                    x if x == settings.move_faster_button => *velocity = _2,
                    _ => {}
                }
            },
            input::Release(button) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                };
                let release = |key, rev_key, rev_val| {
                    keys.remove(key);
                    if keys.contains(rev_key) { rev_val } else { _0 }
                };
                match button {
                    x if x == settings.move_forward_button => set(release(MoveForward, MoveBack, _1), dy, dz),
                    x if x == settings.move_backward_button => set(release(MoveBack, MoveForward, -_1), dy, dz),
                    x if x == settings.strafe_left_button => set(dx, dy, release(StrafeLeft, StrafeRight, -_1)),
                    x if x == settings.strafe_right_button => set(dx, dy, release(StrafeRight, StrafeLeft, _1)),
                    x if x == settings.fly_up_button => set(dx, release(FlyUp, FlyDown, -_1), dz),
                    x if x == settings.fly_down_button => set(dx, release(FlyDown, FlyUp, _1), dz),
                    x if x == settings.move_faster_button => *velocity = _1,
                    _ => {}
                }
            },
            _ => {},
        }
    }
}

<|endoftext|>


<commit_before>use header::HeaderList;
use header::Header;
use header::ContentLength;
use header::StompHeaderSet;
use subscription::AckMode;
use std::io::Result;
use std::io::Error;
use std::io::ErrorKind::InvalidInput;
use std::io::Write;
use std::io::Read;
use std::io::BufRead;
use std::str::from_utf8;
use std::fmt;
use std::fmt::Formatter;
use frame::{Frame, Transmission};
use std::collections::VecDeque;

pub struct FrameBuffer {
  buffer: VecDeque<u8>,
  parse_state: ParseState
}

struct ParseState {
  offset: u32,
  command: Option<String>,
  headers: HeaderList,
  body: Option<Vec<u8>>,
  section: FrameSection,
}

impl ParseState {
  fn new() -> ParseState {
    ParseState {
      offset: 0,
      command: None,
      headers: header_list![],
      body: None,
      section: FrameSection::Command
    }
  }
}

enum FrameSection {
  Command,
  Headers,
  Body
}

enum ReadCommandResult {
  HeartBeat,
  Command(String),
  Incomplete
}

enum ReadHeaderResult {
  Header(Header),
  EndOfHeaders,
  Incomplete
}

enum ReadBodyResult {
  Body(Vec<u8>),
  Incomplete
}

impl FrameBuffer {
  pub fn new() -> FrameBuffer {
    FrameBuffer {
      buffer: VecDeque::with_capacity(512), //TODO: VecDeque?
      parse_state: ParseState::new()
    }
  }

  pub fn len(&self) -> usize {
    self.buffer.len()
  }

  pub fn append(&mut self, bytes: &[u8]) { // TODO: Return result?
    for byte in bytes {
      self.buffer.push_back(*byte);
    }
    debug!("Copied {} bytes into the frame buffer.", bytes.len());
  }

  pub fn read_transmission(&mut self) -> Option<Transmission> {
    match self.parse_state.section {
      FrameSection::Command => self.resume_parsing_at_command(),
      FrameSection::Headers => self.resume_parsing_at_headers(),
      FrameSection::Body    => self.resume_parsing_at_body()
    }
  }

  fn resume_parsing_at_command(&mut self) -> Option<Transmission> {
    debug!("Parsing command.");
    match self.read_command() {
      ReadCommandResult::HeartBeat => Some(Transmission::HeartBeat),
      ReadCommandResult::Command(command_string) => {
        self.parse_state.command = Some(command_string);
        self.parse_state.section = FrameSection::Headers;
        self.resume_parsing_at_headers()
      },
      ReadCommandResult::Incomplete => None
    }
  }

  fn resume_parsing_at_headers(&mut self) -> Option<Transmission> {
    debug!("Parsing headers.");
    match self.read_header() {
      ReadHeaderResult::Header(header) => {
        self.parse_state.headers.push(header);
        self.resume_parsing_at_headers()
      },
      ReadHeaderResult::EndOfHeaders => {
        self.parse_state.section = FrameSection::Body;
        self.resume_parsing_at_body()
      },
      ReadHeaderResult::Incomplete => None
    }
  }

//TODO: Eliminate clone()s
  fn resume_parsing_at_body(&mut self) -> Option<Transmission> {
    debug!("Parsing body.");
    match self.read_body() {
      ReadBodyResult::Body(body_bytes) => {
        //self.parse_state.body = Some(body_bytes);
        let command = match self.parse_state.command {
          Some(ref command) => command.to_string(),
          None => panic!("No COMMAND found.")
        };
        let headers = self.parse_state.headers.clone();
        let body = body_bytes;
        let frame = Frame {
          command: command,
          headers: headers,
          body: body
        };
        self.reset_parse_state();
        Some(Transmission::CompleteFrame(frame))
      },
      ReadBodyResult::Incomplete => None
    }
  }

  fn reset_parse_state(&mut self) {
    self.parse_state.offset = 0;
    self.parse_state.command = None;
    self.parse_state.headers = header_list![];
    self.parse_state.body = None;
    self.parse_state.section = FrameSection::Command;
  }

  // Replace these methods with bridge-buffer concept
  fn read_into_vec(&mut self, n: usize) -> Vec<u8> {
    let mut vec = Vec::with_capacity(n);
    for _ in 0..n {
      let byte = match self.buffer.pop_front() {
        Some(byte) => byte,
        None => panic!("Attempted to read beyond the end of the buffer!")
      };
      vec.push(byte);
    }
    debug!("Removed {} bytes from frame buffer, new size: {}", n, self.buffer.len());
    vec
  }

  // Wasteful with allocations
  fn read_into_string(&mut self, n: usize) -> String {
    let vec = self.read_into_vec(n);
    let string = from_utf8(&vec)
      .ok()
      .expect("Attempted to read a string that was not utf8.");
    return string.to_string();
  }

  fn discard(&mut self, n: usize) {
    for _ in 0..n {
      let _ = &mut self.buffer.pop_front();
    }
  }

  fn chomp(mut line: String) -> String {
    // This may be suboptimal, but fine for now
    let chomped_length : usize;
    {
      let chars_to_remove : &[char] = &['\r', '\n'];
      let trimmed_line : &str = line.trim_right_matches(chars_to_remove);
      chomped_length = trimmed_line.len();
    }
    line.truncate(chomped_length);
    line
  }

  fn read_command(&mut self) -> ReadCommandResult {
    use frame_buffer::ReadCommandResult::*;
    //TODO: check for \r\n
    match self.find_next('\n' as u8) {
      Some(0) => {
        debug!("Found Heartbeat");
        let num_bytes = 1;
        self.discard(num_bytes);
        HeartBeat
      },
      Some(index) => {
        debug!("Found command ending @ index {}", index);
        let num_bytes = index + 1;
        let command = self.read_into_string(num_bytes as usize);
        let command = FrameBuffer::chomp(command);
        debug!("Command -> '{}'", command);
        Command(command)
      },
      None => Incomplete
    }
  }

  fn read_header(&mut self) -> ReadHeaderResult {
    match self.find_next('\n' as u8) {
      Some(index) => {
        debug!("Found header ending @ index {}", index);
        let num_bytes = index + 1;
        let header_string = self.read_into_string(num_bytes as usize);
        let header_string = FrameBuffer::chomp(header_string);
        debug!("Header -> '{}'", header_string);
        if(header_string == "") {
          return ReadHeaderResult::EndOfHeaders;
        }
        let header = Header::decode_string(&header_string).expect("Invalid header encountered.");
        ReadHeaderResult::Header(header)
      },
      None => ReadHeaderResult::Incomplete
    }
  }

  // TODO: Need to read both by Content-Length and by null byte
  // This is easier if we've already created the header set
  fn read_body(&mut self) -> ReadBodyResult {
    let maybe_body : Option<Vec<u8>> = match self.parse_state.headers.get_content_length() {
      Some(ContentLength(num_bytes)) => self.read_body_by_content_length(num_bytes as usize),
      None => self.read_body_by_null_octet()
    };
    match maybe_body {
      Some(body) => ReadBodyResult::Body(body),
      None => ReadBodyResult::Incomplete
    }
  }

  fn read_body_by_content_length(&mut self, content_length: usize) -> Option<Vec<u8>> {
    debug!("Reading body by content length.");
    if self.buffer.len() < content_length {
      debug!("Not enough bytes to form body; needed {}, only had {}.", content_length, self.buffer.len());
      return None;
    }
    let body = self.read_into_vec(content_length);
    debug!("Body -> '{}'", FrameBuffer::body_as_string(&body));
    Some(body)
  }

  fn read_body_by_null_octet(&mut self) -> Option<Vec<u8>> {
    debug!("Reading body by null octet.");
    match self.find_next(0u8) {
      Some(index) => {
        debug!("Found body ending @ index {}", index);
        let num_bytes = index + 1;
        let mut body = self.read_into_vec(num_bytes as usize);
        body.pop(); // Discard null octet
        debug!("Body -> '{}'", FrameBuffer::body_as_string(&body));
        Some(body)
      },
      None => None
    }
  }

  fn body_as_string(body: &Vec<u8>) -> &str {
    match from_utf8(&body) {
      Ok(ref s) => *s,
      Err(_) => "<Non-utf8 Binary Content>"
    }
  }

  fn find_next(&self, needle: u8) -> Option<u32> {
    let mut step = 0u32;
    for byte in &self.buffer {
      if *byte == needle {
        return Some(step);
      }
      step += 1;
    }
    None
  }
}
<commit_msg>Fixed parsing.<commit_after>use header::HeaderList;
use header::Header;
use header::ContentLength;
use header::StompHeaderSet;
use subscription::AckMode;
use std::io::Result;
use std::io::Error;
use std::io::ErrorKind::InvalidInput;
use std::io::Write;
use std::io::Read;
use std::io::BufRead;
use std::str::from_utf8;
use std::fmt;
use std::fmt::Formatter;
use frame::{Frame, Transmission};
use std::collections::VecDeque;

pub struct FrameBuffer {
  buffer: VecDeque<u8>,
  parse_state: ParseState
}

struct ParseState {
  offset: u32,
  command: Option<String>,
  headers: HeaderList,
  body: Option<Vec<u8>>,
  section: FrameSection,
}

impl ParseState {
  fn new() -> ParseState {
    ParseState {
      offset: 0,
      command: None,
      headers: header_list![],
      body: None,
      section: FrameSection::Command
    }
  }
}

enum FrameSection {
  Command,
  Headers,
  Body
}

enum ReadCommandResult {
  HeartBeat,
  Command(String),
  Incomplete
}

enum ReadHeaderResult {
  Header(Header),
  EndOfHeaders,
  Incomplete
}

enum ReadBodyResult {
  Body(Vec<u8>),
  Incomplete
}

impl FrameBuffer {
  pub fn new() -> FrameBuffer {
    FrameBuffer {
      buffer: VecDeque::with_capacity(512), //TODO: VecDeque?
      parse_state: ParseState::new()
    }
  }

  pub fn len(&self) -> usize {
    self.buffer.len()
  }

  pub fn append(&mut self, bytes: &[u8]) { // TODO: Return result?
    for byte in bytes {
      self.buffer.push_back(*byte);
    }
    debug!("Copied {} bytes into the frame buffer.", bytes.len());
  }

  pub fn read_transmission(&mut self) -> Option<Transmission> {
    match self.parse_state.section {
      FrameSection::Command => self.resume_parsing_at_command(),
      FrameSection::Headers => self.resume_parsing_at_headers(),
      FrameSection::Body    => self.resume_parsing_at_body()
    }
  }

  fn resume_parsing_at_command(&mut self) -> Option<Transmission> {
    debug!("Parsing command.");
    match self.read_command() {
      ReadCommandResult::HeartBeat => Some(Transmission::HeartBeat),
      ReadCommandResult::Command(command_string) => {
        self.parse_state.command = Some(command_string);
        self.parse_state.section = FrameSection::Headers;
        self.resume_parsing_at_headers()
      },
      ReadCommandResult::Incomplete => None
    }
  }

  fn resume_parsing_at_headers(&mut self) -> Option<Transmission> {
    debug!("Parsing headers.");
    match self.read_header() {
      ReadHeaderResult::Header(header) => {
        self.parse_state.headers.push(header);
        self.resume_parsing_at_headers()
      },
      ReadHeaderResult::EndOfHeaders => {
        self.parse_state.section = FrameSection::Body;
        self.resume_parsing_at_body()
      },
      ReadHeaderResult::Incomplete => None
    }
  }

//TODO: Eliminate clone()s
  fn resume_parsing_at_body(&mut self) -> Option<Transmission> {
    debug!("Parsing body.");
    match self.read_body() {
      ReadBodyResult::Body(body_bytes) => {
        //self.parse_state.body = Some(body_bytes);
        let command = match self.parse_state.command {
          Some(ref command) => command.to_string(),
          None => panic!("No COMMAND found.")
        };
        let headers = self.parse_state.headers.clone();
        let body = body_bytes;
        let frame = Frame {
          command: command,
          headers: headers,
          body: body
        };
        self.reset_parse_state();
        Some(Transmission::CompleteFrame(frame))
      },
      ReadBodyResult::Incomplete => None
    }
  }

  fn reset_parse_state(&mut self) {
    self.parse_state.offset = 0;
    self.parse_state.command = None;
    self.parse_state.headers = header_list![];
    self.parse_state.body = None;
    self.parse_state.section = FrameSection::Command;
  }

  // Replace these methods with bridge-buffer concept
  fn read_into_vec(&mut self, n: usize) -> Vec<u8> {
    let mut vec = Vec::with_capacity(n);
    for _ in 0..n {
      let byte = match self.buffer.pop_front() {
        Some(byte) => byte,
        None => panic!("Attempted to read beyond the end of the buffer!")
      };
      vec.push(byte);
    }
    debug!("Removed {} bytes from frame buffer, new size: {}", n, self.buffer.len());
    vec
  }

  // Wasteful with allocations
  fn read_into_string(&mut self, n: usize) -> String {
    let vec = self.read_into_vec(n);
    let string = from_utf8(&vec)
      .ok()
      .expect("Attempted to read a string that was not utf8.");
    return string.to_string();
  }

  fn discard(&mut self, n: usize) {
    for _ in 0..n {
      let _ = &mut self.buffer.pop_front();
    }
  }

  fn chomp(mut line: String) -> String {
    // This may be suboptimal, but fine for now
    let chomped_length : usize;
    {
      let chars_to_remove : &[char] = &['\r', '\n'];
      let trimmed_line : &str = line.trim_right_matches(chars_to_remove);
      chomped_length = trimmed_line.len();
    }
    line.truncate(chomped_length);
    line
  }

  fn read_command(&mut self) -> ReadCommandResult {
    use frame_buffer::ReadCommandResult::*;
    //TODO: check for \r\n
    match self.find_next('\n' as u8) {
/*      Some(0) => {
        debug!("Found Heartbeat");
        let num_bytes = 1;
        self.discard(num_bytes);
        HeartBeat
      },
*/
      Some(index) => {
        debug!("Found command ending @ index {}", index);
        let num_bytes = index + 1;
        let command = self.read_into_string(num_bytes as usize);
        let command = FrameBuffer::chomp(command);
        debug!("Chomped length: {}", command.len());
        if command == "" {
          debug!("Found HeartBeat");
          return HeartBeat;
        }
        if command.len() == 1 {
          debug!("Byte: {}", command.as_bytes()[0]);
        }
        debug!("Command -> '{}'", command);
        Command(command)
      },
      None => Incomplete
    }
  }

  fn read_header(&mut self) -> ReadHeaderResult {
    match self.find_next('\n' as u8) {
      Some(index) => {
        debug!("Found header ending @ index {}", index);
        let num_bytes = index + 1;
        let header_string = self.read_into_string(num_bytes as usize);
        let header_string = FrameBuffer::chomp(header_string);
        debug!("Header -> '{}'", header_string);
        if header_string == "" {
          return ReadHeaderResult::EndOfHeaders;
        }
        let header = Header::decode_string(&header_string).expect("Invalid header encountered.");
        ReadHeaderResult::Header(header)
      },
      None => ReadHeaderResult::Incomplete
    }
  }

  // TODO: Need to read both by Content-Length and by null byte
  // This is easier if we've already created the header set
  fn read_body(&mut self) -> ReadBodyResult {
    let maybe_body : Option<Vec<u8>> = match self.parse_state.headers.get_content_length() {
      Some(ContentLength(num_bytes)) => self.read_body_by_content_length(num_bytes as usize),
      None => self.read_body_by_null_octet()
    };
    match maybe_body {
      Some(body) => ReadBodyResult::Body(body),
      None => ReadBodyResult::Incomplete
    }
  }

  fn read_body_by_content_length(&mut self, content_length: usize) -> Option<Vec<u8>> {
    debug!("Reading body by content length.");
    let bytes_needed = content_length + 1; // null octet
    if self.buffer.len() < bytes_needed {
      debug!("Not enough bytes to form body; needed {}, only had {}.", content_length, self.buffer.len());
      return None;
    }
    let mut body = self.read_into_vec(bytes_needed);
    body.pop(); // Discard null octet
    debug!("Body -> '{}'", FrameBuffer::body_as_string(&body));
    Some(body)
  }

  fn read_body_by_null_octet(&mut self) -> Option<Vec<u8>> {
    debug!("Reading body by null octet.");
    match self.find_next(0u8) {
      Some(index) => {
        debug!("Found body ending @ index {}", index);
        let num_bytes = index + 1;
        let mut body = self.read_into_vec(num_bytes as usize);
        body.pop(); // Discard null octet
        debug!("Body -> '{}'", FrameBuffer::body_as_string(&body));
        Some(body)
      },
      None => None
    }
  }

  fn body_as_string(body: &Vec<u8>) -> &str {
    match from_utf8(&body) {
      Ok(ref s) => *s,
      Err(_) => "<Non-utf8 Binary Content>"
    }
  }

  fn find_next(&self, needle: u8) -> Option<u32> {
    let mut step = 0u32;
    for byte in &self.buffer {
      if *byte == needle {
        return Some(step);
      }
      step += 1;
    }
    None
  }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

use ll::stylesheet::css_fixed;
use types::CssQName;
use std::libc::c_void;
use lwcstr_from_rust_str = wapcaplet::from_rust_string;

pub fn css_fixed_to_float(f: css_fixed) -> float {
    static BEFORE: i32 = 10;
    f as float * 1.0f / ((1i32 << BEFORE) as float)
}

pub fn float_to_css_fixed(f: float) -> css_fixed {
    static BEFORE: i32 = 10;
    (f * ((1 << BEFORE) as float)) as css_fixed
}

pub fn rust_str_to_net_qname(s: &str) -> CssQName {
    CssQName {
        ns: None,
        name: lwcstr_from_rust_str(s)
    }
}

pub fn net_qname_to_rust_str<'a>(qname: &'a CssQName) -> &'a str {
    qname.name.to_str_slice()
}

// FIXME: These methods should be unsafe
pub trait VoidPtrLike {
    fn from_void_ptr(*c_void) -> Self;
    fn to_void_ptr(&self) -> *c_void;
}
<commit_msg>Upgrade to rustc 0.8-pre (0ac3e02 2013-08-30 05:45:45 -0700)<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

use ll::stylesheet::css_fixed;
use types::CssQName;
use std::libc::c_void;
use lwcstr_from_rust_str = wapcaplet::from_rust_string;

pub fn css_fixed_to_float(f: css_fixed) -> float {
    static BEFORE: i32 = 10;
    f as float * 1.0f / ((1i32 << BEFORE) as float)
}

pub fn float_to_css_fixed(f: float) -> css_fixed {
    static BEFORE: i32 = 10;
    (f * ((1 << BEFORE) as float)) as css_fixed
}

pub fn rust_str_to_net_qname(s: &str) -> CssQName {
    CssQName {
        ns: None,
        name: lwcstr_from_rust_str(s)
    }
}

pub fn net_qname_to_rust_str<'a>(qname: &'a CssQName) -> &'a str {
    qname.name.to_str_slice()
}

// FIXME: These methods should be unsafe
pub trait VoidPtrLike {
    fn from_void_ptr(ptr: *c_void) -> Self;
    fn to_void_ptr(&self) -> *c_void;
}
<|endoftext|>