<commit_before>// library
extern crate my_extern_lib;

// modules
mod simple_functions {
    pub fn print_hello_world() {
        println!("Hello, World! (from the simple_functions module)");
     }

    // nested modules
    pub mod simple_math {
        pub fn multiple_two_integers(a: i32, b: i32) -> i32 {
            a * b
        }
    }
}

use simple_functions::simple_math::multiple_two_integers;

fn print_some_msg() {
    println!("Modules: printing from the outer function");
}

mod sample_module {

    pub fn call_sample_module() {
        use second_module::print_some_msg as print_second;
        use self::second_module::print_some_msg as print_second_sample;
        use super::print_some_msg as print_outside;
        print_outside();
        print_second();
        print_some_msg();
        print_second_sample();
    }

    mod second_module {

        pub fn print_some_msg() {
            println!("Modules: printing from the second module inside the sample module");
        }

    }

    fn print_some_msg() {
        println!("Modules: printing from the inside of the sample module");
    }

}

mod second_module {
    pub fn print_some_msg() {
        println!("Modules: printing from the second module");
    }
}

mod modules;

fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

    // variables
    let integer = 3i32;
    let floating_point = 2.1137;

    let mut u_integer = 3u32;
    //integer += 1; error: an immutable variable
    u_integer += 1;

    println!("{}, {}, {}", integer, floating_point, u_integer);
    // TODO find out why snake case instead of camel case

    // shadowing
    let first_var = 4;
    {
        let first_var = 51;
        println!("first_var = {}", first_var);
    }
    println!("first_var = {}", first_var);

    // unitialized variables
    let uninit_var;
    //println!("uninit_var = {}", uninit_var); error: use of an init variable
    uninit_var = 231.2;
    println!("already initialized uninit_var = {}", uninit_var);

    // type casting
    let a_integer = 0x40_u8;
    let a_char = a_integer as char;
    println!("char cast from integer {}: {}", a_integer, a_char);

    let a_float = 8.45511;
    println!("integer cast from float {}: {}", a_float, a_float as i32);

    println!("Binary represntation of {}: {:08b}", -1_i8, -1_i8);
    println!("Binary represntation of {}: {:08b}", -2_i8, -2_i8);

    // aliases
    type FloatingPoint32 = f32;
    let a_float_2 : FloatingPoint32 = 3 as f32;
    println!("Type alias: {}, size of var {}", a_float_2, std::mem::size_of_val(&a_float_2));

    // expressions
    let expr = {
        let x = 4.09;
        let y = 1.28;
        println!("x = {}, y = {}", x, y);
        x / y
    };
    println!("expr = {}", expr);

    // if-statement (every if-statement is an expression too, which is really a cool thing)
    let speed = 10;
    let mass = 890;
    let consumption =
        if speed < 0 {
            -1.0
        }
        else if speed == 0 {
            0.8
        }
        else if speed > 0 && speed < 10 {
            18.52
        }
        else if speed >= 10 && speed < 30 {
            let x = mass / speed;
            (x as f32) * 0.05
        }
        else {
            11.71
        };
        println!("Speed = {}, consumption = {}", speed, consumption);

        // loop
        let mut count = 0u32;
        loop {
            println!("loop iteration #{}", count);
            count += 1;
            if count > 9 {
            break;
            }
        }

        count = 0;
        while count < 10 {
            println!("while loop iteration #{}", count);
            count += 1;
        }

        for n in 0u32..10 {
            println!("for loop iteration #{}", n);
        }

        // matching
        let age = 19;
        match age {
            1  => println!("Seems like 1"),
            5  => println!("It's 5"),
            18 => println!("Exactly 18!"),
            _  => println!("I couldn't guess :("),
        }

        match age {
            a if a > 1 && a <= 9  => println!("The age is in range [1,9]"),
            a if a > 9 && a <= 19 => println!("The age is in range [10, 19]"),
            _                     => println!("Nothing, I don't know what range the age is in :("),
        }

        // the previous match is equivalent to the following:
        match age {
            a @ 1...9   => println!("The age is {} and in range [1,9]", a),
            a @ 10...19 => println!("The age is {} and in range [10, 19]", a),
            a           => println!("Nothing, I don't know what range the age {} is in :(", a),
        }

        // if let
        let a_some = Some(0.0008);
        if let Some(i) = a_some {
            println!("a_some is not None, {}", i);
            println!("result {}",  9.0 / i);
        }
        else {
            println!("None");
        }

        // while let
        let mut a_optional = Some(10);

        while let Some(i) = a_optional {
            if i == 20 {
                println!("while let: i equals 20, leave");
                a_optional = None;
            }
            else {
                a_optional = Some(i + 1);
            }
        }

        // functions, finally!
        let first_integer: i32 = -20;
        let second_integer: i32 = 8;
        let result_of_addition = add_two_integers(first_integer, second_integer);
        println!("{} + {} = {}", first_integer, second_integer, result_of_addition);

        simple_functions::print_hello_world();
        let mul_result = simple_functions::simple_math::multiple_two_integers(3, 15);
        println!("Modules: multiplication result = {}", mul_result);

        // this doesn't work.. why?
        println!("Modules: multiplication result 2 = {}", multiple_two_integers(-1, 8));

        // "super" and "self"
        sample_module::call_sample_module();

        // file hierarchy
        {
            let a : i32 = 4;
            let b : i32 = 15;
            println!("modules::math {} + {} = {}", a, b, modules::math::add_two_int(a, b));
        }

        // call external library
        my_extern_lib::run(5);

        // tuples
        let pair = ("key", 4);
        println!("tuple value: ({}, {})", pair.0, pair.1);
        println!("tuple value: {:?}", pair);

        // structs
        let bmw: Car = Car {color: "Blue".to_string(), weight: 940};
        println!("BMW: {} - {}", bmw.color, bmw.weight);

        // tuple structs
        let color_1: RgbColor = RgbColor(123, 33, 81);
        println!("RGB color: {}, {}, {}", color_1.0, color_1.1, color_1.2);

        // unit structs
        let _nil = Nil;

        // a struct with a constructor and getter
        let rabbit = my_extern_lib::Animal::new(2, 4, "The King");
        println!("Rabbit: {}, {}, {}", rabbit.age, rabbit.weight, rabbit.get_secret_info());

        // generics
        {
            struct ThreeValues<T, U, V> {
                first: T,
                second: U,
                third: V,
            }

            let three_values = ThreeValues { first: 4, second: 2.01, third: "hello" };
            println!("Generic data structure: {}, {}, {}", three_values.first, three_values.second, three_values.third);

            // generic function
            fn swap<U, V>(first_value: U, second_value: V) -> (V, U) {
                (second_value, first_value)
            }

            let random_tuple = swap(4, 2);
            println!("Use unused variables: {} {}", random_tuple.0, random_tuple.1);

        }

        // box (heap allocation)
        {

            let toyota: Car = Car {color: "Green".to_string(), weight: 1040,};
            let porche: Box<Car> = Box::new(Car {color: "Black".to_string(), weight: 876, });

            println!("Toyota's size on stack is {}", std::mem::size_of_val(&toyota));
            println!("Boxed porche's size on stack is {}", std::mem::size_of_val(&porche));

            let unboxed_porche: Car = *porche;
            println!("Unboxed porche's size on stack is {}", std::mem::size_of_val(&unboxed_porche));

            // ownership
            let bmw : Box<Car> = Box::new(Car {color: "Yellow".to_string(), weight: 1620});
            println!("Boxed BMW at {:p}: {}/{}", &bmw, bmw.color, bmw.weight);
            let moved_bmw: Box<Car> = bmw;
            println!("Moved BMW at {:p}: {}/{}", &moved_bmw, moved_bmw.color, moved_bmw.weight);
            // can't do the following, the ownership has been moved
            // println!("Boxed BMW at {:p}: {}/{}", &bmw, bmw.color, bmw.weight);

            // mutability
            let immutable_car = Box::new(Car {color: "Pink".to_string(), weight: 510});
            // can't do this
            // immutable_car.weight = 403;

            // but we can change mutability
            let mut mutable_car = immutable_car;
            mutable_car.weight = 401;

        }

        // ref
        {

            let mut bmw: Car = Car {color: "Green".to_string(), weight: 870};
            println!("Ref: bmw {},{}", bmw.color, bmw.weight);

            {
                let Car {color: _, weight: ref weight_reference} = bmw;

                println!("Ref: {}", *weight_reference);
            }

            {
                let Car {color: _, weight: ref mut weight_mut_ref} = bmw;

                *weight_mut_ref = 200;
            }

            println!("Ref: bmw {},{}", bmw.color, bmw.weight);

        }

        // try some enums
        {

            enum TwoValues {
                First(i8),
                Second(f32),
            }

            fn test_enum(some_number: i32) -> TwoValues {

                if some_number > 0 {
                    TwoValues::First(120)
                }
                else {
                    TwoValues::Second(3.09)
                }

            }

            match test_enum(-2) {
                TwoValues::First(value) => println!("TwoValues enum: {}", value),
                TwoValues::Second(value) => println!("TwoValues enum: {}", value),
            }

            let two_values_instance = TwoValues::First(9);
            println!("TwoValues enum: size of a variant {}", std::mem::size_of_val(&two_values_instance));

        }

        // closures
        {
            let say = |phrase: String| {println!("{}", phrase)};
            say("Hello, closure!".to_string()); // this is probably worse than just println!

            fn mutate_integer<F: Fn(i32) -> i32>(value: i32, mutator: F) -> i32 {
                mutator(value)
            }

            let modulo_three = |v: i32| {v % 3};

            let value: i32 = 23;
            println!("Closures: input value = {}, result = {}", value, mutate_integer(value, modulo_three));

            let add_five = |v: u32| {v + 5};
            let mul_ten = |v: u32| {v * 10};

            fn mutate_integer_2<F, G>(value: u32, mutator_1: F, mutator_2: G) -> u32
                where F: Fn(u32) -> u32, G: Fn(u32) -> u32 {

                mutator_2(mutator_1(value))

            }

            let value_2: u32 = 7194682;
            println!("Closures #2: input value = {}, result = {}", value_2, mutate_integer_2(value_2, add_five, mul_ten));
        }
}

// a C-like struct
struct Car {
    color: String,
    weight: u32,
}

// a tuple struct s
struct RgbColor(i8, i8, i8);

