<commit_before>extern crate crossbeam;
extern crate clap;
#[macro_use] extern crate version;
#[macro_use] extern crate log;
extern crate walkdir;

extern crate libimagrt;

use std::env;
use std::process::exit;
use std::process::Command;
use std::process::Stdio;
use std::io::ErrorKind;

use walkdir::WalkDir;
use crossbeam::*;
use clap::{Arg, AppSettings, SubCommand};

use libimagrt::runtime::Runtime;

fn help(cmds: Vec<String>) {
    println!(r#"

     _
    (_)_ __ ___   __ _  __ _
    | | '_ \` _ \/ _\`|/ _\`|
    | | | | | | | (_| | (_| |
    |_|_| |_| |_|\__,_|\__, |
                       |___/
    -------------------------

    Usage: imag [--version | --versions | -h | --help] <command> <args...>

    imag - the personal information management suite for the commandline

    imag is a PIM suite for the commandline. It consists of several commands,
    called "modules". Each module implements one PIM aspect and all of these
    modules can be used independently.

    Available commands:
    "#);

    for cmd in cmds.iter() {
        println!("\t{}", cmd);
    }

    println!(r#"

    Call a command with 'imag <command> <args>'
    Each command can be called with "--help" to get the respective helptext.

    Please visit https://github.com/matthiasbeyer/imag to view the source code,
    follow the development of imag or maybe even contribute to imag.

    imag is free software. It is released under the terms of LGPLv2.1

    (c) 2016 Matthias Beyer and contributors"#);
}

fn get_commands() -> Vec<String> {
    let path = env::var("PATH");
    if path.is_err() {
        println!("PATH error: {:?}", path);
        exit(1);
    }
    let pathelements = path.unwrap();
    let pathelements = pathelements.split(":");

    let joinhandles : Vec<ScopedJoinHandle<Vec<String>>> = pathelements
        .map(|elem| {
            crossbeam::scope(|scope| {
                scope.spawn(|| {
                    WalkDir::new(elem)
                        .max_depth(1)
                        .into_iter()
                        .filter(|path| {
                            match path {
                                &Ok(ref p) => p.file_name()
                                    .to_str()
                                    .map_or(false, |filename| filename.starts_with("imag-")),
                                &Err(_)   => false,
                            }
                        })
                        .filter_map(|x| x.ok())
                        .filter_map(|path| {
                           path.file_name()
                               .to_str()
                               .and_then(|s| s.splitn(2, "-").nth(1).map(String::from))
                        })
                        .collect()
                })
            })
        })
        .collect();

    let mut execs = vec![];
    for joinhandle in joinhandles.into_iter() {
        let mut v = joinhandle.join();
        execs.append(&mut v);
    }

    execs
}

fn main() {
    let appname  = "imag";
    let version  = &version!();
    let about    = "imag - the PIM suite for the commandline";
    let commands = get_commands();
    let r        = Runtime::get_default_cli_builder(appname, version, about);
    let matches  = commands
        .iter()
        .fold(r, |app, cmd| app.subcommand(SubCommand::with_name(cmd)))
        .arg(Arg::with_name("version")
             .long("version")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the version of imag"))
        .arg(Arg::with_name("versions")
             .long("versions")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the versions of the imag commands"))
        .arg(Arg::with_name("help")
             .long("help")
             .short("h")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Show help"))
        .subcommand(SubCommand::with_name("help").help("Show help"))
        .settings(&[AppSettings::AllowExternalSubcommands])
        .get_matches();

    if matches.is_present("help") {
        help(get_commands());
        exit(0);
    }

    if matches.is_present("version") {
        println!("imag {}", &version!()[..]);
        exit(0);
    }

    if matches.is_present("versions") {
        let mut result = vec![];
        for command in commands.iter() {
            result.push(crossbeam::scope(|scope| {
                scope.spawn(|| {
                    let v = Command::new(command).arg("--version").output();
                    match v {
                        Ok(v) => match String::from_utf8(v.stdout) {
                            Ok(s) => format!("{} -> {}", command, s),
                            Err(e) => format!("Failed calling {} -> {:?}", command, e),
                        },
                        Err(e) => format!("Failed calling {} -> {:?}", command, e),
                    }
                })
            }))
        }

        for versionstring in result.into_iter().map(|handle| handle.join()) {
            println!("{}", versionstring);
        }
    }

    matches.subcommand_name()
        .map(|subcommand| {

            let mut subcommand_args = vec![];

            for arg in Runtime::arg_names() {
                matches.value_of(arg)
                    .map(|value| {
                        subcommand_args.push(arg);
                        subcommand_args.push(value);
                    });
            }

            match Command::new(format!("imag-{}", subcommand))
                .stdin(Stdio::inherit())
                .stdout(Stdio::inherit())
                .stderr(Stdio::inherit())
                .arg(subcommand)
                .args(&subcommand_args[..])
                .spawn()
                .and_then(|mut handle| handle.wait())
            {
                Ok(exit_status) => {
                    if !exit_status.success() {
                        println!("{} exited with non-zero exit code", subcommand);
                        exit(exit_status.code().unwrap_or(42));
                    }
                },

                Err(e) => {
                    match e.kind() {
                        ErrorKind::NotFound => {
                            println!("No such command: 'imag-{}'", subcommand);
                            exit(2);
                        },
                        ErrorKind::PermissionDenied => {
                            println!("No permission to execute: 'imag-{}'", subcommand);
                            exit(1);
                        },
                        _ => {
                            println!("Error spawning: {:?}", e);
                            exit(1337);
                        }
                    }
                }
            }
        });
}
<commit_msg>Use libimagrt::setup::generate_runtime_setup() helper to build Runtime object<commit_after>extern crate crossbeam;
extern crate clap;
#[macro_use] extern crate version;
#[macro_use] extern crate log;
extern crate walkdir;

extern crate libimagrt;

use std::env;
use std::process::exit;
use std::process::Command;
use std::process::Stdio;
use std::io::ErrorKind;

use walkdir::WalkDir;
use crossbeam::*;
use clap::{Arg, App, AppSettings, SubCommand};

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;

fn help(cmds: Vec<String>) {
    println!(r#"

     _
    (_)_ __ ___   __ _  __ _
    | | '_ \` _ \/ _\`|/ _\`|
    | | | | | | | (_| | (_| |
    |_|_| |_| |_|\__,_|\__, |
                       |___/
    -------------------------

    Usage: imag [--version | --versions | -h | --help] <command> <args...>

    imag - the personal information management suite for the commandline

    imag is a PIM suite for the commandline. It consists of several commands,
    called "modules". Each module implements one PIM aspect and all of these
    modules can be used independently.

    Available commands:
    "#);

    for cmd in cmds.iter() {
        println!("\t{}", cmd);
    }

    println!(r#"

    Call a command with 'imag <command> <args>'
    Each command can be called with "--help" to get the respective helptext.

    Please visit https://github.com/matthiasbeyer/imag to view the source code,
    follow the development of imag or maybe even contribute to imag.

    imag is free software. It is released under the terms of LGPLv2.1

    (c) 2016 Matthias Beyer and contributors"#);
}

fn get_commands() -> Vec<String> {
    let path = env::var("PATH");
    if path.is_err() {
        println!("PATH error: {:?}", path);
        exit(1);
    }
    let pathelements = path.unwrap();
    let pathelements = pathelements.split(":");

    let joinhandles : Vec<ScopedJoinHandle<Vec<String>>> = pathelements
        .map(|elem| {
            crossbeam::scope(|scope| {
                scope.spawn(|| {
                    WalkDir::new(elem)
                        .max_depth(1)
                        .into_iter()
                        .filter(|path| {
                            match path {
                                &Ok(ref p) => p.file_name()
                                    .to_str()
                                    .map_or(false, |filename| filename.starts_with("imag-")),
                                &Err(_)   => false,
                            }
                        })
                        .filter_map(|x| x.ok())
                        .filter_map(|path| {
                           path.file_name()
                               .to_str()
                               .and_then(|s| s.splitn(2, "-").nth(1).map(String::from))
                        })
                        .collect()
                })
            })
        })
        .collect();

    let mut execs = vec![];
    for joinhandle in joinhandles.into_iter() {
        let mut v = joinhandle.join();
        execs.append(&mut v);
    }

    execs
}

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    get_commands()
        .iter()
        .fold(app, |app, cmd| app.subcommand(SubCommand::with_name(cmd)))
        .arg(Arg::with_name("version")
             .long("version")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the version of imag"))
        .arg(Arg::with_name("versions")
             .long("versions")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the versions of the imag commands"))
        .arg(Arg::with_name("help")
             .long("help")
             .short("h")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Show help"))
        .subcommand(SubCommand::with_name("help").help("Show help"))
        .settings(&[AppSettings::AllowExternalSubcommands])
}

fn main() {
    let appname  = "imag";
    let version  = &version!();
    let about    = "imag - the PIM suite for the commandline";
    let rt       = generate_runtime_setup(appname, version, about, build_ui);
    let matches  = rt.cli();

    debug!("matches: {:?}", matches);
    if matches.is_present("help") {
        debug!("Calling help()");
        help(get_commands());
        exit(0);
    }

    if matches.is_present("version") {
        debug!("Showing version");
        println!("imag {}", &version!()[..]);
        exit(0);
    }

    if matches.is_present("versions") {
        debug!("Showing versions");
        let mut result = vec![];
        for command in get_commands().iter() {
            result.push(crossbeam::scope(|scope| {
                scope.spawn(|| {
                    let v = Command::new(command).arg("--version").output();
                    match v {
                        Ok(v) => match String::from_utf8(v.stdout) {
                            Ok(s) => format!("{} -> {}", command, s),
                            Err(e) => format!("Failed calling {} -> {:?}", command, e),
                        },
                        Err(e) => format!("Failed calling {} -> {:?}", command, e),
                    }
                })
            }))
        }

        for versionstring in result.into_iter().map(|handle| handle.join()) {
            println!("{}", versionstring);
        }
    }

    matches.subcommand_name()
        .map(|subcommand| {

            let mut subcommand_args = vec![];

            for arg in Runtime::arg_names() {
                matches.value_of(arg)
                    .map(|value| {
                        subcommand_args.push(arg);
                        subcommand_args.push(value);
                    });
            }

            match Command::new(format!("imag-{}", subcommand))
                .stdin(Stdio::inherit())
                .stdout(Stdio::inherit())
                .stderr(Stdio::inherit())
                .arg(subcommand)
                .args(&subcommand_args[..])
                .spawn()
                .and_then(|mut handle| handle.wait())
            {
                Ok(exit_status) => {
                    if !exit_status.success() {
                        println!("{} exited with non-zero exit code", subcommand);
                        exit(exit_status.code().unwrap_or(42));
                    }
                },

                Err(e) => {
                    match e.kind() {
                        ErrorKind::NotFound => {
                            println!("No such command: 'imag-{}'", subcommand);
                            exit(2);
                        },
                        ErrorKind::PermissionDenied => {
                            println!("No permission to execute: 'imag-{}'", subcommand);
                            exit(1);
                        },
                        _ => {
                            println!("Error spawning: {:?}", e);
                            exit(1337);
                        }
                    }
                }
            }
        });
}
<|endoftext|>


<commit_before>use lopdf::xobject;
use lopdf::Document;
use std::fmt::Write;
use std::str::FromStr;

fn convert_number_to_bits<T: std::fmt::Binary>(num: T, size: usize) -> Vec<u8> {
    let bin = format!("{:b}", num);
    let pad = "0".repeat(size - bin.len());
    let mut bytes = (pad + &bin).into_bytes();
    bytes.reverse();
    bytes
}

fn generate_barcode(page: u32, code: u16) -> Vec<(f64, f64, f64, f64, u8)> {
    assert!(page > 0 && page <= 255, "Page number should within range: 1-255");
    assert!(code <= 511, "Bar code should within range: 0-511");
    let page_bits = convert_number_to_bits(page, 8);
    let code_bits = convert_number_to_bits(code, 9);
    let mut rects = vec![];
    let mut x = 0.0;
    let y = 0.0;
    let w = 9.0;
    let h = 10.0;
    {
        let mut add_flag = |w, bit| {
            rects.push((x, y, w, h, bit));
            x += w;
        };
        add_flag(w, b'0');
        for bit in page_bits {
            add_flag(w, bit);
        }
        add_flag(w, code_bits[0]);
        add_flag(6.53, b'0');
        add_flag(w, code_bits[1]);
        add_flag(w, code_bits[2]);
        add_flag(w, code_bits[3]);
        add_flag(w, code_bits[4]);
        add_flag(w, b'1');
        add_flag(w, b'0');
        add_flag(w, code_bits[5]);
        add_flag(w, code_bits[6]);
        add_flag(w, code_bits[7]);
        add_flag(w, code_bits[8]);
    }
    rects
}

fn generate_operations(rects: Vec<(f64, f64, f64, f64, u8)>) -> String {
    let mut operations = String::new();
    let mut current_color = b'\0';
    for (x, y, w, h, bit) in rects {
        if bit != current_color {
            operations.push_str(match bit {
                b'0' => "1 1 1 rg\n",
                b'1' => "0 0 0 rg\n",
                _ => "\n",
            });
            current_color = bit;
        }
        write!(&mut operations, "{} {} {} {} re\nf\n", x, y, w, h).unwrap();
    }
    operations
}

#[allow(non_upper_case_globals)]
const mm2pt: f64 = 2.834;

fn main() {
    let args: Vec<String> = std::env::args().collect();
    assert!(args.len() == 4, "Not enough arguments: pdf_file bar_code output_file");
    let pdf_file = &args[1];
    let code = u16::from_str(&args[2]).expect("error in parsing code argument");
    let output_file = &args[3];
    let mut doc = Document::load(pdf_file).unwrap();
    for (page_number, page_id) in doc.get_pages() {
        let operations = generate_operations(generate_barcode(page_number, code));
        let barcode = xobject::form(
            vec![0.0, 0.0, 595.0 - 12.44 * mm2pt * 2.0, 10.0 * mm2pt],
            vec![mm2pt, 0.0, 0.0, mm2pt, 12.44 * mm2pt, 842.0 - 14.53 * mm2pt],
            operations.as_bytes().to_vec(),
        );
        doc.insert_form_object(page_id, barcode).unwrap();
    }
    // Store file in current working directory.
    doc.save(output_file).unwrap();
}
<commit_msg>Fix add_barcode example<commit_after>use lopdf::xobject;
use lopdf::Document;
use std::fmt::Write;
use std::str::FromStr;

fn convert_number_to_bits<T: std::fmt::Binary>(num: T, size: usize) -> Vec<u8> {
    let bin = format!("{:b}", num);
    let pad = "0".repeat(size - bin.len());
    let mut bytes = (pad + &bin).into_bytes();
    bytes.reverse();
    bytes
}

fn generate_barcode(page: u32, code: u16) -> Vec<(f64, f64, f64, f64, u8)> {
    assert!(page > 0 && page <= 255, "Page number should within range: 1-255");
    assert!(code <= 511, "Bar code should within range: 0-511");
    let page_bits = convert_number_to_bits(page, 8);
    let code_bits = convert_number_to_bits(code, 9);
    let mut rects = vec![];
    let mut x = 0.0;
    let y = 0.0;
    let w = 9.0;
    let h = 10.0;
    {
        let mut add_flag = |w, bit| {
            rects.push((x, y, w, h, bit));
            x += w;
        };
        add_flag(w, b'0');
        for bit in page_bits {
            add_flag(w, bit);
        }
        add_flag(w, code_bits[0]);
        add_flag(6.53, b'0');
        add_flag(w, code_bits[1]);
        add_flag(w, code_bits[2]);
        add_flag(w, code_bits[3]);
        add_flag(w, code_bits[4]);
        add_flag(w, b'1');
        add_flag(w, b'0');
        add_flag(w, code_bits[5]);
        add_flag(w, code_bits[6]);
        add_flag(w, code_bits[7]);
        add_flag(w, code_bits[8]);
    }
    rects
}

fn generate_operations(rects: Vec<(f64, f64, f64, f64, u8)>) -> String {
    let mut operations = String::new();
    let mut current_color = b'\0';
    for (x, y, w, h, bit) in rects {
        if bit != current_color {
            operations.push_str(match bit {
                b'0' => "1 1 1 rg\n",
                b'1' => "0 0 0 rg\n",
                _ => "\n",
            });
            current_color = bit;
        }
        write!(&mut operations, "{} {} {} {} re\nf\n", x, y, w, h).unwrap();
    }
    operations
}

#[allow(non_upper_case_globals)]
const mm2pt: f32 = 2.834;

fn main() {
    let args: Vec<String> = std::env::args().collect();
    assert!(args.len() == 4, "Not enough arguments: pdf_file bar_code output_file");
    let pdf_file = &args[1];
    let code = u16::from_str(&args[2]).expect("error in parsing code argument");
    let output_file = &args[3];
    let mut doc = Document::load(pdf_file).unwrap();
    for (page_number, page_id) in doc.get_pages() {
        let operations = generate_operations(generate_barcode(page_number, code));
        let barcode = xobject::form(
            vec![0.0, 0.0, 595.0 - 12.44 * mm2pt * 2.0, 10.0 * mm2pt],
            vec![mm2pt, 0.0, 0.0, mm2pt, 12.44 * mm2pt, 842.0 - 14.53 * mm2pt],
            operations.as_bytes().to_vec(),
        );
        doc.insert_form_object(page_id, barcode).unwrap();
    }
    // Store file in current working directory.
    doc.save(output_file).unwrap();
}
<|endoftext|>


<commit_before>// Chapter 1
// ------------------ print macros start ------------------
// Macros: Macros look like functions, except that their name ends with a bang !,
// but instead of generating a function call, macros are expanded into source code
// that gets compiled with the rest of the program. eg. println!
// println! -> prints statement to console in a new line

// !!!--- start uncommenting from line below ---!!!
// fn main() {
//     println!("April has {} days.", 31);
//     println!("{month} has {numberOfDays} days.",
//         month = "January",
//         numberOfDays = "31");
//     // Special formating is used here
//     // {:b} -> converts 2 to 10 (binary form)
//     println!("{} of {:b} people know binary, the other half doesn't", 1, 2);
//     let width = 6;
//     println!("{number:>width$} {spaces} spaces and {number}", number = 1, width = width, spaces = width - 1);
//     println!("{}", format!("{:05}", 12));

//     // rounds off the number
//     let pi = 3.141592;
//     println!("Pi is roughly {:.3}", pi);
// }
// !!!--- end uncommenting from line above ---!!!
// ------------------ print macros end ------------------

// Chapter 2
// ------------------ Debugging start ------------------
// In JS we use console.log() for logging and debugging purposes.
// console.log() can be used to print pretty any type of object.
// However, in Rust this is not possible as all types which want to use
// std::fmt formatting traits require an implementation to be printable.
// The fmt::Debug trait makes this very straightforward.
// All types can derive (automatically create) the fmt::Debug implementation.
// This is not true for fmt::Display which must be manually implemented.
// Below given example shows automatic derive(Debug) implementation
// and manual Display implementation.

// !!!--- start uncommenting from line below ---!!!
// Import (via `use`) the `fmt` module to make it available.
// use std::fmt::{self, Formatter, Display};
// #[derive(Debug)]
// struct Person<'a> {
//     name: &'a str,
//     age: u8
// }

// // Implement `Display` for `Person`.
// impl<'a> fmt::Display for Person<'a> {
//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//         // Try `write!` to see if it errors. If it errors, return
//         // the error. Otherwise continue.
//         write!(f, "(Name is {} and Age is {})", self.name, self.age)?;
//         write!(f, "")
//     }
// }

// #[derive(Debug)]
// struct Color {
//     red: u8,
//     green: u8,
//     blue: u8,
// }

// impl Display for Color {
//     // `f` is a buffer, this method must write the formatted string into it
//     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
//         // `write!` is like `format!`, but it will write the formatted string
//         // into a buffer (the first argument)
//         write!(f, "RGB ({}, {}, {}) 0x{:02.X}{:02.X}{:02.X}",
//             self.red, self.green, self.blue, self.red, self.green, self.blue)
//     }
// }

// fn main() {
//     let name = "Peter";
//     let age = 27;
//     let peter = Person { name, age };

//     println!("Compare Person");
//     println!("Debug: Normal {:?}", peter);
//     println!("Debug: Pretty {:#?}", peter);
//     println!("Display: {}", peter);

//     for color in [
//         Color { red: 128, green: 255, blue: 90 },
//         Color { red: 0, green: 3, blue: 254 },
//         Color { red: 0, green: 0, blue: 0 },
//     ].iter() {
//         // Switch this to use {} once you've added an implementation
//         // for fmt::Display
//         println!("{:}", *color);
//     }
// }
// !!!--- end uncommenting from line above ---!!!
// ------------------ Debugging end ------------------

// Chapter 3
// ------------------ Primitives start ------------------
// Rust provides access to a wide variety of primitives.

// !!!--- start uncommenting from line below ---!!!
fn main() {
    // Variables can be type annotated.
    let logical: bool = true;

    let a_float: f64 = 1.0;  // Regular annotation
    let an_integer   = 5i32; // Suffix annotation

    // Or a default will be used.
    let default_float   = 3.0; // `f64`
    let default_integer = 7;   // `i32`

    // A type can also be inferred from context
    let mut inferred_type = 12; // Type i64 is inferred from another line
    inferred_type = 4294967296i64;

    // A mutable variable's value can be changed.
    let mut mutable = 12; // Mutable `i32`
    mutable = 21;

    // Error! The type of a variable can't be changed.
    //mutable = true;

    // Variables can be overwritten with shadowing.
    let mutable = true;
}
// !!!--- end uncommenting from line above ---!!!
// ------------------ Primitives end ------------------<commit_msg>add various simple operations<commit_after>// Chapter 1
// ------------------ print macros start ------------------
// Macros: Macros look like functions, except that their name ends with a bang !,
// but instead of generating a function call, macros are expanded into source code
// that gets compiled with the rest of the program. eg. println!
// println! -> prints statement to console in a new line

// !!!--- start uncommenting from line below ---!!!
// fn main() {
//     println!("April has {} days.", 31);
//     println!("{month} has {numberOfDays} days.",
//         month = "January",
//         numberOfDays = "31");
//     // Special formating is used here
//     // {:b} -> converts 2 to 10 (binary form)
//     println!("{} of {:b} people know binary, the other half doesn't", 1, 2);
//     let width = 6;
//     println!("{number:>width$} {spaces} spaces and {number}", number = 1, width = width, spaces = width - 1);
//     println!("{}", format!("{:05}", 12));

//     // rounds off the number
//     let pi = 3.141592;
//     println!("Pi is roughly {:.3}", pi);
// }
// !!!--- end uncommenting from line above ---!!!
// ------------------ print macros end ------------------

// Chapter 2
// ------------------ Debugging start ------------------
// In JS we use console.log() for logging and debugging purposes.
// console.log() can be used to print pretty any type of object.
// However, in Rust this is not possible as all types which want to use
// std::fmt formatting traits require an implementation to be printable.
// The fmt::Debug trait makes this very straightforward.
// All types can derive (automatically create) the fmt::Debug implementation.
// This is not true for fmt::Display which must be manually implemented.
// Below given example shows automatic derive(Debug) implementation
// and manual Display implementation.

// !!!--- start uncommenting from line below ---!!!
// Import (via `use`) the `fmt` module to make it available.
// use std::fmt::{self, Formatter, Display};
// #[derive(Debug)]
// struct Person<'a> {
//     name: &'a str,
//     age: u8
// }

// // Implement `Display` for `Person`.
// impl<'a> fmt::Display for Person<'a> {
//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//         // Try `write!` to see if it errors. If it errors, return
//         // the error. Otherwise continue.
//         write!(f, "(Name is {} and Age is {})", self.name, self.age)?;
//         write!(f, "")
//     }
// }

// #[derive(Debug)]
// struct Color {
//     red: u8,
//     green: u8,
//     blue: u8,
// }

// impl Display for Color {
//     // `f` is a buffer, this method must write the formatted string into it
//     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
//         // `write!` is like `format!`, but it will write the formatted string
//         // into a buffer (the first argument)
//         write!(f, "RGB ({}, {}, {}) 0x{:02.X}{:02.X}{:02.X}",
//             self.red, self.green, self.blue, self.red, self.green, self.blue)
//     }
// }

// fn main() {
//     let name = "Peter";
//     let age = 27;
//     let peter = Person { name, age };

//     println!("Compare Person");
//     println!("Debug: Normal {:?}", peter);
//     println!("Debug: Pretty {:#?}", peter);
//     println!("Display: {}", peter);

//     for color in [
//         Color { red: 128, green: 255, blue: 90 },
//         Color { red: 0, green: 3, blue: 254 },
//         Color { red: 0, green: 0, blue: 0 },
//     ].iter() {
//         // Switch this to use {} once you've added an implementation
//         // for fmt::Display
//         println!("{:}", *color);
//     }
// }
// !!!--- end uncommenting from line above ---!!!
// ------------------ Debugging end ------------------

// Chapter 3
// ------------------ Primitives start ------------------
// Rust provides access to a wide variety of primitives.

// !!!--- start uncommenting from line below ---!!!
fn main() {
    // Variables can be type annotated.
    let logical: bool = true;

    let a_float: f64 = 1.0;  // Regular annotation
    let an_integer   = 5i32; // Suffix annotation

    // Or a default will be used.
    let default_float   = 3.0; // `f64`
    let default_integer = 7;   // `i32`

    // A type can also be inferred from context
    let mut inferred_type = 12; // Type i64 is inferred from another line
    inferred_type = 4294967296i64;

    // A mutable variable's value can be changed.
    let mut mutable = 12; // Mutable `i32`
    mutable = 21;

    // Error! The type of a variable can't be changed.
    //mutable = true;

    // Variables can be overwritten with shadowing.
    let mutable = true;

    // Integer addition
    // We need to tell the compiler the type of the literals we use.
    println!("1 + 2 = {}", 1u32 + 2);

    // Integer subtraction
    // We need to tell the compiler the type of the literals we use.
    println!("1 - 2 = {}", 1i32 - 2);

    // Short-circuiting boolean logic
    println!("true AND false is {}", true && false);
    println!("true OR false is {}", true || false);
    println!("NOT true is {}", !true);

    // Bitwise operations
    println!("0011 AND 0101 is {:04b}", 0b0011u32 & 0b0101);
    println!("0011 OR 0101 is {:04b}", 0b0011u32 | 0b0101);
    println!("0011 XOR 0101 is {:04b}", 0b0011u32 ^ 0b0101);
    println!("1 << 5 is {}", 1u32 << 5);
    println!("0x80 >> 2 is 0x{:x}", 0x80u32 >> 2);

    // Use underscores to improve readability!
    println!("One million is written as {}", 1_000_000u32);
}
// !!!--- end uncommenting from line above ---!!!
// ------------------ Primitives end ------------------<|endoftext|>


<commit_before>#![feature(test)]
#![allow(dead_code)]
extern crate test;

// Ugly hack to allow benchmarking private modules
#[path = "../src/bit_iterator.rs"] mod bit_iterator;
#[path = "../src/packet.rs"] mod packet;
use test::Bencher;
use packet::Packet;

#[bench]
fn bench_decode(b: &mut Bencher) {
    let buf = [0x21, 0x00, 0x41, 0xa8, 0x99, 0x2f, 0xd0, 0x2a, 0x9f, 0x4a,
               0x26, 0x21, 0x00, 0x10, 0x00, 0x00, 0x3a, 0xf2, 0x6c, 0x79,
               0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a];
    b.iter(|| { let _ = Packet::decode(&buf); });
}

#[bench]
fn bench_encode(b: &mut Bencher) {
    let payload = [1, 2, 3, 4, 5, 6];
    let mut packet = Packet::new();
    packet.payload = payload.to_vec();

    b.iter(|| {
        let _ = test::black_box(packet.bytes());
    });
}
<commit_msg>Fix benchmark compilation.<commit_after>#![feature(test)]
#![allow(dead_code)]
extern crate test;
extern crate quickcheck;

// Ugly hack to allow benchmarking private modules
#[path = "../src/bit_iterator.rs"] mod bit_iterator;
#[path = "../src/packet.rs"] mod packet;
use test::Bencher;
use packet::Packet;

#[bench]
fn bench_decode(b: &mut Bencher) {
    let buf = [0x21, 0x00, 0x41, 0xa8, 0x99, 0x2f, 0xd0, 0x2a, 0x9f, 0x4a,
               0x26, 0x21, 0x00, 0x10, 0x00, 0x00, 0x3a, 0xf2, 0x6c, 0x79,
               0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a];
    b.iter(|| { let _ = Packet::decode(&buf); });
}

#[bench]
fn bench_encode(b: &mut Bencher) {
    let payload = [1, 2, 3, 4, 5, 6];
    let mut packet = Packet::new();
    packet.payload = payload.to_vec();

    b.iter(|| {
        let _ = test::black_box(packet.bytes());
    });
}
<|endoftext|>


<commit_before>#![unstable(feature = "futures_api",
            reason = "futures in libcore are unstable",
            issue = "50547")]

use fmt;
use marker::Unpin;

/// A `RawWaker` allows the implementor of a task executor to create a `Waker`
/// which provides customized wakeup behavior.
///
/// It consists of a data pointer and a virtual function pointer table (vtable) that
/// customizes the behavior of the `RawWaker`.
#[derive(PartialEq)]
pub struct RawWaker {
    /// A data pointer, which can be used to store arbitrary data as required
    /// by the executor. This could be e.g. a type-erased pointer to an `Arc`
    /// that is associated with the task.
    /// The value of this field gets passed to all functions that are part of
    /// the vtable as first parameter.
    pub data: *const (),
    /// Virtual function pointer table that customizes the behavior of this waker.
    pub vtable: &'static RawWakerVTable,
}

impl fmt::Debug for RawWaker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("RawWaker")
            .finish()
    }
}

/// A virtual function pointer table (vtable) that specifies the behavior
/// of a `RawWaker`.
///
/// The pointer passed to all functions inside the vtable is the `data` pointer
/// from the enclosing `RawWaker` object.
#[derive(PartialEq, Copy, Clone)]
pub struct RawWakerVTable {
    /// This function will be called when the `RawWaker` gets cloned, e.g. when
    /// the `Waker` in which the `RawWaker` is stored gets cloned.
    ///
    /// The implementation of this function must retain all resources that are
    /// required for this additional instance of a `RawWaker` and associated
    /// task. Calling `wake` on the resulting `RawWaker` should result in a wakeup
    /// of the same task that would have been awoken by the original `RawWaker`.
    pub clone: unsafe fn(*const ()) -> RawWaker,

    /// This function will be called when `wake` is called on the `Waker`.
    /// It must wake up the task associated with this `RawWaker`.
    pub wake: unsafe fn(*const ()),

    /// This function gets called when a `RawWaker` gets dropped.
    ///
    /// The implementation of this function must make sure to release any
    /// resources that are associated with this instance of a `RawWaker` and
    /// associated task.
    pub drop_fn: unsafe fn(*const ()),
}

impl fmt::Debug for RawWakerVTable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("RawWakerVTable")
            .finish()
    }
}

/// A `Waker` is a handle for waking up a task by notifying its executor that it
/// is ready to be run.
///
/// This handle encapsulates a `RawWaker` instance, which defines the
/// executor-specific wakeup behavior.
///
/// Implements `Clone`, `Send`, and `Sync`.
#[repr(transparent)]
pub struct Waker {
    waker: RawWaker,
}

impl Unpin for Waker {}
unsafe impl Send for Waker {}
unsafe impl Sync for Waker {}

impl Waker {
    /// Wake up the task associated with this `Waker`.
    pub fn wake(&self) {
        // The actual wakeup call is delegated through a virtual function call
        // to the implementation which is defined by the executor.
        unsafe { (self.waker.vtable.wake)(self.waker.data) }
    }

    /// Returns whether or not this `Waker` and other `Waker` have awaken the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `Waker`s would awaken the same task. However, if this function
    /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task.
    ///
    /// This function is primarily used for optimization purposes.
    pub fn will_wake(&self, other: &Waker) -> bool {
        self.waker == other.waker
    }

    /// Creates a new `Waker` from `RawWaker`.
    ///
    /// The method cannot check whether `RawWaker` fulfills the required API
    /// contract to make it usable for `Waker` and is therefore unsafe.
    pub unsafe fn new_unchecked(waker: RawWaker) -> Waker {
        Waker {
            waker: waker,
        }
    }
}

impl Clone for Waker {
    fn clone(&self) -> Self {
        Waker {
            waker: unsafe { (self.waker.vtable.clone)(self.waker.data) },
        }
    }
}

impl Drop for Waker {
    fn drop(&mut self) {
        unsafe { (self.waker.vtable.drop_fn)(self.waker.data) }
    }
}

impl fmt::Debug for Waker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Waker")
            .finish()
    }
}
<commit_msg>Apply suggestions from code review<commit_after>#![unstable(feature = "futures_api",
            reason = "futures in libcore are unstable",
            issue = "50547")]

use fmt;
use marker::Unpin;

/// A `RawWaker` allows the implementor of a task executor to create a `Waker`
/// which provides customized wakeup behavior.
///
/// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table
///
/// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] that
/// customizes the behavior of the `RawWaker`.
#[derive(PartialEq)]
pub struct RawWaker {
    /// A data pointer, which can be used to store arbitrary data as required
    /// by the executor. This could be e.g. a type-erased pointer to an `Arc`
    /// that is associated with the task.
    /// The value of this field gets passed to all functions that are part of
    /// the vtable as the first parameter.
    pub data: *const (),
    /// Virtual function pointer table that customizes the behavior of this waker.
    pub vtable: &'static RawWakerVTable,
}

impl fmt::Debug for RawWaker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("RawWaker")
            .finish()
    }
}

/// A virtual function pointer table (vtable) that specifies the behavior
/// of a [`RawWaker`].
///
/// The pointer passed to all functions inside the vtable is the `data` pointer
/// from the enclosing `RawWaker` object.
#[derive(PartialEq, Copy, Clone)]
pub struct RawWakerVTable {
    /// This function will be called when the `RawWaker` gets cloned, e.g. when
    /// the `Waker` in which the `RawWaker` is stored gets cloned.
    ///
    /// The implementation of this function must retain all resources that are
    /// required for this additional instance of a `RawWaker` and associated
    /// task. Calling `wake` on the resulting `RawWaker` should result in a wakeup
    /// of the same task that would have been awoken by the original `RawWaker`.
    pub clone: unsafe fn(*const ()) -> RawWaker,

    /// This function will be called when `wake` is called on the `Waker`.
    /// It must wake up the task associated with this `RawWaker`.
    pub wake: unsafe fn(*const ()),

    /// This function gets called when a `RawWaker` gets dropped.
    ///
    /// The implementation of this function must make sure to release any
    /// resources that are associated with this instance of a `RawWaker` and
    /// associated task.
    pub drop_fn: unsafe fn(*const ()),
}

impl fmt::Debug for RawWakerVTable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("RawWakerVTable")
            .finish()
    }
}