// a unit struct
struct Nil;

fn add_two_integers(a: i32, b: i32) -> i32 {
    a + b
}
<commit_msg>Progress: threads<commit_after>// library
extern crate my_extern_lib;

// modules
mod simple_functions {
    pub fn print_hello_world() {
        println!("Hello, World! (from the simple_functions module)");
     }

    // nested modules
    pub mod simple_math {
        pub fn multiple_two_integers(a: i32, b: i32) -> i32 {
            a * b
        }
    }
}

use simple_functions::simple_math::multiple_two_integers;

fn print_some_msg() {
    println!("Modules: printing from the outer function");
}

mod sample_module {

    pub fn call_sample_module() {
        use second_module::print_some_msg as print_second;
        use self::second_module::print_some_msg as print_second_sample;
        use super::print_some_msg as print_outside;
        print_outside();
        print_second();
        print_some_msg();
        print_second_sample();
    }

    mod second_module {

        pub fn print_some_msg() {
            println!("Modules: printing from the second module inside the sample module");
        }

    }

    fn print_some_msg() {
        println!("Modules: printing from the inside of the sample module");
    }

}

mod second_module {
    pub fn print_some_msg() {
        println!("Modules: printing from the second module");
    }
}

mod modules;

fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

    // variables
    let integer = 3i32;
    let floating_point = 2.1137;

    let mut u_integer = 3u32;
    //integer += 1; error: an immutable variable
    u_integer += 1;

    println!("{}, {}, {}", integer, floating_point, u_integer);
    // TODO find out why snake case instead of camel case

    // shadowing
    let first_var = 4;
    {
        let first_var = 51;
        println!("first_var = {}", first_var);
    }
    println!("first_var = {}", first_var);

    // unitialized variables
    let uninit_var;
    //println!("uninit_var = {}", uninit_var); error: use of an init variable
    uninit_var = 231.2;
    println!("already initialized uninit_var = {}", uninit_var);

    // type casting
    let a_integer = 0x40_u8;
    let a_char = a_integer as char;
    println!("char cast from integer {}: {}", a_integer, a_char);

    let a_float = 8.45511;
    println!("integer cast from float {}: {}", a_float, a_float as i32);

    println!("Binary represntation of {}: {:08b}", -1_i8, -1_i8);
    println!("Binary represntation of {}: {:08b}", -2_i8, -2_i8);

    // aliases
    type FloatingPoint32 = f32;
    let a_float_2 : FloatingPoint32 = 3 as f32;
    println!("Type alias: {}, size of var {}", a_float_2, std::mem::size_of_val(&a_float_2));

    // expressions
    let expr = {
        let x = 4.09;
        let y = 1.28;
        println!("x = {}, y = {}", x, y);
        x / y
    };
    println!("expr = {}", expr);

    // if-statement (every if-statement is an expression too, which is really a cool thing)
    let speed = 10;
    let mass = 890;
    let consumption =
        if speed < 0 {
            -1.0
        }
        else if speed == 0 {
            0.8
        }
        else if speed > 0 && speed < 10 {
            18.52
        }
        else if speed >= 10 && speed < 30 {
            let x = mass / speed;
            (x as f32) * 0.05
        }
        else {
            11.71
        };
        println!("Speed = {}, consumption = {}", speed, consumption);

        // loop
        let mut count = 0u32;
        loop {
            println!("loop iteration #{}", count);
            count += 1;
            if count > 9 {
            break;
            }
        }

        count = 0;
        while count < 10 {
            println!("while loop iteration #{}", count);
            count += 1;
        }

        for n in 0u32..10 {
            println!("for loop iteration #{}", n);
        }

        // matching
        let age = 19;
        match age {
            1  => println!("Seems like 1"),
            5  => println!("It's 5"),
            18 => println!("Exactly 18!"),
            _  => println!("I couldn't guess :("),
        }

        match age {
            a if a > 1 && a <= 9  => println!("The age is in range [1,9]"),
            a if a > 9 && a <= 19 => println!("The age is in range [10, 19]"),
            _                     => println!("Nothing, I don't know what range the age is in :("),
        }

        // the previous match is equivalent to the following:
        match age {
            a @ 1...9   => println!("The age is {} and in range [1,9]", a),
            a @ 10...19 => println!("The age is {} and in range [10, 19]", a),
            a           => println!("Nothing, I don't know what range the age {} is in :(", a),
        }

        // if let
        let a_some = Some(0.0008);
        if let Some(i) = a_some {
            println!("a_some is not None, {}", i);
            println!("result {}",  9.0 / i);
        }
        else {
            println!("None");
        }

        // while let
        let mut a_optional = Some(10);

        while let Some(i) = a_optional {
            if i == 20 {
                println!("while let: i equals 20, leave");
                a_optional = None;
            }
            else {
                a_optional = Some(i + 1);
            }
        }

        // functions, finally!
        let first_integer: i32 = -20;
        let second_integer: i32 = 8;
        let result_of_addition = add_two_integers(first_integer, second_integer);
        println!("{} + {} = {}", first_integer, second_integer, result_of_addition);

        simple_functions::print_hello_world();
        let mul_result = simple_functions::simple_math::multiple_two_integers(3, 15);
        println!("Modules: multiplication result = {}", mul_result);

        // this doesn't work.. why?
        println!("Modules: multiplication result 2 = {}", multiple_two_integers(-1, 8));

        // "super" and "self"
        sample_module::call_sample_module();

        // file hierarchy
        {
            let a : i32 = 4;
            let b : i32 = 15;
            println!("modules::math {} + {} = {}", a, b, modules::math::add_two_int(a, b));
        }

        // call external library
        my_extern_lib::run(5);

        // tuples
        let pair = ("key", 4);
        println!("tuple value: ({}, {})", pair.0, pair.1);
        println!("tuple value: {:?}", pair);

        // structs
        let bmw: Car = Car {color: "Blue".to_string(), weight: 940};
        println!("BMW: {} - {}", bmw.color, bmw.weight);

        // tuple structs
        let color_1: RgbColor = RgbColor(123, 33, 81);
        println!("RGB color: {}, {}, {}", color_1.0, color_1.1, color_1.2);

        // unit structs
        let _nil = Nil;

        // a struct with a constructor and getter
        let rabbit = my_extern_lib::Animal::new(2, 4, "The King");
        println!("Rabbit: {}, {}, {}", rabbit.age, rabbit.weight, rabbit.get_secret_info());

        // generics
        {
            struct ThreeValues<T, U, V> {
                first: T,
                second: U,
                third: V,
            }

            let three_values = ThreeValues { first: 4, second: 2.01, third: "hello" };
            println!("Generic data structure: {}, {}, {}", three_values.first, three_values.second, three_values.third);

            // generic function
            fn swap<U, V>(first_value: U, second_value: V) -> (V, U) {
                (second_value, first_value)
            }

            let random_tuple = swap(4, 2);
            println!("Use unused variables: {} {}", random_tuple.0, random_tuple.1);

        }

        // box (heap allocation)
        {

            let toyota: Car = Car {color: "Green".to_string(), weight: 1040,};
            let porche: Box<Car> = Box::new(Car {color: "Black".to_string(), weight: 876, });

            println!("Toyota's size on stack is {}", std::mem::size_of_val(&toyota));
            println!("Boxed porche's size on stack is {}", std::mem::size_of_val(&porche));

            let unboxed_porche: Car = *porche;
            println!("Unboxed porche's size on stack is {}", std::mem::size_of_val(&unboxed_porche));

            // ownership
            let bmw : Box<Car> = Box::new(Car {color: "Yellow".to_string(), weight: 1620});
            println!("Boxed BMW at {:p}: {}/{}", &bmw, bmw.color, bmw.weight);
            let moved_bmw: Box<Car> = bmw;
            println!("Moved BMW at {:p}: {}/{}", &moved_bmw, moved_bmw.color, moved_bmw.weight);
            // can't do the following, the ownership has been moved
            // println!("Boxed BMW at {:p}: {}/{}", &bmw, bmw.color, bmw.weight);

            // mutability
            let immutable_car = Box::new(Car {color: "Pink".to_string(), weight: 510});
            // can't do this
            // immutable_car.weight = 403;

            // but we can change mutability
            let mut mutable_car = immutable_car;
            mutable_car.weight = 401;

        }

        // ref
        {

            let mut bmw: Car = Car {color: "Green".to_string(), weight: 870};
            println!("Ref: bmw {},{}", bmw.color, bmw.weight);

            {
                let Car {color: _, weight: ref weight_reference} = bmw;

                println!("Ref: {}", *weight_reference);
            }

            {
                let Car {color: _, weight: ref mut weight_mut_ref} = bmw;

                *weight_mut_ref = 200;
            }

            println!("Ref: bmw {},{}", bmw.color, bmw.weight);

        }

        // try some enums
        {

            enum TwoValues {
                First(i8),
                Second(f32),
            }

            fn test_enum(some_number: i32) -> TwoValues {

                if some_number > 0 {
                    TwoValues::First(120)
                }
                else {
                    TwoValues::Second(3.09)
                }

            }

            match test_enum(-2) {
                TwoValues::First(value) => println!("TwoValues enum: {}", value),
                TwoValues::Second(value) => println!("TwoValues enum: {}", value),
            }

            let two_values_instance = TwoValues::First(9);
            println!("TwoValues enum: size of a variant {}", std::mem::size_of_val(&two_values_instance));

        }

        // closures
        {
            let say = |phrase: String| {println!("{}", phrase)};
            say("Hello, closure!".to_string()); // this is probably worse than just println!

            fn mutate_integer<F: Fn(i32) -> i32>(value: i32, mutator: F) -> i32 {
                mutator(value)
            }

            let modulo_three = |v: i32| {v % 3};

            let value: i32 = 23;
            println!("Closures: input value = {}, result = {}", value, mutate_integer(value, modulo_three));

            let add_five = |v: u32| {v + 5};
            let mul_ten = |v: u32| {v * 10};

            fn mutate_integer_2<F, G>(value: u32, mutator_1: F, mutator_2: G) -> u32
                where F: Fn(u32) -> u32, G: Fn(u32) -> u32 {

                mutator_2(mutator_1(value))

            }

            let value_2: u32 = 7194682;
            println!("Closures #2: input value = {}, result = {}", value_2, mutate_integer_2(value_2, add_five, mul_ten));
        }

        // threads
        {
            use std::thread;
            use std::old_io::timer;
            use std::time::Duration;

            // without a guard
            thread::spawn(|| {
                println!("Very first thread EEEEEEYYYYYEEEECCCCAAAAAAATTTCCCHHHEEEERRR!!!");
            });
            timer::sleep(Duration::milliseconds(50)); // we need it because main terminates and kills all the threads

            // with a guard
            let thread_guard = thread::scoped(|| {
                println!("Thread with a guard here!!");
            });

            // another example
            for i in range(0, 16) {

                thread::spawn(move || {
                    println!("Thread #{} started", i);
                    timer::sleep(Duration::milliseconds(500 % (i + 1)));
                    println!("Thread #{} finished", i);
                });

            }
            timer::sleep(Duration::milliseconds(2500));
        }
}

// a C-like struct
struct Car {
    color: String,
    weight: u32,
}

// a tuple struct s
struct RgbColor(i8, i8, i8);

// a unit struct
struct Nil;

fn add_two_integers(a: i32, b: i32) -> i32 {
    a + b
}
<|endoftext|>


<commit_before>#![allow(ctypes)]
#![no_std]
#![no_main]
#![feature(globs)]
#![feature(asm)]
// Adding pub mod (another fix for this warning) increases footprint, so just
// disble it instead.
#![allow(visible_private_types)]

extern crate core;

use con::write;
use start32::MultiBootInfo;
//use start32::OrigMultiBootInfo;
use start32::PhysAddr;
use start32::MutPhysAddr;
use x86::idt;

#[allow(dead_code)]
mod con;
mod mboot;
mod mem;
mod start32;
mod util;
mod x86;

static mut idt_table : [idt::Entry, ..48] = [idt::null_entry, ..48];

#[allow(dead_code)]
fn writeMBInfo(infop : *mboot::Info) {
	con::write("Multiboot info at ");
	con::writePtr(infop);
	con::putc('\n');

	let &info = unsafe { &*infop };
	con::write("Flags: ");
	con::writeHex(info.flags as uint);
	con::newline();

	if info.has(mboot::MemorySize) {
		con::writeUInt(info.mem_lower as uint);
		con::write("kB lower memory, ");
		con::writeUInt(info.mem_upper as uint);
		con::write("kB upper memory, ");
		con::writeUInt(((info.mem_lower + info.mem_upper + 1023) / 1024) as uint);
		con::write("MB total.\n");
	}
	// FIXME start32 doesn't copy this
	if info.has(mboot::CommandLine) {
		let cmdline : *u8 = PhysAddr(info.cmdline as uint);
		con::write("Command line @");
		con::writePtr(cmdline);
		con::write(" (");
		con::writeHex(info.cmdline as uint);
		con::write(") \"");
		con::writeCStr(cmdline);
		con::write("\"\n");
	}
}

pub fn generic_irq_handler(_vec : u8) {
}

pub fn page_fault(_error : u64) {
}

pub fn idle() -> ! {
	loop { unsafe { asm!("hlt"); } }
}

pub struct PerCpu {
	selfp : *mut PerCpu,
	memory : mem::PerCpu,
}

impl PerCpu {
	// TODO Always do a heap allocation so we can populate selfp with a proper
	// value
	fn new() -> PerCpu {
		PerCpu { selfp : 0 as *mut PerCpu, memory : mem::PerCpu::new() }
	}

	fn run(&mut self) -> ! {
		// TODO: Pop something from run queue, run it
		idle();
	}
}

// NB: One of the funky guarantees that Rust gives/requires is that there is
// at most one &mut reference to the same thing at any one time. This function
// can't quite guarantee that...
// This function also returns garbage as long as PerCpu::new doesn't fill in
// the selfp pointer.
pub fn cpu() -> &mut PerCpu {
	unsafe {
		let mut ret = 0;
		asm!("movq gs:($0), $0" : "=r"(ret) : "0"(ret));
		return &mut *(ret as *mut PerCpu);
	}
}

#[lang="exchange_malloc"]
pub fn malloc(_size : uint) -> *mut u8 {
	return cpu().memory.alloc_frame_panic();
}

#[lang="exchange_free"]
pub fn free(p : *mut u8) {
	cpu().memory.free_frame(p);
}

#[no_mangle]
pub unsafe fn start64() -> ! {
	con::init(MutPhysAddr(0xb8000), 80, 25);
	con::clear();
	write("Hello World!\n");

	x86::lgdt(start32::Gdtr());

	let handlers = [(14, idt::Error(page_fault))];
	idt::build(&mut idt_table, handlers, generic_irq_handler);
	idt::load(&idt_table);

	mem::global.init(&*start32::MultiBootInfo(), start32::memory_start as uint);
	write("Memory initialized. ");
	mem::global.stat();

	let mut cpu = PerCpu::new();
	cpu.memory.test();
	mem::global.stat();

//	let mut i = 0;
//	loop {
//		con.writeUInt(i);
//		con.putc('\n');
//		i += 1;
//	}
	cpu.run();
}
<commit_msg>Fix assembly error with new clang<commit_after>#![allow(ctypes)]
#![no_std]
#![no_main]
#![feature(globs)]
#![feature(asm)]
// Adding pub mod (another fix for this warning) increases footprint, so just
// disble it instead.
#![allow(visible_private_types)]

extern crate core;

use con::write;
use start32::MultiBootInfo;
//use start32::OrigMultiBootInfo;
use start32::PhysAddr;
use start32::MutPhysAddr;
use x86::idt;

#[allow(dead_code)]
mod con;
mod mboot;
mod mem;
mod start32;
mod util;
mod x86;

static mut idt_table : [idt::Entry, ..48] = [idt::null_entry, ..48];

#[allow(dead_code)]
fn writeMBInfo(infop : *mboot::Info) {
	con::write("Multiboot info at ");
	con::writePtr(infop);
	con::putc('\n');

	let &info = unsafe { &*infop };
	con::write("Flags: ");
	con::writeHex(info.flags as uint);
	con::newline();

	if info.has(mboot::MemorySize) {
		con::writeUInt(info.mem_lower as uint);
		con::write("kB lower memory, ");
		con::writeUInt(info.mem_upper as uint);
		con::write("kB upper memory, ");
		con::writeUInt(((info.mem_lower + info.mem_upper + 1023) / 1024) as uint);
		con::write("MB total.\n");
	}
	// FIXME start32 doesn't copy this
	if info.has(mboot::CommandLine) {
		let cmdline : *u8 = PhysAddr(info.cmdline as uint);
		con::write("Command line @");
		con::writePtr(cmdline);
		con::write(" (");
		con::writeHex(info.cmdline as uint);
		con::write(") \"");
		con::writeCStr(cmdline);
		con::write("\"\n");
	}
}

pub fn generic_irq_handler(_vec : u8) {
}

pub fn page_fault(_error : u64) {
}

pub fn idle() -> ! {
	loop { unsafe { asm!("hlt"); } }
}

pub struct PerCpu {
	selfp : *mut PerCpu,
	memory : mem::PerCpu,
}

impl PerCpu {
	// TODO Always do a heap allocation so we can populate selfp with a proper
	// value
	fn new() -> PerCpu {
		PerCpu { selfp : 0 as *mut PerCpu, memory : mem::PerCpu::new() }
	}

	fn run(&mut self) -> ! {
		// TODO: Pop something from run queue, run it
		idle();
	}
}

// NB: One of the funky guarantees that Rust gives/requires is that there is
// at most one &mut reference to the same thing at any one time. This function
// can't quite guarantee that...
// This function also returns garbage as long as PerCpu::new doesn't fill in
// the selfp pointer.
pub fn cpu() -> &mut PerCpu {
	unsafe {
		let mut ret = 0;
		asm!("movq %gs:($0), $0" : "=r"(ret) : "0"(ret));
		return &mut *(ret as *mut PerCpu);
	}
}

#[lang="exchange_malloc"]
pub fn malloc(_size : uint) -> *mut u8 {
	return cpu().memory.alloc_frame_panic();
}

#[lang="exchange_free"]
pub fn free(p : *mut u8) {
	cpu().memory.free_frame(p);
}

#[no_mangle]
pub unsafe fn start64() -> ! {
	con::init(MutPhysAddr(0xb8000), 80, 25);
	con::clear();
	write("Hello World!\n");

	x86::lgdt(start32::Gdtr());

	let handlers = [(14, idt::Error(page_fault))];
	idt::build(&mut idt_table, handlers, generic_irq_handler);
	idt::load(&idt_table);

	mem::global.init(&*start32::MultiBootInfo(), start32::memory_start as uint);
	write("Memory initialized. ");
	mem::global.stat();

	let mut cpu = PerCpu::new();
	cpu.memory.test();
	mem::global.stat();

//	let mut i = 0;
//	loop {
//		con.writeUInt(i);
//		con.putc('\n');
//		i += 1;
//	}
	cpu.run();
}
<|endoftext|>


<commit_before>//! Common utilities for the generator and the build script for Qt crates.
//!
//!
//! See [README](https://github.com/rust-qt/cpp_to_rust)
//! for more information.

use log::debug;
use ritual_common::cpp_build_config::{
    CppBuildConfig, CppBuildConfigData, CppBuildPaths, CppLibraryType,
};
use ritual_common::errors::{bail, Result};
use ritual_common::string_utils::CaseOperations;
use ritual_common::target;
use ritual_common::utils::get_command_output;
use std::path::PathBuf;
use std::process::Command;

/// Makes a query to `qmake`.
fn run_qmake_string_query(property: &str) -> Result<String> {
    let result = get_command_output(Command::new("qmake").arg("-query").arg(property))?;
    Ok(result.trim().to_string())
}

/// Makes a query to `qmake` and interprets its output as a path.
fn run_qmake_query(property: &str) -> Result<PathBuf> {
    Ok(PathBuf::from(run_qmake_string_query(property)?))
}

/// Properties of a Qt installation
pub struct InstallationData {
    /// Qt version.
    pub qt_version: String,
    /// Path to the parent include directory of the installation.
    pub root_include_path: PathBuf,
    /// Path to the include directory of the library that is being processed.
    /// This is a direct subdirectory of `root_include_path`.
    pub lib_include_path: PathBuf,
    /// Path to the directory containing library files for the linker.
    pub lib_path: PathBuf,
    /// Path to the directory containing Qt documentation files.
    pub docs_path: PathBuf,
    /// If true, this Qt library was built as a MacOS framework.
    pub is_framework: bool,
}