/// A `Waker` is a handle for waking up a task by notifying its executor that it
/// is ready to be run.
///
/// This handle encapsulates a `RawWaker` instance, which defines the
/// executor-specific wakeup behavior.
///
/// Implements `Clone`, `Send`, and `Sync`.
#[repr(transparent)]
pub struct Waker {
    waker: RawWaker,
}

impl Unpin for Waker {}
unsafe impl Send for Waker {}
unsafe impl Sync for Waker {}

impl Waker {
    /// Wake up the task associated with this `Waker`.
    pub fn wake(&self) {
        // The actual wakeup call is delegated through a virtual function call
        // to the implementation which is defined by the executor.
        unsafe { (self.waker.vtable.wake)(self.waker.data) }
    }

    /// Returns whether or not this `Waker` and other `Waker` have awaken the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `Waker`s would awaken the same task. However, if this function
    /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task.
    ///
    /// This function is primarily used for optimization purposes.
    pub fn will_wake(&self, other: &Waker) -> bool {
        self.waker == other.waker
    }

    /// Creates a new `Waker` from `RawWaker`.
    ///
    /// The method cannot check whether `RawWaker` fulfills the required API
    /// contract to make it usable for `Waker` and is therefore unsafe.
    pub unsafe fn new_unchecked(waker: RawWaker) -> Waker {
        Waker {
            waker,
        }
    }
}