/// Detects properties of current Qt installation using `qmake` command line utility.
pub fn get_installation_data(crate_name: &str) -> Result<InstallationData> {
    let qt_version = run_qmake_string_query("QT_VERSION")?;
    debug!("QT_VERSION = \"{}\"", qt_version);

    let qt_version_parsed = semver::Version::parse(&qt_version)?;
    if qt_version_parsed.major != 5 {
        bail!(
            "only Qt 5 is supported! \"{}\" is not supported",
            qt_version
        );
    }

    debug!("Detecting Qt directories");

    let root_include_path = run_qmake_query("QT_INSTALL_HEADERS")?;
    debug!("QT_INSTALL_HEADERS = \"{}\"", root_include_path.display());
    let lib_path = run_qmake_query("QT_INSTALL_LIBS")?;
    debug!("QT_INSTALL_LIBS = \"{}\"", lib_path.display());
    let docs_path = run_qmake_query("QT_INSTALL_DOCS")?;
    debug!("QT_INSTALL_DOCS = \"{}\"", docs_path.display());
    let folder_name = lib_folder_name(crate_name);
    let dir = root_include_path.join(&folder_name);
    if dir.exists() {
        Ok(InstallationData {
            root_include_path,
            lib_path,
            docs_path,
            lib_include_path: dir,
            is_framework: false,
            qt_version,
        })
    } else {
        let dir2 = lib_path.join(format!("{}.framework/Headers", folder_name));
        if dir2.exists() {
            Ok(InstallationData {
                root_include_path,
                lib_path,
                docs_path,
                lib_include_path: dir2,
                is_framework: true,
                qt_version,
            })
        } else {
            bail!(
                "extra header dir not found (tried: {}, {})",
                dir.display(),
                dir2.display()
            );
        }
    }
}

pub struct FullBuildConfig {
    pub installation_data: InstallationData,
    pub cpp_build_config: CppBuildConfig,
    pub cpp_build_paths: CppBuildPaths,
}

pub fn get_full_build_config(crate_name: &str) -> Result<FullBuildConfig> {
    let installation_data = get_installation_data(crate_name)?;
    let mut cpp_build_paths = CppBuildPaths::new();
    let mut cpp_build_config_data = CppBuildConfigData::new();
    {
        let mut apply_installation_data = |name: &str, data: &InstallationData| {
            cpp_build_paths.add_include_path(&data.root_include_path);
            cpp_build_paths.add_include_path(&data.lib_include_path);
            if data.is_framework {
                cpp_build_paths.add_framework_path(&data.lib_path);
                cpp_build_config_data.add_linked_framework(framework_name(name));
            } else {
                cpp_build_paths.add_lib_path(&data.lib_path);
                cpp_build_config_data.add_linked_lib(real_lib_name(name));
            }
        };

        apply_installation_data(crate_name, &installation_data);
        for dep in lib_dependencies(crate_name)? {
            let dep_data = get_installation_data(dep)?;
            apply_installation_data(dep, &dep_data);
        }
    }
    let mut cpp_build_config = CppBuildConfig::new();
    cpp_build_config.add(target::Condition::True, cpp_build_config_data);
    {
        let mut data = CppBuildConfigData::new();
        data.add_compiler_flag("-std=gnu++11");
        cpp_build_config.add(target::Condition::Env(target::Env::Msvc).negate(), data);
    }
    {
        let mut data = CppBuildConfigData::new();
        data.add_compiler_flag("-fPIC");
        // msvc and mingw don't need this
        cpp_build_config.add(target::Condition::OS(target::OS::Windows).negate(), data);
    }
    {
        let mut data = CppBuildConfigData::new();
        data.set_library_type(CppLibraryType::Shared);
        cpp_build_config.add(target::Condition::Env(target::Env::Msvc), data);
    }
    Ok(FullBuildConfig {
        installation_data,
        cpp_build_config,
        cpp_build_paths,
    })
}

/// Returns library name of the specified module as
/// should be passed to the linker, e.g. `"Qt5Core"`.
pub fn real_lib_name(crate_name: &str) -> String {
    let sublib_name = crate_name.replace("qt_", "");
    let sublib_name_capitalized = sublib_name.to_class_case();
    format!("Qt5{}", sublib_name_capitalized)
}

/// Returns name of the module's include directory, e.g. `"QtCore"`.
pub fn lib_folder_name(crate_name: &str) -> String {
    let sublib_name = crate_name.replace("qt_", "");
    let sublib_name_capitalized = sublib_name.to_class_case();
    format!("Qt{}", sublib_name_capitalized)
}

/// Returns MacOS framework name of the specified module as
/// should be passed to the linker, e.g. `"QtCore"`.
pub fn framework_name(crate_name: &str) -> String {
    let sublib_name = crate_name.replace("qt_", "");
    let sublib_name_capitalized = sublib_name.to_class_case();
    format!("Qt{}", sublib_name_capitalized)
}

pub fn all_crate_names() -> &'static [&'static str] {
    &[
        "qt_core",
        "qt_gui",
        "qt_widgets",
        "qt_ui_tools",
        "qt_3d_core",
        "qt_3d_render",
        "qt_3d_input",
        "qt_3d_logic",
        "qt_3d_extras",
    ]
}

/// Returns list of modules this module depends on.
pub fn lib_dependencies(crate_name: &str) -> Result<&'static [&'static str]> {
    Ok(match crate_name {
        "qt_core" => &[],
        "qt_gui" => &["qt_core"],
        "qt_widgets" => &["qt_core", "qt_gui"],
        "qt_3d_core" => &["qt_core", "qt_gui"],
        "qt_3d_render" | "qt_3d_input" | "qt_3d_logic" => &["qt_core", "qt_gui", "qt_3d_core"],
        "qt_3d_extras" => &[
            "qt_core",
            "qt_gui",
            "qt_3d_core",
            "qt_3d_render",
            "qt_3d_input",
            "qt_3d_logic",
        ],
        "qt_ui_tools" => &["qt_core", "qt_gui", "qt_widgets"],
        "moqt_core" => &[],
        "moqt_gui" => &["moqt_core"],
        _ => bail!("Unknown crate name: {}", crate_name),
    })
}
<commit_msg>fix qt library type in config<commit_after>//! Common utilities for the generator and the build script for Qt crates.
//!
//!
//! See [README](https://github.com/rust-qt/cpp_to_rust)
//! for more information.

use log::debug;
use ritual_common::cpp_build_config::{
    CppBuildConfig, CppBuildConfigData, CppBuildPaths, CppLibraryType,
};
use ritual_common::errors::{bail, Result};
use ritual_common::string_utils::CaseOperations;
use ritual_common::target;
use ritual_common::utils::get_command_output;
use std::path::PathBuf;
use std::process::Command;

/// Makes a query to `qmake`.
fn run_qmake_string_query(property: &str) -> Result<String> {
    let result = get_command_output(Command::new("qmake").arg("-query").arg(property))?;
    Ok(result.trim().to_string())
}

/// Makes a query to `qmake` and interprets its output as a path.
fn run_qmake_query(property: &str) -> Result<PathBuf> {
    Ok(PathBuf::from(run_qmake_string_query(property)?))
}

/// Properties of a Qt installation
pub struct InstallationData {
    /// Qt version.
    pub qt_version: String,
    /// Path to the parent include directory of the installation.
    pub root_include_path: PathBuf,
    /// Path to the include directory of the library that is being processed.
    /// This is a direct subdirectory of `root_include_path`.
    pub lib_include_path: PathBuf,
    /// Path to the directory containing library files for the linker.
    pub lib_path: PathBuf,
    /// Path to the directory containing Qt documentation files.
    pub docs_path: PathBuf,
    /// If true, this Qt library was built as a MacOS framework.
    pub is_framework: bool,
}

/// Detects properties of current Qt installation using `qmake` command line utility.
pub fn get_installation_data(crate_name: &str) -> Result<InstallationData> {
    let qt_version = run_qmake_string_query("QT_VERSION")?;
    debug!("QT_VERSION = \"{}\"", qt_version);

    let qt_version_parsed = semver::Version::parse(&qt_version)?;
    if qt_version_parsed.major != 5 {
        bail!(
            "only Qt 5 is supported! \"{}\" is not supported",
            qt_version
        );
    }

    debug!("Detecting Qt directories");

    let root_include_path = run_qmake_query("QT_INSTALL_HEADERS")?;
    debug!("QT_INSTALL_HEADERS = \"{}\"", root_include_path.display());
    let lib_path = run_qmake_query("QT_INSTALL_LIBS")?;
    debug!("QT_INSTALL_LIBS = \"{}\"", lib_path.display());
    let docs_path = run_qmake_query("QT_INSTALL_DOCS")?;
    debug!("QT_INSTALL_DOCS = \"{}\"", docs_path.display());
    let folder_name = lib_folder_name(crate_name);
    let dir = root_include_path.join(&folder_name);
    if dir.exists() {
        Ok(InstallationData {
            root_include_path,
            lib_path,
            docs_path,
            lib_include_path: dir,
            is_framework: false,
            qt_version,
        })
    } else {
        let dir2 = lib_path.join(format!("{}.framework/Headers", folder_name));
        if dir2.exists() {
            Ok(InstallationData {
                root_include_path,
                lib_path,
                docs_path,
                lib_include_path: dir2,
                is_framework: true,
                qt_version,
            })
        } else {
            bail!(
                "extra header dir not found (tried: {}, {})",
                dir.display(),
                dir2.display()
            );
        }
    }
}

pub struct FullBuildConfig {
    pub installation_data: InstallationData,
    pub cpp_build_config: CppBuildConfig,
    pub cpp_build_paths: CppBuildPaths,
}