impl Clone for Waker {
    fn clone(&self) -> Self {
        Waker {
            waker: unsafe { (self.waker.vtable.clone)(self.waker.data) },
        }
    }
}

impl Drop for Waker {
    fn drop(&mut self) {
        unsafe { (self.waker.vtable.drop_fn)(self.waker.data) }
    }
}

impl fmt::Debug for Waker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Waker")
            .finish()
    }
}
<|endoftext|>


<commit_before>use crate::spec::{LinkerFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
    let mut base = super::linux_base::opts();
    base.cpu = "x86-64".to_string();
    base.max_atomic_width = Some(64);
    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string());
    base.stack_probes = true;
    base.has_elf_tls = false;
    // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
    // breaks code gen. See LLVM bug 36743
    base.needs_plt = true;

    Ok(Target {
        llvm_target: "x86_64-unknown-linux-gnux32".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128".to_string(),
        arch: "x86_64".to_string(),
        target_os: "linux".to_string(),
        target_env: "gnu".to_string(),
        target_vendor: "unknown".to_string(),
        linker_flavor: LinkerFlavor::Gcc,
        options: base,
    })
}
<commit_msg>Rollup merge of #59686 - crlf0710:disable_gnux32_stackprobe, r=luqmana<commit_after>use crate::spec::{LinkerFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
    let mut base = super::linux_base::opts();
    base.cpu = "x86-64".to_string();
    base.max_atomic_width = Some(64);
    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string());
    // BUG: temporarily workaround #59674
    base.stack_probes = false;
    base.has_elf_tls = false;
    // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
    // breaks code gen. See LLVM bug 36743
    base.needs_plt = true;

    Ok(Target {
        llvm_target: "x86_64-unknown-linux-gnux32".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128".to_string(),
        arch: "x86_64".to_string(),
        target_os: "linux".to_string(),
        target_env: "gnu".to_string(),
        target_vendor: "unknown".to_string(),
        linker_flavor: LinkerFlavor::Gcc,
        options: base,
    })
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 prelude::*;
use super::support::PathLike;
use super::{Reader, Writer, Seek};
use super::{SeekSet, SeekStyle};
use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
use rt::io::{io_error, read_error, EndOfFile};
use rt::local::Local;
use rt::test::*;
use libc::{O_RDWR, O_RDONLY, O_WRONLY, S_IWUSR, S_IRUSR,
           O_CREAT, O_TRUNC, O_APPEND};

/// Instructions on how to open a file and return a `FileStream`.
enum FileMode {
    /// Opens an existing file. IoError if file does not exist.
    Open,
    /// Creates a file. IoError if file exists.
    Create,
    /// Opens an existing file or creates a new one.
    OpenOrCreate,
    /// Opens an existing file or creates a new one, positioned at EOF.
    Append,
    /// Opens an existing file, truncating it to 0 bytes.
    Truncate,
    /// Opens an existing file or creates a new one, truncating it to 0 bytes.
    CreateOrTruncate,
}

/// How should the file be opened? `FileStream`s opened with `Read` will
/// raise an `io_error` condition if written to.
enum FileAccess {
    Read,
    Write,
    ReadWrite
}

/// Abstraction representing *positional* access to a file. In this case,
/// *positional* refers to it keeping an encounter *cursor* of where in the
/// file a subsequent `read` or `write` will begin from. Users of a `FileStream`
/// can `seek` to move the cursor to a given location *within the bounds of the
/// file* and can ask to have the `FileStream` `tell` them the location, in
/// bytes, of the cursor.
///
/// This abstraction is roughly modeled on the access workflow as represented
/// by `open(2)`, `read(2)`, `write(2)` and friends.
///
/// The `open` and `unlink` static methods are provided to manage creation/removal
/// of files. All other methods operatin on an instance of `FileStream`.
pub struct FileStream {
    fd: ~RtioFileStream,
    last_nread: int,
}

impl FileStream {
    pub fn open<P: PathLike>(path: &P,
                             mode: FileMode,
                             access: FileAccess
                            ) -> Option<FileStream> {
        let open_result = unsafe {
            let io = Local::unsafe_borrow::<IoFactoryObject>();
            let mut flags = match mode {
                Open => 0,
                Create => O_CREAT,
                OpenOrCreate => O_CREAT,
                Append => O_APPEND,
                Truncate => O_TRUNC,
                CreateOrTruncate => O_TRUNC | O_CREAT
            };
            flags = match access {
                Read => flags | O_RDONLY,
                Write => flags | O_WRONLY,
                ReadWrite => flags | O_RDWR
            };
            let create_mode = match mode {
                Create|OpenOrCreate|CreateOrTruncate =>
                    S_IRUSR | S_IWUSR,
                _ => 0
            };
            (*io).fs_open(path, flags as int, create_mode as int)
        };
        match open_result {
            Ok(fd) => Some(FileStream {
                fd: fd,
                last_nread: -1
            }),
            Err(ioerr) => {
                io_error::cond.raise(ioerr);
                None
            }
        }
    }
    fn unlink<P: PathLike>(path: &P) {
        let unlink_result = unsafe {
            let io = Local::unsafe_borrow::<IoFactoryObject>();
            (*io).fs_unlink(path)
        };
        match unlink_result {
            Ok(_) => (),
            Err(ioerr) => {
                io_error::cond.raise(ioerr);
            }
        }
    }
}

impl Reader for FileStream {
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        match self.fd.read(buf) {
            Ok(read) => {
                self.last_nread = read;
                match read {
                    0 => None,
                    _ => Some(read as uint)
                }
            },
            Err(ioerr) => {
                // EOF is indicated by returning None
                if ioerr.kind != EndOfFile {
                    read_error::cond.raise(ioerr);
                }
                return None;
            }
        }
    }

    fn eof(&mut self) -> bool {
        self.last_nread == 0
    }
}