pub fn get_full_build_config(crate_name: &str) -> Result<FullBuildConfig> {
    let installation_data = get_installation_data(crate_name)?;
    let mut cpp_build_paths = CppBuildPaths::new();
    let mut cpp_build_config_data = CppBuildConfigData::new();
    {
        let mut apply_installation_data = |name: &str, data: &InstallationData| {
            cpp_build_paths.add_include_path(&data.root_include_path);
            cpp_build_paths.add_include_path(&data.lib_include_path);
            if data.is_framework {
                cpp_build_paths.add_framework_path(&data.lib_path);
                cpp_build_config_data.add_linked_framework(framework_name(name));
            } else {
                cpp_build_paths.add_lib_path(&data.lib_path);
                cpp_build_config_data.add_linked_lib(real_lib_name(name));
            }
        };

        apply_installation_data(crate_name, &installation_data);
        for dep in lib_dependencies(crate_name)? {
            let dep_data = get_installation_data(dep)?;
            apply_installation_data(dep, &dep_data);
        }
    }
    let mut cpp_build_config = CppBuildConfig::new();
    cpp_build_config.add(target::Condition::True, cpp_build_config_data);
    {
        let mut data = CppBuildConfigData::new();
        data.add_compiler_flag("-std=gnu++11");
        cpp_build_config.add(target::Condition::Env(target::Env::Msvc).negate(), data);
    }
    {
        let mut data = CppBuildConfigData::new();
        data.add_compiler_flag("-fPIC");
        // msvc and mingw don't need this
        cpp_build_config.add(target::Condition::OS(target::OS::Windows).negate(), data);
    }
    {
        let mut data = CppBuildConfigData::new();
        data.set_library_type(CppLibraryType::Shared);
        cpp_build_config.add(target::Condition::Env(target::Env::Msvc), data);
    }
    {
        let mut data = CppBuildConfigData::new();
        data.set_library_type(CppLibraryType::Static);
        cpp_build_config.add(target::Condition::Env(target::Env::Msvc).negate(), data);
    }
    Ok(FullBuildConfig {
        installation_data,
        cpp_build_config,
        cpp_build_paths,
    })
}

/// Returns library name of the specified module as
/// should be passed to the linker, e.g. `"Qt5Core"`.
pub fn real_lib_name(crate_name: &str) -> String {
    let sublib_name = crate_name.replace("qt_", "");
    let sublib_name_capitalized = sublib_name.to_class_case();
    format!("Qt5{}", sublib_name_capitalized)
}

/// Returns name of the module's include directory, e.g. `"QtCore"`.
pub fn lib_folder_name(crate_name: &str) -> String {
    let sublib_name = crate_name.replace("qt_", "");
    let sublib_name_capitalized = sublib_name.to_class_case();
    format!("Qt{}", sublib_name_capitalized)
}

/// Returns MacOS framework name of the specified module as
/// should be passed to the linker, e.g. `"QtCore"`.
pub fn framework_name(crate_name: &str) -> String {
    let sublib_name = crate_name.replace("qt_", "");
    let sublib_name_capitalized = sublib_name.to_class_case();
    format!("Qt{}", sublib_name_capitalized)
}

pub fn all_crate_names() -> &'static [&'static str] {
    &[
        "qt_core",
        "qt_gui",
        "qt_widgets",
        "qt_ui_tools",
        "qt_3d_core",
        "qt_3d_render",
        "qt_3d_input",
        "qt_3d_logic",
        "qt_3d_extras",
    ]
}

/// Returns list of modules this module depends on.
pub fn lib_dependencies(crate_name: &str) -> Result<&'static [&'static str]> {
    Ok(match crate_name {
        "qt_core" => &[],
        "qt_gui" => &["qt_core"],
        "qt_widgets" => &["qt_core", "qt_gui"],
        "qt_3d_core" => &["qt_core", "qt_gui"],
        "qt_3d_render" | "qt_3d_input" | "qt_3d_logic" => &["qt_core", "qt_gui", "qt_3d_core"],
        "qt_3d_extras" => &[
            "qt_core",
            "qt_gui",
            "qt_3d_core",
            "qt_3d_render",
            "qt_3d_input",
            "qt_3d_logic",
        ],
        "qt_ui_tools" => &["qt_core", "qt_gui", "qt_widgets"],
        "moqt_core" => &[],
        "moqt_gui" => &["moqt_core"],
        _ => bail!("Unknown crate name: {}", crate_name),
    })
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate toml;

#[cfg(test)]
mod tests;

use std::collections::BTreeMap;
use std::env;
use std::error::Error;
use std::fs::File;
use std::io::{self, Read};
use std::net::SocketAddr;
use std::path::{Path, PathBuf};

pub use toml::Value;

#[derive(Deserialize)]
pub struct CargonautsConfig {
    host: Option<SocketAddr>,
    templates: Option<PathBuf>,
    assets: Option<PathBuf>,
    conns: Option<BTreeMap<String, BTreeMap<String, toml::Value>>>,
    env: Option<Env>,
}

impl CargonautsConfig {
    pub fn find_and_parse() -> Result<CargonautsConfig, Box<Error>> {
        let path: PathBuf = env::var("CARGO_MANIFEST_DIR")?.into();
        let file = File::open(path.join("Cargo.toml"))?;
        CargonautsConfig::from_file(file)
    }

    fn from_file(mut file: File) -> Result<CargonautsConfig, Box<Error>> {
        let mut buffer = String::new();
        file.read_to_string(&mut buffer)?;
        CargonautsConfig::from_toml(&buffer).map_err(Into::into)
    }

    fn from_toml(toml: &str) -> Result<CargonautsConfig, toml::de::Error> {
        let cargo: CargoToml = toml::from_str(toml)?;
        Ok(cargo.package.metadata.cargonauts)
    }

    pub fn host(&self) -> Option<SocketAddr> {
        self.host
    }

    pub fn templates(&self) -> Option<&Path> {
        self.templates.as_ref().map(|p| p.as_path())
    }

    pub fn assets(&self) -> Option<&Path> {
        self.assets.as_ref().map(|p| p.as_path())
    }

    pub fn conn_cfg(&self, conn: &str) -> Option<&BTreeMap<String, Value>> {
        self.conns.as_ref().and_then(|conns| conns.get(conn))
    }

    pub fn env(&self, profile: &str) -> Option<&BTreeMap<String, String>> {
        match profile {
            "dev"       => self.env.as_ref().and_then(|env| env.dev.as_ref()),
            "release"   => self.env.as_ref().and_then(|env| env.release.as_ref()),
            "test"      => self.env.as_ref().and_then(|env| env.test.as_ref()),
            _           => None,
        }
    }
}

#[derive(Deserialize)]
pub struct Env {
    dev: Option<BTreeMap<String, String>>,
    release: Option<BTreeMap<String, String>>,
    test: Option<BTreeMap<String, String>>
}

#[derive(Deserialize)]
struct CargoToml {
    package: Package,
}

#[derive(Deserialize)]
struct Package {
    metadata: Metadata,
}

#[derive(Deserialize)]
struct Metadata {
    cargonauts: CargonautsConfig,
}
<commit_msg>Unused import.<commit_after>#[macro_use]
extern crate serde_derive;
extern crate toml;

#[cfg(test)]
mod tests;

use std::collections::BTreeMap;
use std::env;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::net::SocketAddr;
use std::path::{Path, PathBuf};

pub use toml::Value;

#[derive(Deserialize)]
pub struct CargonautsConfig {
    host: Option<SocketAddr>,
    templates: Option<PathBuf>,
    assets: Option<PathBuf>,
    conns: Option<BTreeMap<String, BTreeMap<String, toml::Value>>>,
    env: Option<Env>,
}

impl CargonautsConfig {
    pub fn find_and_parse() -> Result<CargonautsConfig, Box<Error>> {
        let path: PathBuf = env::var("CARGO_MANIFEST_DIR")?.into();
        let file = File::open(path.join("Cargo.toml"))?;
        CargonautsConfig::from_file(file)
    }

    fn from_file(mut file: File) -> Result<CargonautsConfig, Box<Error>> {
        let mut buffer = String::new();
        file.read_to_string(&mut buffer)?;
        CargonautsConfig::from_toml(&buffer).map_err(Into::into)
    }

    fn from_toml(toml: &str) -> Result<CargonautsConfig, toml::de::Error> {
        let cargo: CargoToml = toml::from_str(toml)?;
        Ok(cargo.package.metadata.cargonauts)
    }

    pub fn host(&self) -> Option<SocketAddr> {
        self.host
    }

    pub fn templates(&self) -> Option<&Path> {
        self.templates.as_ref().map(|p| p.as_path())
    }

    pub fn assets(&self) -> Option<&Path> {
        self.assets.as_ref().map(|p| p.as_path())
    }

    pub fn conn_cfg(&self, conn: &str) -> Option<&BTreeMap<String, Value>> {
        self.conns.as_ref().and_then(|conns| conns.get(conn))
    }

    pub fn env(&self, profile: &str) -> Option<&BTreeMap<String, String>> {
        match profile {
            "dev"       => self.env.as_ref().and_then(|env| env.dev.as_ref()),
            "release"   => self.env.as_ref().and_then(|env| env.release.as_ref()),
            "test"      => self.env.as_ref().and_then(|env| env.test.as_ref()),
            _           => None,
        }
    }
}

#[derive(Deserialize)]
pub struct Env {
    dev: Option<BTreeMap<String, String>>,
    release: Option<BTreeMap<String, String>>,
    test: Option<BTreeMap<String, String>>
}

#[derive(Deserialize)]
struct CargoToml {
    package: Package,
}

#[derive(Deserialize)]
struct Package {
    metadata: Metadata,
}

#[derive(Deserialize)]
struct Metadata {
    cargonauts: CargonautsConfig,
}
<|endoftext|>


<commit_before>use crate::cli::Command;
use mprovision as mp;
use std::env;
use std::io::{self, Write};
use std::path::Path;
use std::path::PathBuf;
use std::time::{Duration, SystemTime};

mod cli;

fn main() {
    if let Err(e) = cli::parse(env::args()).and_then(run) {
        e.exit();
    }
}

fn run(command: cli::Command) -> Result<(), cli::Error> {
    match command {
        Command::List(cli::ListParams {
            text,
            expire_in_days,
            directory,
        }) => list(&text, expire_in_days, directory),
        Command::ShowUuid(cli::ShowUuidParams { uuid, directory }) => show_uuid(&uuid, directory),
        Command::ShowFile(cli::ShowFileParams { file }) => show_file(&file),
        Command::Remove(cli::RemoveParams { ids, directory }) => remove(&ids, directory),
        Command::Clean(cli::CleanParams { directory }) => clean(directory),
    }
}

fn list(
    text: &Option<String>,
    expires_in_days: Option<u64>,
    directory: Option<PathBuf>,
) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| {
            let date = expires_in_days
                .map(|days| SystemTime::now() + Duration::from_secs(days * 24 * 60 * 60));
            let filter_string = text.as_ref();
            let mut profiles = mp::filter(entries, |profile| match (date, filter_string) {
                (Some(date), Some(string)) => {
                    profile.info.expiration_date <= date && profile.info.contains(string)
                }
                (Some(date), _) => profile.info.expiration_date <= date,
                (_, Some(string)) => profile.info.contains(string),
                (_, _) => true,
            });
            profiles.sort_by(|a, b| a.info.creation_date.cmp(&b.info.creation_date));
            profiles
        })
        .and_then(|profiles| {
            let stdout = io::stdout();
            let mut stdout = stdout.lock();
            if profiles.is_empty() {
                Ok(())
            } else {
                for profile in &profiles {
                    writeln!(&mut stdout, "{}\n", profile.info.description())?;
                }
                Ok(())
            }
        })
}