impl Writer for FileStream {
    fn write(&mut self, buf: &[u8]) {
        match self.fd.write(buf) {
            Ok(_) => (),
            Err(ioerr) => {
                io_error::cond.raise(ioerr);
            }
        }
    }

    fn flush(&mut self) {
        match self.fd.flush() {
            Ok(_) => (),
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
            }
        }
    }
}

impl Seek for FileStream {
    fn tell(&self) -> u64 {
        let res = self.fd.tell();
        match res {
            Ok(cursor) => cursor,
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
                return -1;
            }
        }
    }

    fn seek(&mut self, pos: i64, style: SeekStyle) {
        use libc::{SEEK_SET, SEEK_CUR, SEEK_END};
        let whence = match style {
            SeekSet => SEEK_SET,
            SeekCur => SEEK_CUR,
            SeekEnd => SEEK_END
        } as i64;
        match self.fd.seek(pos, whence) {
            Ok(_) => {
                // successful seek resets EOF indocator
                self.last_nread = -1;
                ()
            },
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
            }
        }
    }
}

fn file_test_smoke_test_impl() {
    do run_in_newsched_task {
        let message = "it's alright. have a good time";
        let filename = &Path("./rt_io_file_test.txt");
        {
            let mut write_stream = FileStream::open(filename, Create, ReadWrite).unwrap();
            write_stream.write(message.as_bytes());
        }
        {
            use str;
            let mut read_stream = FileStream::open(filename, Open, Read).unwrap();
            let mut read_buf = [0, .. 1028];
            let read_str = match read_stream.read(read_buf).unwrap() {
                -1|0 => fail!("shouldn't happen"),
                n => str::from_bytes(read_buf.slice_to(n))
            };
            assert!(read_str == message.to_owned());
        }
        FileStream::unlink(filename);
    }
}

#[test]
fn file_test_io_smoke_test() {
    file_test_smoke_test_impl();
}

fn file_test_invalid_path_opened_without_create_should_raise_condition_impl() {
    do run_in_newsched_task {
        let filename = &Path("./file_that_does_not_exist.txt");
        let mut called = false;
        do io_error::cond.trap(|_| {
            called = true;
        }).inside {
            let result = FileStream::open(filename, Open, Read);
            assert!(result.is_none());
        }
        assert!(called);
    }
}
#[test]
fn file_test_io_invalid_path_opened_without_create_should_raise_condition() {
    file_test_invalid_path_opened_without_create_should_raise_condition_impl();
}

fn file_test_unlinking_invalid_path_should_raise_condition_impl() {
    do run_in_newsched_task {
        let filename = &Path("./another_file_that_does_not_exist.txt");
        let mut called = false;
        do io_error::cond.trap(|_| {
            called = true;
        }).inside {
            FileStream::unlink(filename);
        }
        assert!(called);
    }
}
#[test]
fn file_test_iounlinking_invalid_path_should_raise_condition() {
    file_test_unlinking_invalid_path_should_raise_condition_impl();
}

fn file_test_io_non_positional_read_impl() {
    do run_in_newsched_task {
        use str;
        let message = "ten-four";
        let mut read_mem = [0, .. 8];
        let filename = &Path("./rt_io_file_test_positional.txt");
        {
            let mut rw_stream = FileStream::open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(message.as_bytes());
        }
        {
            let mut read_stream = FileStream::open(filename, Open, Read).unwrap();
            {
                let read_buf = read_mem.mut_slice(0, 4);
                read_stream.read(read_buf);
            }
            {
                let read_buf = read_mem.mut_slice(4, 8);
                read_stream.read(read_buf);
            }
        }
        FileStream::unlink(filename);
        let read_str = str::from_bytes(read_mem);
        assert!(read_str == message.to_owned());
    }
}

#[test]
fn file_test_io_non_positional_read() {
    file_test_io_non_positional_read_impl();
}

fn file_test_io_seeking_impl() {
    do run_in_newsched_task {
        use str;
        let message = "ten-four";
        let mut read_mem = [0, .. 4];
        let set_cursor = 4 as u64;
        let mut tell_pos_pre_read;
        let mut tell_pos_post_read;
        let filename = &Path("./rt_io_file_test_seeking.txt");
        {
            let mut rw_stream = FileStream::open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(message.as_bytes());
        }
        {
            let mut read_stream = FileStream::open(filename, Open, Read).unwrap();
            read_stream.seek(set_cursor as i64, SeekSet);
            tell_pos_pre_read = read_stream.tell();
            read_stream.read(read_mem);
            tell_pos_post_read = read_stream.tell();
        }
        FileStream::unlink(filename);
        let read_str = str::from_bytes(read_mem);
        assert!(read_str == message.slice(4, 8).to_owned());
        assert!(tell_pos_pre_read == set_cursor);
        assert!(tell_pos_post_read == message.len() as u64);
    }
}
#[test]
fn file_test_io_seek_and_tell_smoke_test() {
    file_test_io_seeking_impl();
}
<commit_msg>std: more seek tests<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 prelude::*;
use super::support::PathLike;
use super::{Reader, Writer, Seek};
use super::{SeekSet, SeekCur, SeekEnd, SeekStyle};
use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
use rt::io::{io_error, read_error, EndOfFile};
use rt::local::Local;
use rt::test::*;
use libc::{O_RDWR, O_RDONLY, O_WRONLY, S_IWUSR, S_IRUSR,
           O_CREAT, O_TRUNC, O_APPEND};

/// Instructions on how to open a file and return a `FileStream`.
enum FileMode {
    /// Opens an existing file. IoError if file does not exist.
    Open,
    /// Creates a file. IoError if file exists.
    Create,
    /// Opens an existing file or creates a new one.
    OpenOrCreate,
    /// Opens an existing file or creates a new one, positioned at EOF.
    Append,
    /// Opens an existing file, truncating it to 0 bytes.
    Truncate,
    /// Opens an existing file or creates a new one, truncating it to 0 bytes.
    CreateOrTruncate,
}

/// How should the file be opened? `FileStream`s opened with `Read` will
/// raise an `io_error` condition if written to.
enum FileAccess {
    Read,
    Write,
    ReadWrite
}

/// Abstraction representing *positional* access to a file. In this case,
/// *positional* refers to it keeping an encounter *cursor* of where in the
/// file a subsequent `read` or `write` will begin from. Users of a `FileStream`
/// can `seek` to move the cursor to a given location *within the bounds of the
/// file* and can ask to have the `FileStream` `tell` them the location, in
/// bytes, of the cursor.
///
/// This abstraction is roughly modeled on the access workflow as represented
/// by `open(2)`, `read(2)`, `write(2)` and friends.
///
/// The `open` and `unlink` static methods are provided to manage creation/removal
/// of files. All other methods operatin on an instance of `FileStream`.
pub struct FileStream {
    fd: ~RtioFileStream,
    last_nread: int,
}

impl FileStream {
    pub fn open<P: PathLike>(path: &P,
                             mode: FileMode,
                             access: FileAccess
                            ) -> Option<FileStream> {
        let open_result = unsafe {
            let io = Local::unsafe_borrow::<IoFactoryObject>();
            let mut flags = match mode {
                Open => 0,
                Create => O_CREAT,
                OpenOrCreate => O_CREAT,
                Append => O_APPEND,
                Truncate => O_TRUNC,
                CreateOrTruncate => O_TRUNC | O_CREAT
            };
            flags = match access {
                Read => flags | O_RDONLY,
                Write => flags | O_WRONLY,
                ReadWrite => flags | O_RDWR
            };
            let create_mode = match mode {
                Create|OpenOrCreate|CreateOrTruncate =>
                    S_IRUSR | S_IWUSR,
                _ => 0
            };
            (*io).fs_open(path, flags as int, create_mode as int)
        };
        match open_result {
            Ok(fd) => Some(FileStream {
                fd: fd,
                last_nread: -1
            }),
            Err(ioerr) => {
                io_error::cond.raise(ioerr);
                None
            }
        }
    }
    fn unlink<P: PathLike>(path: &P) {
        let unlink_result = unsafe {
            let io = Local::unsafe_borrow::<IoFactoryObject>();
            (*io).fs_unlink(path)
        };
        match unlink_result {
            Ok(_) => (),
            Err(ioerr) => {
                io_error::cond.raise(ioerr);
            }
        }
    }
}

impl Reader for FileStream {
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        match self.fd.read(buf) {
            Ok(read) => {
                self.last_nread = read;
                match read {
                    0 => None,
                    _ => Some(read as uint)
                }
            },
            Err(ioerr) => {
                // EOF is indicated by returning None
                if ioerr.kind != EndOfFile {
                    read_error::cond.raise(ioerr);
                }
                return None;
            }
        }
    }

    fn eof(&mut self) -> bool {
        self.last_nread == 0
    }
}

impl Writer for FileStream {
    fn write(&mut self, buf: &[u8]) {
        match self.fd.write(buf) {
            Ok(_) => (),
            Err(ioerr) => {
                io_error::cond.raise(ioerr);
            }
        }
    }

    fn flush(&mut self) {
        match self.fd.flush() {
            Ok(_) => (),
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
            }
        }
    }
}

impl Seek for FileStream {
    fn tell(&self) -> u64 {
        let res = self.fd.tell();
        match res {
            Ok(cursor) => cursor,
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
                return -1;
            }
        }
    }

    fn seek(&mut self, pos: i64, style: SeekStyle) {
        use libc::{SEEK_SET, SEEK_CUR, SEEK_END};
        let whence = match style {
            SeekSet => SEEK_SET,
            SeekCur => SEEK_CUR,
            SeekEnd => SEEK_END
        } as i64;
        match self.fd.seek(pos, whence) {
            Ok(_) => {
                // successful seek resets EOF indocator
                self.last_nread = -1;
                ()
            },
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
            }
        }
    }
}

fn file_test_smoke_test_impl() {
    do run_in_newsched_task {
        let message = "it's alright. have a good time";
        let filename = &Path("./rt_io_file_test.txt");
        {
            let mut write_stream = FileStream::open(filename, Create, ReadWrite).unwrap();
            write_stream.write(message.as_bytes());
        }
        {
            use str;
            let mut read_stream = FileStream::open(filename, Open, Read).unwrap();
            let mut read_buf = [0, .. 1028];
            let read_str = match read_stream.read(read_buf).unwrap() {
                -1|0 => fail!("shouldn't happen"),
                n => str::from_bytes(read_buf.slice_to(n))
            };
            assert!(read_str == message.to_owned());
        }
        FileStream::unlink(filename);
    }
}

#[test]
fn file_test_io_smoke_test() {
    file_test_smoke_test_impl();
}

fn file_test_invalid_path_opened_without_create_should_raise_condition_impl() {
    do run_in_newsched_task {
        let filename = &Path("./file_that_does_not_exist.txt");
        let mut called = false;
        do io_error::cond.trap(|_| {
            called = true;
        }).inside {
            let result = FileStream::open(filename, Open, Read);
            assert!(result.is_none());
        }
        assert!(called);
    }
}
#[test]
fn file_test_io_invalid_path_opened_without_create_should_raise_condition() {
    file_test_invalid_path_opened_without_create_should_raise_condition_impl();
}

fn file_test_unlinking_invalid_path_should_raise_condition_impl() {
    do run_in_newsched_task {
        let filename = &Path("./another_file_that_does_not_exist.txt");
        let mut called = false;
        do io_error::cond.trap(|_| {
            called = true;
        }).inside {
            FileStream::unlink(filename);
        }
        assert!(called);
    }
}
#[test]
fn file_test_iounlinking_invalid_path_should_raise_condition() {
    file_test_unlinking_invalid_path_should_raise_condition_impl();
}

fn file_test_io_non_positional_read_impl() {
    do run_in_newsched_task {
        use str;
        let message = "ten-four";
        let mut read_mem = [0, .. 8];
        let filename = &Path("./rt_io_file_test_positional.txt");
        {
            let mut rw_stream = FileStream::open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(message.as_bytes());
        }
        {
            let mut read_stream = FileStream::open(filename, Open, Read).unwrap();
            {
                let read_buf = read_mem.mut_slice(0, 4);
                read_stream.read(read_buf);
            }
            {
                let read_buf = read_mem.mut_slice(4, 8);
                read_stream.read(read_buf);
            }
        }
        FileStream::unlink(filename);
        let read_str = str::from_bytes(read_mem);
        assert!(read_str == message.to_owned());
    }
}

#[test]
fn file_test_io_non_positional_read() {
    file_test_io_non_positional_read_impl();
}

fn file_test_io_seeking_impl() {
    do run_in_newsched_task {
        use str;
        let message = "ten-four";
        let mut read_mem = [0, .. 4];
        let set_cursor = 4 as u64;
        let mut tell_pos_pre_read;
        let mut tell_pos_post_read;
        let filename = &Path("./rt_io_file_test_seeking.txt");
        {
            let mut rw_stream = FileStream::open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(message.as_bytes());
        }
        {
            let mut read_stream = FileStream::open(filename, Open, Read).unwrap();
            read_stream.seek(set_cursor as i64, SeekSet);
            tell_pos_pre_read = read_stream.tell();
            read_stream.read(read_mem);
            tell_pos_post_read = read_stream.tell();
        }
        FileStream::unlink(filename);
        let read_str = str::from_bytes(read_mem);
        assert!(read_str == message.slice(4, 8).to_owned());
        assert!(tell_pos_pre_read == set_cursor);
        assert!(tell_pos_post_read == message.len() as u64);
    }
}
#[test]
fn file_test_io_seek_and_tell_smoke_test() {
    file_test_io_seeking_impl();
}

fn file_test_io_seek_and_write_impl() {
    use io;
    do run_in_newsched_task {
        use str;
        let initial_msg =   "food-is-yummy";
        let overwrite_msg =    "-the-bar!!";
        let final_msg =     "foo-the-bar!!";
        let seek_idx = 3;
        let mut read_mem = [0, .. 13];
        let filename = &Path("./rt_io_file_test_seek_and_write.txt");
        {
            let mut rw_stream = FileStream::open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(initial_msg.as_bytes());
            rw_stream.seek(seek_idx as i64, SeekSet);
            rw_stream.write(overwrite_msg.as_bytes());
        }
        {
            let mut read_stream = FileStream::open(filename, Open, Read).unwrap();
            read_stream.read(read_mem);
        }
        FileStream::unlink(filename);
        let read_str = str::from_bytes(read_mem);
        io::println(fmt!("read_str: '%?' final_msg: '%?'", read_str, final_msg));
        assert!(read_str == final_msg.to_owned());
    }
}
#[test]
fn file_test_io_seek_and_write() {
    file_test_io_seek_and_write_impl();
}

fn file_test_io_seek_shakedown_impl() {
    do run_in_newsched_task {
        use str;          // 01234567890123
        let initial_msg =   "qwer-asdf-zxcv";
        let chunk_one = "qwer";
        let chunk_two = "asdf";
        let chunk_three = "zxcv";
        let mut read_mem = [0, .. 4];
        let filename = &Path("./rt_io_file_test_seek_shakedown.txt");
        {
            let mut rw_stream = FileStream::open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(initial_msg.as_bytes());
        }
        {
            let mut read_stream = FileStream::open(filename, Open, Read).unwrap();

            read_stream.seek(-4, SeekEnd);
            read_stream.read(read_mem);
            let read_str = str::from_bytes(read_mem);
            assert!(read_str == chunk_three.to_owned());

            read_stream.seek(-9, SeekCur);
            read_stream.read(read_mem);
            let read_str = str::from_bytes(read_mem);
            assert!(read_str == chunk_two.to_owned());

            read_stream.seek(0, SeekSet);
            read_stream.read(read_mem);
            let read_str = str::from_bytes(read_mem);
            assert!(read_str == chunk_one.to_owned());
        }
        FileStream::unlink(filename);
    }
}
#[test]
fn file_test_io_seek_shakedown() {
    file_test_io_seek_shakedown_impl();
}
<|endoftext|>


<commit_before>//! Provides a Quaternion type for properly interpolating rotations

use std::f32;
use std::ops::{Add, Sub, Mul, Div};

use linalg::{self, Vector, Transform, Matrix4};

/// Quaternions describe a rotation in 3d space but can be
/// properly interpolated unlike rotation matrices. The quaternion
/// also provides methods to compute the corresponding rotation
/// transform so that it can be composed with scaling and translation
#[derive(Debug, Copy, Clone)]
pub struct Quaternion {
    pub v: Vector,
    pub w: f32,
}

impl Quaternion {
    /// Construct an identity quaternion
    pub fn identity() -> Quaternion {
        Quaternion { v: Vector::broadcast(0.0), w: 1.0 }
    }
    /// Construct a quaternion from the rotation transform
    /// Based on Shoemake 1991
    pub fn from_transform(t: &Transform) -> Quaternion {
        let m = &t.mat;
        let trace = *m.at(0, 0) + *m.at(1, 1) + *m.at(2, 2);
        if trace > 0.0 {
            // Compute w from matrix trace, then the vector
            let mut s = f32::sqrt(trace + 1.0);
            let w = s / 2.0;
            s = 0.5 / s;
            Quaternion { v: Vector::new(s * (*m.at(2, 1) - *m.at(1, 2)), s * (*m.at(0, 2) - *m.at(2, 0)),
                                        s * (*m.at(1, 0) - *m.at(0, 1))),
                         w: w
            }
        } else {
            // Compute largest of x, y or z then the remaining components
            let next = [1, 2, 0];
            let mut q = Vector::broadcast(0.0);
            let mut i = 0;
            if *m.at(1, 1) > *m.at(0, 0) {
                i = 1;
            }
            if *m.at(2, 2) > *m.at(i, i) {
                i = 2;
            }
            let j = next[i];
            let k = next[j];
            let mut s = f32::sqrt((*m.at(i, i) - (*m.at(j, j) + *m.at(k, k))) + 1.0);
            q[i] = s * 0.5;
            if s != 0.0 {
                s = 0.5 / s;
            }
            let w = (*m.at(k, j) - *m.at(j, k)) * s;
            q[j] = (*m.at(j, i) + *m.at(i, j)) * s;
            q[k] = (*m.at(k, i) + *m.at(i, k)) * s;
            Quaternion { v: q, w: w }
        }
    }
    /// Get the rotation transform described by this quaternion
    pub fn to_transform(&self) -> Transform {
        Transform::from_mat(&Matrix4::new(
            [1.0 - 2.0 * (f32::powf(self.v.y, 2.0) + f32::powf(self.v.x, 2.0)),
             2.0 * (self.v.x * self.v.y + self.v.z * self.w),
             2.0 * (self.v.x * self.v.z - self.v.y * self.w),
             0.0,

             2.0 * (self.v.x * self.v.y - self.v.z * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.z, 2.0)),
             2.0 * (self.v.y * self.v.z + self.v.x * self.w),
             0.0,

             2.0 * (self.v.x * self.v.z + self.v.y * self.w),
             2.0 * (self.v.y * self.v.z - self.v.x * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.y, 2.0)),
             0.0,

             0.0, 0.0, 0.0, 1.0
            ]))
    }
    /// Get the normalized quaternion for this rotation
    pub fn normalized(&self) -> Quaternion {
        *self / f32::sqrt(dot(self, self))
    }
}

/// Compute the dot product of the two quaternions
pub fn dot(a: &Quaternion, b: &Quaternion) -> f32 {
    linalg::dot(&a.v, &b.v) + a.w * b.w
}

/// Use spherical linear interpolation to interpolate between the two quaternions
pub fn slerp(t: f32, a: &Quaternion, b: &Quaternion) -> Quaternion {
    // Check if a and b are nearly parallel. To avoid numerical instability we do
    // regular linear interpolation in this case
    let cos_theta = dot(a, b);
    if cos_theta > 0.9995 {
        ((1.0 - t) * *a + t * *b).normalized()
    } else {
        let theta = f32::acos(linalg::clamp(cos_theta, -1.0, 1.0));
        let theta_t = theta * t;
        let q_perp = (*b - *a * cos_theta).normalized();
        *a * f32::cos(theta_t) + q_perp * f32::sin(theta_t)
    }
}

impl Add for Quaternion {
    type Output = Quaternion;
    /// Add two quaternions
    fn add(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v + rhs.v, w: self.w + rhs.w }
    }
}

impl Sub for Quaternion {
    type Output = Quaternion;
    /// Subtract two quaternions
    fn sub(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v - rhs.v, w: self.w - rhs.w }
    }
}

impl Mul<f32> for Quaternion {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v * rhs, w: self.w * rhs }
    }
}

impl Mul<Quaternion> for f32 {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self * rhs.v, w: self * rhs.w }
    }
}

impl Div<f32> for Quaternion {
    type Output = Quaternion;
    /// Divide the quaternion by a scalar
    fn div(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v * rhs, w: self. w * rhs }
    }
}

<commit_msg>Add method to make quaternion from just a matrix<commit_after>//! Provides a Quaternion type for properly interpolating rotations