fn show_uuid(uuid: &str, directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_uuid(&directory, &uuid)
                .and_then(|profile| mp::show(&profile.path).map(|xml| println!("{}", xml)))
        })
        .map_err(|err| err.into())
}

fn show_file(path: &Path) -> Result<(), cli::Error> {
    mp::show(&path)
        .map(|xml| println!("{}", xml))
        .map_err(|err| err.into())
}

fn remove(ids: &[String], directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_ids(&directory, &ids).and_then(|profiles| {
                for profile in profiles {
                    if mp::remove(&profile.path).is_ok() {
                        println!("\nRemoved: {}", profile.info.description());
                    } else {
                        println!("\nError while removing '{}'", profile.info.uuid);
                    }
                }
                Ok(())
            })
        })
        .map_err(|err| err.into())
}

fn clean(directory: Option<PathBuf>) -> Result<(), cli::Error> {
    fn concat(mut s1: String, s2: &str) -> String {
        s1.push_str(&s2);
        s1
    }

    let date = SystemTime::now();
    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| mp::filter(entries, |profile| profile.info.expiration_date <= date))
        .and_then(|profiles| {
            if profiles.is_empty() {
                println!("All provisioning profiles are valid");
                Ok(())
            } else {
                profiles
                    .iter()
                    .map(|profile| {
                        std::fs::remove_file(&profile.path)
                            .map(|_| format!("'{}' was removed\n", profile.info.uuid))
                            .map_err(|err| format!("'{}' {}\n", profile.info.uuid, err))
                    })
                    .fold(Ok(String::new()), |acc, s| match (acc, s) {
                        (Ok(acc), Ok(s)) => Ok(concat(acc, &s)),
                        (Ok(acc), Err(s)) | (Err(acc), Ok(s)) | (Err(acc), Err(s)) => {
                            Err(concat(acc, &s))
                        }
                    })
                    .map(|s| println!("{}", s))
                    .map_err(cli::Error::Custom)
            }
        })
}
<commit_msg>Refactor out chaining combinators for the list command<commit_after>use crate::cli::Command;
use mprovision as mp;
use std::env;
use std::io::{self, Write};
use std::path::Path;
use std::path::PathBuf;
use std::time::{Duration, SystemTime};

mod cli;

fn main() {
    if let Err(e) = cli::parse(env::args()).and_then(run) {
        e.exit();
    }
}

fn run(command: cli::Command) -> Result<(), cli::Error> {
    match command {
        Command::List(cli::ListParams {
            text,
            expire_in_days,
            directory,
        }) => list(&text, expire_in_days, directory),
        Command::ShowUuid(cli::ShowUuidParams { uuid, directory }) => show_uuid(&uuid, directory),
        Command::ShowFile(cli::ShowFileParams { file }) => show_file(&file),
        Command::Remove(cli::RemoveParams { ids, directory }) => remove(&ids, directory),
        Command::Clean(cli::CleanParams { directory }) => clean(directory),
    }
}

fn list(
    text: &Option<String>,
    expires_in_days: Option<u64>,
    directory: Option<PathBuf>,
) -> Result<(), cli::Error> {
    let dir = mp::with_directory(directory)?;
    let entries = mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>())?;
    let date =
        expires_in_days.map(|days| SystemTime::now() + Duration::from_secs(days * 24 * 60 * 60));
    let filter_string = text.as_ref();
    let mut profiles = mp::filter(entries, |profile| match (date, filter_string) {
        (Some(date), Some(string)) => {
            profile.info.expiration_date <= date && profile.info.contains(string)
        }
        (Some(date), _) => profile.info.expiration_date <= date,
        (_, Some(string)) => profile.info.contains(string),
        (_, _) => true,
    });
    profiles.sort_by(|a, b| a.info.creation_date.cmp(&b.info.creation_date));
    if profiles.is_empty() {
        Ok(())
    } else {
        let stdout = io::stdout();
        let mut stdout = stdout.lock();
        for profile in &profiles {
            writeln!(&mut stdout, "{}\n", profile.info.description())?;
        }
        Ok(())
    }
}

fn show_uuid(uuid: &str, directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_uuid(&directory, &uuid)
                .and_then(|profile| mp::show(&profile.path).map(|xml| println!("{}", xml)))
        })
        .map_err(|err| err.into())
}

fn show_file(path: &Path) -> Result<(), cli::Error> {
    mp::show(&path)
        .map(|xml| println!("{}", xml))
        .map_err(|err| err.into())
}

fn remove(ids: &[String], directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_ids(&directory, &ids).and_then(|profiles| {
                for profile in profiles {
                    if mp::remove(&profile.path).is_ok() {
                        println!("\nRemoved: {}", profile.info.description());
                    } else {
                        println!("\nError while removing '{}'", profile.info.uuid);
                    }
                }
                Ok(())
            })
        })
        .map_err(|err| err.into())
}

fn clean(directory: Option<PathBuf>) -> Result<(), cli::Error> {
    fn concat(mut s1: String, s2: &str) -> String {
        s1.push_str(&s2);
        s1
    }

    let date = SystemTime::now();
    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| mp::filter(entries, |profile| profile.info.expiration_date <= date))
        .and_then(|profiles| {
            if profiles.is_empty() {
                println!("All provisioning profiles are valid");
                Ok(())
            } else {
                profiles
                    .iter()
                    .map(|profile| {
                        std::fs::remove_file(&profile.path)
                            .map(|_| format!("'{}' was removed\n", profile.info.uuid))
                            .map_err(|err| format!("'{}' {}\n", profile.info.uuid, err))
                    })
                    .fold(Ok(String::new()), |acc, s| match (acc, s) {
                        (Ok(acc), Ok(s)) => Ok(concat(acc, &s)),
                        (Ok(acc), Err(s)) | (Err(acc), Ok(s)) | (Err(acc), Err(s)) => {
                            Err(concat(acc, &s))
                        }
                    })
                    .map(|s| println!("{}", s))
                    .map_err(cli::Error::Custom)
            }
        })
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate getopts;
extern crate miri;
extern crate rustc;
extern crate rustc_driver;
extern crate env_logger;
extern crate log_settings;
extern crate syntax;
#[macro_use] extern crate log;

use miri::{
    EvalContext,
    CachedMir,
    step,
    EvalError,
    Frame,
};
use rustc::session::Session;
use rustc_driver::{driver, CompilerCalls};
use rustc::ty::{TyCtxt, subst};
use rustc::mir::mir_map::MirMap;
use rustc::hir::def_id::DefId;

struct MiriCompilerCalls;

impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
    fn build_controller(
        &mut self,
        _: &Session,
        _: &getopts::Matches
    ) -> driver::CompileController<'a> {
        let mut control = driver::CompileController::basic();

        control.after_analysis.callback = Box::new(|state| {
            state.session.abort_if_errors();
            interpret_start_points(state.tcx.unwrap(), state.mir_map.unwrap());
        });

        control
    }
}

fn interpret_start_points<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    mir_map: &MirMap<'tcx>,
) {
    let initial_indentation = ::log_settings::settings().indentation;
    for (&id, mir) in &mir_map.map {
        for attr in tcx.map.attrs(id) {
            use syntax::attr::AttrMetaMethods;
            if attr.check_name("miri_run") {
                let item = tcx.map.expect_item(id);

                ::log_settings::settings().indentation = initial_indentation;

                debug!("Interpreting: {}", item.name);

                let mut ecx = EvalContext::new(tcx, mir_map);
                let substs = tcx.mk_substs(subst::Substs::empty());
                let return_ptr = ecx.alloc_ret_ptr(mir.return_ty, substs);

                ecx.push_stack_frame(tcx.map.local_def_id(id), mir.span, CachedMir::Ref(mir), substs, return_ptr);

                loop {
                    match step(&mut ecx) {
                        Ok(true) => {}
                        Ok(false) => {
                            match return_ptr {
                                Some(ptr) => if log_enabled!(::log::LogLevel::Debug) {
                                    ecx.memory().dump(ptr.alloc_id);
                                },
                                None => warn!("diverging function returned"),
                            }
                            break;
                        }
                        // FIXME: diverging functions can end up here in some future miri
                        Err(e) => {
                            report(tcx, &ecx, e);
                            break;
                        }
                    }
                }
            }
        }
    }
}

fn report(tcx: TyCtxt, ecx: &EvalContext, e: EvalError) {
    let frame = ecx.stack().last().expect("stackframe was empty");
    let block = &frame.mir.basic_blocks()[frame.next_block];
    let span = if frame.stmt < block.statements.len() {
        block.statements[frame.stmt].source_info.span
    } else {
        block.terminator().source_info.span
    };
    let mut err = tcx.sess.struct_span_err(span, &e.to_string());
    for &Frame { def_id, substs, span, .. } in ecx.stack().iter().rev() {
        // FIXME(solson): Find a way to do this without this Display impl hack.
        use rustc::util::ppaux;
        use std::fmt;
        struct Instance<'tcx>(DefId, &'tcx subst::Substs<'tcx>);
        impl<'tcx> fmt::Display for Instance<'tcx> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                ppaux::parameterized(f, self.1, self.0, ppaux::Ns::Value, &[],
                    |tcx| Some(tcx.lookup_item_type(self.0).generics))
            }
        }
        err.span_note(span, &format!("inside call to {}", Instance(def_id, substs)));
    }
    err.emit();
}

fn main() {
    init_logger();
    let args: Vec<String> = std::env::args().collect();
    rustc_driver::run_compiler(&args, &mut MiriCompilerCalls);
}