use std::f32;
use std::ops::{Add, Sub, Mul, Div};

use linalg::{self, Vector, Transform, Matrix4};

/// Quaternions describe a rotation in 3d space but can be
/// properly interpolated unlike rotation matrices. The quaternion
/// also provides methods to compute the corresponding rotation
/// transform so that it can be composed with scaling and translation
#[derive(Debug, Copy, Clone)]
pub struct Quaternion {
    pub v: Vector,
    pub w: f32,
}

impl Quaternion {
    /// Construct an identity quaternion
    pub fn identity() -> Quaternion {
        Quaternion { v: Vector::broadcast(0.0), w: 1.0 }
    }
    /// Construct a quaternion from the rotation matrix
    /// Based on Shoemake 1991
    pub fn from_matrix(m: &Matrix4) -> Quaternion {
        let trace = *m.at(0, 0) + *m.at(1, 1) + *m.at(2, 2);
        if trace > 0.0 {
            // Compute w from matrix trace, then the vector
            let mut s = f32::sqrt(trace + 1.0);
            let w = s / 2.0;
            s = 0.5 / s;
            Quaternion { v: Vector::new(s * (*m.at(2, 1) - *m.at(1, 2)), s * (*m.at(0, 2) - *m.at(2, 0)),
                                        s * (*m.at(1, 0) - *m.at(0, 1))),
                         w: w
            }
        } else {
            // Compute largest of x, y or z then the remaining components
            let next = [1, 2, 0];
            let mut q = Vector::broadcast(0.0);
            let mut i = 0;
            if *m.at(1, 1) > *m.at(0, 0) {
                i = 1;
            }
            if *m.at(2, 2) > *m.at(i, i) {
                i = 2;
            }
            let j = next[i];
            let k = next[j];
            let mut s = f32::sqrt((*m.at(i, i) - (*m.at(j, j) + *m.at(k, k))) + 1.0);
            q[i] = s * 0.5;
            if s != 0.0 {
                s = 0.5 / s;
            }
            let w = (*m.at(k, j) - *m.at(j, k)) * s;
            q[j] = (*m.at(j, i) + *m.at(i, j)) * s;
            q[k] = (*m.at(k, i) + *m.at(i, k)) * s;
            Quaternion { v: q, w: w }
        }
    }
    /// Construct the quaternion from the transform
    pub fn from_transform(t: &Transform) -> Quaternion {
        Quaternion::from_matrix(&t.mat)
    }
    /// Get the rotation transform described by this quaternion
    pub fn to_transform(&self) -> Transform {
        Transform::from_mat(&Matrix4::new(
            [1.0 - 2.0 * (f32::powf(self.v.y, 2.0) + f32::powf(self.v.x, 2.0)),
             2.0 * (self.v.x * self.v.y + self.v.z * self.w),
             2.0 * (self.v.x * self.v.z - self.v.y * self.w),
             0.0,

             2.0 * (self.v.x * self.v.y - self.v.z * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.z, 2.0)),
             2.0 * (self.v.y * self.v.z + self.v.x * self.w),
             0.0,

             2.0 * (self.v.x * self.v.z + self.v.y * self.w),
             2.0 * (self.v.y * self.v.z - self.v.x * self.w),
             1.0 - 2.0 * (f32::powf(self.v.x, 2.0) + f32::powf(self.v.y, 2.0)),
             0.0,

             0.0, 0.0, 0.0, 1.0
            ]))
    }
    /// Get the normalized quaternion for this rotation
    pub fn normalized(&self) -> Quaternion {
        *self / f32::sqrt(dot(self, self))
    }
}

/// Compute the dot product of the two quaternions
pub fn dot(a: &Quaternion, b: &Quaternion) -> f32 {
    linalg::dot(&a.v, &b.v) + a.w * b.w
}

/// Use spherical linear interpolation to interpolate between the two quaternions
pub fn slerp(t: f32, a: &Quaternion, b: &Quaternion) -> Quaternion {
    // Check if a and b are nearly parallel. To avoid numerical instability we do
    // regular linear interpolation in this case
    let cos_theta = dot(a, b);
    if cos_theta > 0.9995 {
        ((1.0 - t) * *a + t * *b).normalized()
    } else {
        let theta = f32::acos(linalg::clamp(cos_theta, -1.0, 1.0));
        let theta_t = theta * t;
        let q_perp = (*b - *a * cos_theta).normalized();
        *a * f32::cos(theta_t) + q_perp * f32::sin(theta_t)
    }
}

impl Add for Quaternion {
    type Output = Quaternion;
    /// Add two quaternions
    fn add(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v + rhs.v, w: self.w + rhs.w }
    }
}

impl Sub for Quaternion {
    type Output = Quaternion;
    /// Subtract two quaternions
    fn sub(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self.v - rhs.v, w: self.w - rhs.w }
    }
}

impl Mul<f32> for Quaternion {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v * rhs, w: self.w * rhs }
    }
}

impl Mul<Quaternion> for f32 {
    type Output = Quaternion;
    /// Multiply the quaternion by a scalar
    fn mul(self, rhs: Quaternion) -> Quaternion {
        Quaternion { v: self * rhs.v, w: self * rhs.w }
    }
}

impl Div<f32> for Quaternion {
    type Output = Quaternion;
    /// Divide the quaternion by a scalar
    fn div(self, rhs: f32) -> Quaternion {
        Quaternion { v: self.v * rhs, w: self. w * rhs }
    }
}

<|endoftext|>


<commit_before><commit_msg>Bug 1594524 - Move the call to gpu_profile.end_frame() up so that we don't measure debug overlays. r=gw<commit_after><|endoftext|>


<commit_before>pub use self::entry::*;
use memory::{PAGE_SIZE, Frame, FrameAllocator};
use self::table::{Table, Level4};
use core::ptr::Unique;

mod entry;
mod table;

const ENTRY_COUNT: usize = 512;

pub type PhysicalAddress = usize;
pub type VirtualAddress = usize;

pub struct Page {
    number: usize,
}

impl Page {
    fn containing_address(address: VirtualAddress) -> Page {
        assert!(address < 0x0000_8000_0000_0000 || address >= 0xffff_8000_0000_0000,
                "invalid address: 0x{:x}",
                address);
        Page { number: address / PAGE_SIZE }
    }

    fn start_address(&self) -> usize {
        self.number * PAGE_SIZE
    }

    fn p4_index(&self) -> usize {
        (self.number >> 27) & 0o777
    }
    fn p3_index(&self) -> usize {
        (self.number >> 18) & 0o777
    }
    fn p2_index(&self) -> usize {
        (self.number >> 9) & 0o777
    }
    fn p1_index(&self) -> usize {
        (self.number >> 0) & 0o777
    }
}

pub struct RecursivePageTable {
    p4: Unique<Table<Level4>>,
}

impl RecursivePageTable {
    pub unsafe fn new() -> RecursivePageTable {
        RecursivePageTable { p4: Unique::new(table::P4) }
    }

    fn p4(&self) -> &Table<Level4> {
        unsafe { self.p4.get() }
    }

    fn p4_mut(&mut self) -> &mut Table<Level4> {
        unsafe { self.p4.get_mut() }
    }

    pub fn translate(&self, virtual_address: VirtualAddress) -> Option<PhysicalAddress> {
        let offset = virtual_address % PAGE_SIZE;
        self.translate_page(Page::containing_address(virtual_address))
            .map(|frame| frame.number * PAGE_SIZE + offset)
    }

    fn translate_page(&self, page: Page) -> Option<Frame> {
        let p3 = self.p4().next_table(page.p4_index());

        let huge_page = || {
            p3.and_then(|p3| {
                let p3_entry = &p3[page.p3_index()];
                // 1GiB page?
                if let Some(start_frame) = p3_entry.pointed_frame() {
                    if p3_entry.flags().contains(HUGE_PAGE) {
                        // address must be 1GiB aligned
                        assert!(start_frame.number % (ENTRY_COUNT * ENTRY_COUNT) == 0);
                        return Some(Frame {
                            number: start_frame.number + page.p2_index() * ENTRY_COUNT +
                                    page.p1_index(),
                        });
                    }
                }
                if let Some(p2) = p3.next_table(page.p3_index()) {
                    let p2_entry = &p2[page.p2_index()];
                    // 2MiB page?
                    if let Some(start_frame) = p2_entry.pointed_frame() {
                        if p2_entry.flags().contains(HUGE_PAGE) {
                            // address must be 2MiB aligned
                            assert!(start_frame.number % ENTRY_COUNT == 0);
                            return Some(Frame { number: start_frame.number + page.p1_index() });
                        }
                    }
                }
                None
            })
        };

        p3.and_then(|p3| p3.next_table(page.p3_index()))
          .and_then(|p2| p2.next_table(page.p2_index()))
          .and_then(|p1| p1[page.p1_index()].pointed_frame())
          .or_else(huge_page)
    }

    pub fn map_to<A>(&mut self, page: Page, frame: Frame, flags: EntryFlags, allocator: &mut A)
        where A: FrameAllocator
    {
        let mut p3 = self.p4_mut().next_table_create(page.p4_index(), allocator);
        let mut p2 = p3.next_table_create(page.p3_index(), allocator);
        let mut p1 = p2.next_table_create(page.p2_index(), allocator);

        assert!(p1[page.p1_index()].is_unused());
        p1[page.p1_index()].set(frame, flags | PRESENT);
    }
}
<commit_msg>Add `map` and `identity_map` functions<commit_after>pub use self::entry::*;
use memory::{PAGE_SIZE, Frame, FrameAllocator};
use self::table::{Table, Level4};
use core::ptr::Unique;

mod entry;
mod table;

const ENTRY_COUNT: usize = 512;

pub type PhysicalAddress = usize;
pub type VirtualAddress = usize;

pub struct Page {
    number: usize,
}

impl Page {
    fn containing_address(address: VirtualAddress) -> Page {
        assert!(address < 0x0000_8000_0000_0000 || address >= 0xffff_8000_0000_0000,
                "invalid address: 0x{:x}",
                address);
        Page { number: address / PAGE_SIZE }
    }

    fn start_address(&self) -> usize {
        self.number * PAGE_SIZE
    }

    fn p4_index(&self) -> usize {
        (self.number >> 27) & 0o777
    }
    fn p3_index(&self) -> usize {
        (self.number >> 18) & 0o777
    }
    fn p2_index(&self) -> usize {
        (self.number >> 9) & 0o777
    }
    fn p1_index(&self) -> usize {
        (self.number >> 0) & 0o777
    }
}

pub struct RecursivePageTable {
    p4: Unique<Table<Level4>>,
}