fn init_logger() {
    const NSPACES: usize = 40;
    let format = |record: &log::LogRecord| {
        // prepend spaces to indent the final string
        let indentation = log_settings::settings().indentation;
        format!("{lvl}:{module}{depth:2}{indent:<indentation$} {text}",
            lvl = record.level(),
            module = record.location().module_path(),
            depth = indentation / NSPACES,
            indentation = indentation % NSPACES,
            indent = "",
            text = record.args())
    };

    let mut builder = env_logger::LogBuilder::new();
    builder.format(format).filter(None, log::LogLevelFilter::Info);

    if std::env::var("MIRI_LOG").is_ok() {
        builder.parse(&std::env::var("MIRI_LOG").unwrap());
    }

    builder.init().unwrap();
}
<commit_msg>Get the sysroot (like compiletest) in Miri itself.<commit_after>#![feature(rustc_private)]

extern crate getopts;
extern crate miri;
extern crate rustc;
extern crate rustc_driver;
extern crate env_logger;
extern crate log_settings;
extern crate syntax;
#[macro_use] extern crate log;

use miri::{
    EvalContext,
    CachedMir,
    step,
    EvalError,
    Frame,
};
use rustc::session::Session;
use rustc_driver::{driver, CompilerCalls};
use rustc::ty::{TyCtxt, subst};
use rustc::mir::mir_map::MirMap;
use rustc::hir::def_id::DefId;

struct MiriCompilerCalls;

impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
    fn build_controller(
        &mut self,
        _: &Session,
        _: &getopts::Matches
    ) -> driver::CompileController<'a> {
        let mut control = driver::CompileController::basic();

        control.after_analysis.callback = Box::new(|state| {
            state.session.abort_if_errors();
            interpret_start_points(state.tcx.unwrap(), state.mir_map.unwrap());
        });

        control
    }
}

fn interpret_start_points<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    mir_map: &MirMap<'tcx>,
) {
    let initial_indentation = ::log_settings::settings().indentation;
    for (&id, mir) in &mir_map.map {
        for attr in tcx.map.attrs(id) {
            use syntax::attr::AttrMetaMethods;
            if attr.check_name("miri_run") {
                let item = tcx.map.expect_item(id);

                ::log_settings::settings().indentation = initial_indentation;

                debug!("Interpreting: {}", item.name);

                let mut ecx = EvalContext::new(tcx, mir_map);
                let substs = tcx.mk_substs(subst::Substs::empty());
                let return_ptr = ecx.alloc_ret_ptr(mir.return_ty, substs);

                ecx.push_stack_frame(tcx.map.local_def_id(id), mir.span, CachedMir::Ref(mir), substs, return_ptr);

                loop {
                    match step(&mut ecx) {
                        Ok(true) => {}
                        Ok(false) => {
                            match return_ptr {
                                Some(ptr) => if log_enabled!(::log::LogLevel::Debug) {
                                    ecx.memory().dump(ptr.alloc_id);
                                },
                                None => warn!("diverging function returned"),
                            }
                            break;
                        }
                        // FIXME: diverging functions can end up here in some future miri
                        Err(e) => {
                            report(tcx, &ecx, e);
                            break;
                        }
                    }
                }
            }
        }
    }
}

fn report(tcx: TyCtxt, ecx: &EvalContext, e: EvalError) {
    let frame = ecx.stack().last().expect("stackframe was empty");
    let block = &frame.mir.basic_blocks()[frame.next_block];
    let span = if frame.stmt < block.statements.len() {
        block.statements[frame.stmt].source_info.span
    } else {
        block.terminator().source_info.span
    };
    let mut err = tcx.sess.struct_span_err(span, &e.to_string());
    for &Frame { def_id, substs, span, .. } in ecx.stack().iter().rev() {
        // FIXME(solson): Find a way to do this without this Display impl hack.
        use rustc::util::ppaux;
        use std::fmt;
        struct Instance<'tcx>(DefId, &'tcx subst::Substs<'tcx>);
        impl<'tcx> fmt::Display for Instance<'tcx> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                ppaux::parameterized(f, self.1, self.0, ppaux::Ns::Value, &[],
                    |tcx| Some(tcx.lookup_item_type(self.0).generics))
            }
        }
        err.span_note(span, &format!("inside call to {}", Instance(def_id, substs)));
    }
    err.emit();
}

fn init_logger() {
    const NSPACES: usize = 40;
    let format = |record: &log::LogRecord| {
        // prepend spaces to indent the final string
        let indentation = log_settings::settings().indentation;
        format!("{lvl}:{module}{depth:2}{indent:<indentation$} {text}",
            lvl = record.level(),
            module = record.location().module_path(),
            depth = indentation / NSPACES,
            indentation = indentation % NSPACES,
            indent = "",
            text = record.args())
    };

    let mut builder = env_logger::LogBuilder::new();
    builder.format(format).filter(None, log::LogLevelFilter::Info);

    if std::env::var("MIRI_LOG").is_ok() {
        builder.parse(&std::env::var("MIRI_LOG").unwrap());
    }

    builder.init().unwrap();
}

fn find_sysroot() -> String {
    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
            .to_owned(),
    }
}

fn main() {
    init_logger();
    let mut args: Vec<String> = std::env::args().collect();

    let sysroot_flag = String::from("--sysroot");
    if !args.contains(&sysroot_flag) {
        args.push(sysroot_flag);
        args.push(find_sysroot());
    }

    rustc_driver::run_compiler(&args, &mut MiriCompilerCalls);
}
<|endoftext|>


<commit_before>#[macro_use]
pub mod macros;
pub mod error;
pub mod arguments;
pub mod configuration;
pub mod engines;

extern crate std;
extern crate toml;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::collections::HashMap;
use toml::Value;
use bins::error::*;
use bins::arguments::Arguments;
use bins::engines::Engine;
use hyper::Url;

#[derive(Clone)]
pub struct PasteFile {
  pub name: String,
  pub data: String
}

impl PasteFile {
  fn new(name: String, data: String) -> Self {
    PasteFile {
      name: name,
      data: data
    }
  }
}

pub struct Bins {
  pub config: Value,
  pub arguments: Arguments
}

impl Bins {
  pub fn new(config: Value, arguments: Arguments) -> Self {
    Bins {
      config: config,
      arguments: arguments
    }
  }

  pub fn get_engine(&self) -> Result<&Box<Engine>> {
    let service = match self.arguments.service {
      Some(ref s) => s,
      None => return Err("no service was specified and no default service was set.".into()),
    };
    match engines::get_engine_by_name(service) {
      Some(engine) => Ok(engine),
      None => return Err(format!("unknown service \"{}\"", service).into()),
    }
  }

  fn read_file<P: AsRef<Path>>(&self, p: P) -> Result<String> {
    let path = p.as_ref();
    let name = some_or_err!(path.to_str(), "file name was not valid unicode".into());
    if !path.exists() {
      return Err(format!("{} does not exist", name).into());
    }
    if !path.is_file() {
      return Err(format!("{} is not a file", name).into());
    }
    let mut file = match File::open(path) {
      Ok(f) => f,
      Err(e) => {
        return Err(format!("could not open {}: {}", name, e).into());
      }
    };
    let mut s = String::new();
    if let Err(e) = file.read_to_string(&mut s) {
      return Err(format!("could not read {}: {}", name, e).into());
    }
    Ok(s)
  }

  fn read_file_to_pastefile<P: AsRef<Path>>(&self, p: P) -> Result<PasteFile> {
    let path = p.as_ref();
    match self.read_file(path) {
      Ok(s) => {
        let n = match path.file_name() {
          Some(x) => x,
          None => return Err("not a valid file name".into()),
        };
        Ok(PasteFile::new(n.to_string_lossy().into_owned(), s))
      }
      Err(s) => Err(s),
    }
  }

  pub fn get_to_paste(&self) -> Result<Vec<PasteFile>> {
    let arguments = &self.arguments;
    let message = &arguments.message;
    let paste_files: Vec<PasteFile> = if message.is_some() {
      vec![PasteFile::new(String::from("message"), message.clone().unwrap())]
    } else if !arguments.files.is_empty() {
      let files = arguments.files.clone();
      let results = files.iter()
        .map(|s| Path::new(s))
        .map(|p| self.read_file_to_pastefile(p))
        .map(|r| r.map_err(|e| e.iter().map(|x| x.to_string()).collect::<Vec<_>>().join("\n")))
        .collect::<Vec<_>>();
      for res in results.iter().cloned() {
        if res.is_err() {
          return Err(res.err().unwrap().into());
        }
      }
      let mut pastes =
        results.iter().cloned().map(|r| r.unwrap()).filter(|p| !p.data.trim().is_empty()).collect::<Vec<_>>();
      self.handle_duplicate_file_names(&mut pastes);
      pastes
    } else {
      let mut buffer = String::new();
      if let Err(e) = std::io::stdin().read_to_string(&mut buffer) {
        return Err(format!("error reading stdin: {}", e).into());
      }
      vec![PasteFile::new(String::from("stdin"), buffer)]
    };
    if paste_files.iter().filter(|p| !p.data.trim().is_empty()).count() < 1 {
      return Err("no files (or all empty files) to paste".into());
    }
    Ok(paste_files)
  }

  fn handle_duplicate_file_names(&self, pastes: &mut Vec<PasteFile>) {
    let mut names_map: HashMap<String, i32> = HashMap::new();
    for mut paste in pastes {
      let name = paste.name.clone();
      if names_map.contains_key(&name) {
        let parts = name.rsplit('.');
        let (beginning, end) = if parts.clone().count() > 1 {
          let mut beginning_parts = parts.clone().skip(1).collect::<Vec<_>>();
          beginning_parts.reverse();
          let beginning = beginning_parts.join(".");
          let end = parts.take(1).next().map_or(String::new(), |s| String::from(".") + s);
          (beginning, end)
        } else {
          (name.clone(), String::from(""))
        };
        let number = names_map.entry(name.clone()).or_insert(1);
        paste.name = format!("{}_{}{}", beginning, number, end);
        *number += 1;
      }
      names_map.entry(name.clone()).or_insert(1);
    }
  }