impl RecursivePageTable {
    pub unsafe fn new() -> RecursivePageTable {
        RecursivePageTable { p4: Unique::new(table::P4) }
    }

    fn p4(&self) -> &Table<Level4> {
        unsafe { self.p4.get() }
    }

    fn p4_mut(&mut self) -> &mut Table<Level4> {
        unsafe { self.p4.get_mut() }
    }

    pub fn translate(&self, virtual_address: VirtualAddress) -> Option<PhysicalAddress> {
        let offset = virtual_address % PAGE_SIZE;
        self.translate_page(Page::containing_address(virtual_address))
            .map(|frame| frame.number * PAGE_SIZE + offset)
    }

    fn translate_page(&self, page: Page) -> Option<Frame> {
        let p3 = self.p4().next_table(page.p4_index());

        let huge_page = || {
            p3.and_then(|p3| {
                let p3_entry = &p3[page.p3_index()];
                // 1GiB page?
                if let Some(start_frame) = p3_entry.pointed_frame() {
                    if p3_entry.flags().contains(HUGE_PAGE) {
                        // address must be 1GiB aligned
                        assert!(start_frame.number % (ENTRY_COUNT * ENTRY_COUNT) == 0);
                        return Some(Frame {
                            number: start_frame.number + page.p2_index() * ENTRY_COUNT +
                                    page.p1_index(),
                        });
                    }
                }
                if let Some(p2) = p3.next_table(page.p3_index()) {
                    let p2_entry = &p2[page.p2_index()];
                    // 2MiB page?
                    if let Some(start_frame) = p2_entry.pointed_frame() {
                        if p2_entry.flags().contains(HUGE_PAGE) {
                            // address must be 2MiB aligned
                            assert!(start_frame.number % ENTRY_COUNT == 0);
                            return Some(Frame { number: start_frame.number + page.p1_index() });
                        }
                    }
                }
                None
            })
        };

        p3.and_then(|p3| p3.next_table(page.p3_index()))
          .and_then(|p2| p2.next_table(page.p2_index()))
          .and_then(|p1| p1[page.p1_index()].pointed_frame())
          .or_else(huge_page)
    }

    pub fn map_to<A>(&mut self, page: Page, frame: Frame, flags: EntryFlags, allocator: &mut A)
        where A: FrameAllocator
    {
        let mut p3 = self.p4_mut().next_table_create(page.p4_index(), allocator);
        let mut p2 = p3.next_table_create(page.p3_index(), allocator);
        let mut p1 = p2.next_table_create(page.p2_index(), allocator);

        assert!(p1[page.p1_index()].is_unused());
        p1[page.p1_index()].set(frame, flags | PRESENT);
    }

    pub fn map<A>(&mut self, page: Page, flags: EntryFlags, allocator: &mut A)
        where A: FrameAllocator
    {
        let frame = allocator.allocate_frame().expect("out of memory");
        self.map_to(page, frame, flags, allocator)
    }

    pub fn identity_map<A>(&mut self, frame: Frame, flags: EntryFlags, allocator: &mut A)
        where A: FrameAllocator
    {
        let page = Page::containing_address(frame.start_address());
        self.map_to(page, frame, flags, allocator)
    }
}
<|endoftext|>


<commit_before>
use geometry::Point;
use core::rand::RngUtil;
use core::float::pow;
mod geometry;

//
// Cellule
//

struct Cell {
    center: Point,
    id: uint,
    radius: f64,
    velocity: Point,
    acc: Point,
    generation: int,
    age: int
}

pub impl Cell {
    fn new(ident: uint) -> Cell {
        let radius = 1.0;
        //let r=rand::random::<float>();
        //io::println(fmt!("%f\n", r));
        let center : Point =rand::random();

        Cell{ center: center, id: ident, radius: radius, velocity: Point::new(), acc: Point::new(), generation: 0, age:0}
    }

    fn move(&mut self, tumeur: &Crowd, dt: f64) {
        let old_acc = copy self.acc;

        // Nouvelle position
        self.center+=self.velocity+self.acc*(0.5*float::pow(dt,2.0) as f64);

        // Force aléatoire
        let mut F_alea: Point=rand::random();
        F_alea-=0.5 as f64;
        self.acc=self.calc_rep_force(tumeur)+F_alea*(0.05 as f64);

        // Nouvelle vitesse
        let lambda : f64=5.0;
        let denom : f64 = 1.0/(1.0+lambda*dt/2.0);
        self.velocity=(self.velocity*(1.0-lambda*dt/2.0)+(self.acc+old_acc)*dt/(2.0 as f64))*denom;

    }

    fn replicate(&mut self, tumeur: &Crowd, dt: f64) {
        io::println(fmt!("%d @ %f\n",tumeur.size() as int, dt as float));

        self.age+=1;
    }

    fn calc_rep_force(&self, tumeur: &Crowd) -> Point {
        let seuil=3.0*self.radius;
        let mut force = Point::new();
        for tumeur.cells.each |&cell| {
            if(cell.id != self.id) {
                let dist_cells=(self.dist(cell)+2.0*self.radius)/seuil;
                let factor = 1.0/pow(dist_cells,3.0)*1e-7 as f64;
                force += (self.center-cell.center)*factor;
            }
        }
        force
    }

    #[inline(always)]
    fn x(&self) -> f64 {
        self.center.x
    }

    #[inline(always)]
    fn y(&self) -> f64 {
        self.center.y
    }

    fn dist(&self, other: &Cell) -> f64 {
        self.center.dist(&other.center)
    }

}

impl ToStr for Cell {
    fn to_str(&self) -> ~str {
        fmt!("%d @ (%f, %f)", self.id as int, self.center.x as float, self.center.y as float)
    }
}

#[test]
fn test_new() {
    let cell1=Cell::new(0);
    let cell2=Cell::new(1);
    assert!(cell1.center != cell2.center);
}

//
// Population
//

struct Crowd {
    cells : ~[@mut Cell],
    time : float
}

pub impl Crowd {
    fn new(init_pop : uint) -> Crowd {

        let mut pop : ~[@mut Cell]=~[];
        for uint::range(1,init_pop+1) |num| {
            let lonely_one = @mut Cell::new(num);
            pop.push(copy lonely_one);
        }
        Crowd{ cells : pop, time: 0.0}
    }

    fn size(&self) -> uint {
        self.cells.len()
    }

    fn evolve(&self, dt: f64) {
        for self.cells.each |cell| {
            cell.move(self, dt);
        }
    }
}

impl ToStr for Crowd {
    fn to_str(&self) -> ~str {
        let mut desc =~"";
        for self.cells.each |cell| {
            let mut lcell_desc=~"";
            lcell_desc.push_str(cell.to_str()); lcell_desc.push_str("\n");
             desc.push_str(lcell_desc);
        }
        desc
    }
}

#[test]
fn test_size() {
    let crowd=Crowd::new(13);
    assert!(crowd.size()==13);
}
<commit_msg>Réglage de la force de répulsion<commit_after>
use geometry::Point;
use core::rand::RngUtil;
use core::float::pow;
mod geometry;

//
// Cellule
//

struct Cell {
    center: Point,
    id: uint,
    radius: f64,
    velocity: Point,
    acc: Point,
    generation: int,
    age: int
}

pub impl Cell {
    fn new(ident: uint) -> Cell {
        let radius = 1.0;
        //let r=rand::random::<float>();
        //io::println(fmt!("%f\n", r));
        let center : Point =rand::random();

        Cell{ center: center, id: ident, radius: radius, velocity: Point::new(), acc: Point::new(), generation: 0, age:0}
    }

    fn move(&mut self, tumeur: &Crowd, dt: f64) {
        let old_acc = copy self.acc;

        // Nouvelle position
        self.center+=self.velocity+self.acc*(0.5*float::pow(dt,2.0) as f64);

        // Force aléatoire
        let mut F_alea: Point=rand::random();
        F_alea-=0.5 as f64;
        self.acc=self.calc_rep_force(tumeur)+F_alea*(0.05 as f64);

        // Nouvelle vitesse
        let lambda : f64=5.0;
        let denom : f64 = 1.0/(1.0+lambda*dt/2.0);
        self.velocity=(self.velocity*(1.0-lambda*dt/2.0)+(self.acc+old_acc)*dt/(2.0 as f64))*denom;

    }

    fn replicate(&mut self, tumeur: &Crowd, dt: f64) {
        io::println(fmt!("%d @ %f\n",tumeur.size() as int, dt as float));

        self.age+=1;
    }

    fn calc_rep_force(&self, tumeur: &Crowd) -> Point {
        let seuil=3.0*self.radius;
        let mut force = Point::new();
        for tumeur.cells.each |&cell| {
            if(cell.id != self.id) {
                let dist_cells=(self.dist(cell)+2.0*self.radius)/seuil;
                let factor = 1.0/pow(dist_cells,3.0)*1e-5 as f64;
                force += (self.center-cell.center)*factor;
            }
        }
        force
    }

    #[inline(always)]
    fn x(&self) -> f64 {
        self.center.x
    }

    #[inline(always)]
    fn y(&self) -> f64 {
        self.center.y
    }

    fn dist(&self, other: &Cell) -> f64 {
        self.center.dist(&other.center)
    }

}

impl ToStr for Cell {
    fn to_str(&self) -> ~str {
        fmt!("%d @ (%f, %f)", self.id as int, self.center.x as float, self.center.y as float)
    }
}

#[test]
fn test_new() {
    let cell1=Cell::new(0);
    let cell2=Cell::new(1);
    assert!(cell1.center != cell2.center);
}

//
// Population
//

struct Crowd {
    cells : ~[@mut Cell],
    time : float
}

pub impl Crowd {
    fn new(init_pop : uint) -> Crowd {

        let mut pop : ~[@mut Cell]=~[];
        for uint::range(1,init_pop+1) |num| {
            let lonely_one = @mut Cell::new(num);
            pop.push(copy lonely_one);
        }
        Crowd{ cells : pop, time: 0.0}
    }

    fn size(&self) -> uint {
        self.cells.len()
    }

    fn evolve(&self, dt: f64) {
        for self.cells.each |cell| {
            cell.move(self, dt);
        }
    }
}

impl ToStr for Crowd {
    fn to_str(&self) -> ~str {
        let mut desc =~"";
        for self.cells.each |cell| {
            let mut lcell_desc=~"";
            lcell_desc.push_str(cell.to_str()); lcell_desc.push_str("\n");
             desc.push_str(lcell_desc);
        }
        desc
    }
}

#[test]
fn test_size() {
    let crowd=Crowd::new(13);
    assert!(crowd.size()==13);
}
<|endoftext|>