  fn get_engine_for_url<'a>(&'a self, url: &'a Url) -> Result<&Box<Engine>> {
    let domain = some_or_err!(url.domain(), "input url had no domain".into());
    let engine = some_or_err!(engines::get_engine_by_domain(domain),
                              format!("could not find a bin for domain {}", domain).into());
    Ok(engine)
  }

  fn get_raw(&self, url_string: &str) -> Result<String> {
    // can't use try!() because url::parser is private, and ParseError is at url::parser::ParseError
    let mut url = match Url::parse(url_string.as_ref()) {
      Ok(u) => u,
      Err(e) => return Err(e.to_string().into()),
    };
    let url_clone = url.clone();
    let engine = try!(self.get_engine_for_url(&url_clone));
    engine.get_raw(self, &mut url)
  }

  pub fn get_output(&self) -> Result<String> {
    if let Some(ref input) = self.arguments.input {
      return self.get_raw(input);
    }
    let to_paste = try!(self.get_to_paste());
    let engine = try!(self.get_engine());
    engine.upload(self, &to_paste)
  }
}
<commit_msg>style(bins): use simpler constructs<commit_after>#[macro_use]
pub mod macros;
pub mod error;
pub mod arguments;
pub mod configuration;
pub mod engines;

extern crate std;
extern crate toml;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::collections::HashMap;
use toml::Value;
use bins::error::*;
use bins::arguments::Arguments;
use bins::engines::Engine;
use hyper::Url;

#[derive(Clone)]
pub struct PasteFile {
  pub name: String,
  pub data: String
}

impl PasteFile {
  fn new(name: String, data: String) -> Self {
    PasteFile {
      name: name,
      data: data
    }
  }
}

pub struct Bins {
  pub config: Value,
  pub arguments: Arguments
}

impl Bins {
  pub fn new(config: Value, arguments: Arguments) -> Self {
    Bins {
      config: config,
      arguments: arguments
    }
  }

  pub fn get_engine(&self) -> Result<&Box<Engine>> {
    let service = match self.arguments.service {
      Some(ref s) => s,
      None => return Err("no service was specified and no default service was set.".into()),
    };
    match engines::get_engine_by_name(service) {
      Some(engine) => Ok(engine),
      None => return Err(format!("unknown service \"{}\"", service).into()),
    }
  }

  fn read_file<P: AsRef<Path>>(&self, p: P) -> Result<String> {
    let path = p.as_ref();
    let name = some_or_err!(path.to_str(), "file name was not valid unicode".into());
    if !path.exists() {
      return Err(format!("{} does not exist", name).into());
    }
    if !path.is_file() {
      return Err(format!("{} is not a file", name).into());
    }
    let mut file = match File::open(path) {
      Ok(f) => f,
      Err(e) => return Err(format!("could not open {}: {}", name, e).into()),
    };
    let mut s = String::new();
    if let Err(e) = file.read_to_string(&mut s) {
      return Err(format!("could not read {}: {}", name, e).into());
    }
    Ok(s)
  }

  fn read_file_to_pastefile<P: AsRef<Path>>(&self, p: P) -> Result<PasteFile> {
    let path = p.as_ref();
    match self.read_file(path) {
      Ok(s) => {
        let n = some_or_err!(path.file_name(), "not a valid file name".into());
        Ok(PasteFile::new(n.to_string_lossy().into_owned(), s))
      }
      Err(s) => Err(s),
    }
  }

  pub fn get_to_paste(&self) -> Result<Vec<PasteFile>> {
    let arguments = &self.arguments;
    let message = &arguments.message;
    let paste_files: Vec<PasteFile> = if message.is_some() {
      vec![PasteFile::new(String::from("message"), message.clone().unwrap())]
    } else if !arguments.files.is_empty() {
      let files = arguments.files.clone();
      let results = files.iter()
        .map(|s| Path::new(s))
        .map(|p| self.read_file_to_pastefile(p))
        .map(|r| r.map_err(|e| e.iter().map(|x| x.to_string()).collect::<Vec<_>>().join("\n")))
        .collect::<Vec<_>>();
      for res in results.iter().cloned() {
        if res.is_err() {
          return Err(res.err().unwrap().into());
        }
      }
      let mut pastes =
        results.iter().cloned().map(|r| r.unwrap()).filter(|p| !p.data.trim().is_empty()).collect::<Vec<_>>();
      self.handle_duplicate_file_names(&mut pastes);
      pastes
    } else {
      let mut buffer = String::new();
      if let Err(e) = std::io::stdin().read_to_string(&mut buffer) {
        return Err(format!("error reading stdin: {}", e).into());
      }
      vec![PasteFile::new(String::from("stdin"), buffer)]
    };
    if paste_files.iter().filter(|p| !p.data.trim().is_empty()).count() < 1 {
      return Err("no files (or all empty files) to paste".into());
    }
    Ok(paste_files)
  }

  fn handle_duplicate_file_names(&self, pastes: &mut Vec<PasteFile>) {
    let mut names_map: HashMap<String, i32> = HashMap::new();
    for mut paste in pastes {
      let name = paste.name.clone();
      if names_map.contains_key(&name) {
        let parts = name.rsplit('.');
        let (beginning, end) = if parts.clone().count() > 1 {
          let mut beginning_parts = parts.clone().skip(1).collect::<Vec<_>>();
          beginning_parts.reverse();
          let beginning = beginning_parts.join(".");
          let end = parts.take(1).next().map_or(String::new(), |s| String::from(".") + s);
          (beginning, end)
        } else {
          (name.clone(), String::from(""))
        };
        let number = names_map.entry(name.clone()).or_insert(1);
        paste.name = format!("{}_{}{}", beginning, number, end);
        *number += 1;
      }
      names_map.entry(name.clone()).or_insert(1);
    }
  }

  fn get_engine_for_url<'a>(&'a self, url: &'a Url) -> Result<&Box<Engine>> {
    let domain = some_or_err!(url.domain(), "input url had no domain".into());
    let engine = some_or_err!(engines::get_engine_by_domain(domain),
                              format!("could not find a bin for domain {}", domain).into());
    Ok(engine)
  }

  fn get_raw(&self, url_string: &str) -> Result<String> {
    // can't use try!() because url::parser is private, and ParseError is at url::parser::ParseError
    let mut url = match Url::parse(url_string.as_ref()) {
      Ok(u) => u,
      Err(e) => return Err(e.to_string().into()),
    };
    let url_clone = url.clone();
    let engine = try!(self.get_engine_for_url(&url_clone));
    engine.get_raw(self, &mut url)
  }

  pub fn get_output(&self) -> Result<String> {
    if let Some(ref input) = self.arguments.input {
      return self.get_raw(input);
    }
    let to_paste = try!(self.get_to_paste());
    let engine = try!(self.get_engine());
    engine.upload(self, &to_paste)
  }
}
<|endoftext|>


<commit_before>use std::sync::{Arc, RwLock};
use std::option::Option;

use uuid::Uuid;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

pub struct CellFormat {
    name: String,
    type_: CellType
}

pub struct RecFormat {
    cols: Vec<CellFormat>
}

trait Metaformat<T> {
    fn construct(format_: CellFormat) -> T;
}

pub struct Cell {
    value: CellType
}

impl Metaformat<Cell> for Cell {
    fn construct(format_: CellFormat) -> Cell {
        return match format_.type_ {
            CellType::Int32(_) => Cell { value: CellType::Int32(None) },
            CellType::Int64(_) => Cell { value: CellType::Int64(None) },
            CellType::Text(_) => Cell { value: CellType::Text(None) }
        }
    }
}

trait Container<T> {
    fn size(&self) -> usize;
    fn push(&mut self, item: T);
    //fn remove
}

pub struct Rec {
    pub guid: Uuid,
    pub cells: Vec<Cell>,
    pub format: Arc<RwLock<RecFormat>>
}

pub fn construct_rec(format: Arc<RwLock<RecFormat>>) -> Rec {
    let cells = format.read().unwrap().cols.iter().map(|x| x.type_).collect::<Vec<CellType>>();
    return Rec{guid: Uuid::new_v4(),
        cells: cells,
        format: format}
}

impl Container<Cell> for Rec {

    fn size(&self) -> usize {
        return self.cells.len();
    }

    fn push(&mut self, item: Cell) {
        self.cells.push(item);
    }
}

pub struct Table {
    pub name: String,
    pub rows: Vec<Rec>,
    pub format: Arc<RwLock<RecFormat>>
}

impl Container<Rec> for Table {
    fn size(&self) -> usize {
        return self.rows.len();
    }

    fn push(&mut self, item: Rec) {
        self.rows.push(item);
    }
}
<commit_msg>Remove unnecessary cell type wrapper<commit_after>use std::sync::{Arc, RwLock};
use std::option::Option;

use uuid::Uuid;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

pub struct CellFormat {
    name: String,
    type_: CellType
}

pub struct RecFormat {
    cols: Vec<CellFormat>
}

trait Metaformat<T> {
    fn construct(format_: CellFormat) -> T;
}

//impl Metaformat<Cell> for Cell {
//    fn construct(format_: CellFormat) -> Cell {
//        return match format_.type_ {
//            CellType::Int32(_) => Cell { value: CellType::Int32(None) },
//            CellType::Int64(_) => Cell { value: CellType::Int64(None) },
//            CellType::Text(_) => Cell { value: CellType::Text(None) }
//        }
//    }
//}

trait Container<T> {
    fn size(&self) -> usize;
    fn push(&mut self, item: T);
    //fn remove
}

pub struct Rec {
    pub guid: Uuid,
    pub cells: Vec<CellType>,
    pub format: Arc<RwLock<RecFormat>>
}

pub fn construct_rec(format: Arc<RwLock<RecFormat>>) -> Rec {
    let cells = format.read().unwrap().cols.iter().map(|x| x.type_).collect::<Vec<CellType>>();
    return Rec{guid: Uuid::new_v4(),
        cells: cells,
        format: format}
}

//impl Container<Cell> for Rec {

//    fn size(&self) -> usize {
//        return self.cells.len();
//    }

//    fn push(&mut self, item: Cell) {
//        self.cells.push(item);
//    }
//}

pub struct Table {
    pub name: String,
    pub rows: Vec<Rec>,
    pub format: Arc<RwLock<RecFormat>>
}

impl Container<Rec> for Table {
    fn size(&self) -> usize {
        return self.rows.len();
    }

    fn push(&mut self, item: Rec) {
        self.rows.push(item);
    }
}
<|endoftext|>