<commit_before>extern crate protobuf;
extern crate rand;

use std::fs::File;
use std::path::Path;

use rand::Rng;
use rand::SeedableRng;
use rand::StdRng;

use perftest_data::PerftestData;
use protobuf::Message;
use std::time::Instant;

mod perftest_data;

fn measure_ns<R, F: FnMut() -> R>(mut f: F) -> (u64, R) {
    let start = Instant::now();
    let r = f();
    (start.elapsed().as_nanos() as u64, r)
}

fn measure_and_print<R, F: FnMut() -> R>(title: &str, iter: u64, f: F) -> R {
    let (ns, r) = measure_ns(f);
    let ns_per_iter = ns / iter;
    println!("{}: {} ns per iter", title, ns_per_iter);
    r
}

struct TestRunner {
    data_size: u32,
    selected: Option<String>,
    any_matched: bool,
}

impl TestRunner {
    fn run_test<M: Message + Clone + PartialEq>(&self, name: &str, data: &[M]) {
        assert!(data.len() > 0, "empty string for test: {}", name);

        let mut rng: StdRng = SeedableRng::from_seed([
            10, 20, 30, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0,
        ]);

        let mut random_data: Vec<M> = Vec::new();

        let mut total_size = 0;
        while total_size < self.data_size {
            let ref item = data[rng.gen_range(0, data.len())];
            random_data.push(item.clone());
            total_size += item.compute_size();
        }

        let mut buf = Vec::new();
        measure_and_print(
            &format!("{}: write", name),
            random_data.len() as u64,
            || {
                for m in &random_data {
                    m.write_length_delimited_to_vec(&mut buf).unwrap();
                }
            },
        );

        let read_data =
            measure_and_print(&format!("{}: read", name), random_data.len() as u64, || {
                let mut r = Vec::new();
                let mut coded_input_stream = protobuf::CodedInputStream::from_bytes(&buf);
                while !coded_input_stream.eof().unwrap() {
                    r.push(coded_input_stream.read_message().unwrap());
                }
                r
            });

        assert_eq!(random_data, read_data);

        let merged = measure_and_print(
            &format!("{}: read reuse", name),
            random_data.len() as u64,
            || {
                let mut coded_input_stream = protobuf::CodedInputStream::from_bytes(&buf);
                let mut msg: M = Message::new();
                let mut count = 0;
                while !coded_input_stream.eof().unwrap() {
                    msg.clear();
                    coded_input_stream.merge_message(&mut msg).unwrap();
                    count += 1;
                }
                count
            },
        );

        assert_eq!(random_data.len(), merged);
    }

    fn test<M: Message + Clone + PartialEq>(&mut self, name: &str, data: &[M]) {
        if self.selected.as_ref().map(|s| *s == name).unwrap_or(true) {
            self.run_test(name, data);
            self.any_matched = true;
        }
    }

    fn check(&self) {
        if !self.any_matched {
            let name = self.selected.as_ref().map(|s| &s[..]).unwrap_or("bug");
            panic!("no tests found with name {}", name);
        }
    }
}

fn main() {
    let args = std::env::args().collect::<Vec<_>>();
    if args.len() > 3 {
        panic!("usage: {} [data_size] [test]", args[0])
    }
    let data_size = args
        .iter()
        .nth(1)
        .map(|x| x.parse().unwrap())
        .unwrap_or(1000000);
    let selected = args.iter().nth(2).cloned();

    let mut runner = TestRunner {
        selected: selected,
        any_matched: false,
        data_size: data_size,
    };

    let mut is = File::open(&Path::new("perftest_data.pbbin")).unwrap();
    let test_data = protobuf::parse_from_reader::<PerftestData>(&mut is).unwrap();

    runner.test("test1", &test_data.test1);
    runner.test("test_repeated_bool", &test_data.test_repeated_bool);
    runner.test(
        "test_repeated_packed_int32",
        &test_data.test_repeated_packed_int32,
    );
    runner.test("test_repeated_messages", &test_data.test_repeated_messages);
    runner.test("test_optional_messages", &test_data.test_optional_messages);
    runner.test("test_strings", &test_data.test_strings);
    runner.test("test_small_bytearrays", &test_data.test_small_bytearrays);
    runner.test("test_large_bytearrays", &test_data.test_large_bytearrays);
    runner.check();
}
<commit_msg>Fix compilation<commit_after>extern crate protobuf;
extern crate rand;

use std::fs::File;
use std::path::Path;

use rand::Rng;
use rand::SeedableRng;
use rand::StdRng;

use perftest_data::PerftestData;
use protobuf::Message;
use std::time::Instant;

mod perftest_data;

fn measure_ns<R, F: FnMut() -> R>(mut f: F) -> (u64, R) {
    let start = Instant::now();
    let r = f();
    (start.elapsed().as_nanos() as u64, r)
}

fn measure_and_print<R, F: FnMut() -> R>(title: &str, iter: u64, f: F) -> R {
    let (ns, r) = measure_ns(f);
    let ns_per_iter = ns / iter;
    println!("{}: {} ns per iter", title, ns_per_iter);
    r
}

struct TestRunner {
    data_size: u32,
    selected: Option<String>,
    any_matched: bool,
}

impl TestRunner {
    fn run_test<M: Message + Clone + PartialEq>(&self, name: &str, data: &[M]) {
        assert!(data.len() > 0, "empty string for test: {}", name);

        let mut rng: StdRng = SeedableRng::from_seed([
            10, 20, 30, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0,
        ]);

        let mut random_data: Vec<M> = Vec::new();

        let mut total_size = 0;
        while total_size < self.data_size {
            let ref item = data[rng.gen_range(0, data.len())];
            random_data.push(item.clone());
            total_size += item.compute_size();
        }

        let mut buf = Vec::new();
        measure_and_print(
            &format!("{}: write", name),
            random_data.len() as u64,
            || {
                for m in &random_data {
                    m.write_length_delimited_to_vec(&mut buf).unwrap();
                }
            },
        );

        let read_data =
            measure_and_print(&format!("{}: read", name), random_data.len() as u64, || {
                let mut r = Vec::new();
                let mut coded_input_stream = protobuf::CodedInputStream::from_bytes(&buf);
                while !coded_input_stream.eof().unwrap() {
                    r.push(coded_input_stream.read_message().unwrap());
                }
                r
            });

        assert_eq!(random_data, read_data);

        let merged = measure_and_print(
            &format!("{}: read reuse", name),
            random_data.len() as u64,
            || {
                let mut coded_input_stream = protobuf::CodedInputStream::from_bytes(&buf);
                let mut msg: M = Message::new();
                let mut count = 0;
                while !coded_input_stream.eof().unwrap() {
                    msg.clear();
                    coded_input_stream.merge_message(&mut msg).unwrap();
                    count += 1;
                }
                count
            },
        );

        assert_eq!(random_data.len(), merged);
    }

    fn test<M: Message + Clone + PartialEq>(&mut self, name: &str, data: &[M]) {
        if self.selected.as_ref().map(|s| *s == name).unwrap_or(true) {
            self.run_test(name, data);
            self.any_matched = true;
        }
    }

    fn check(&self) {
        if !self.any_matched {
            let name = self.selected.as_ref().map(|s| &s[..]).unwrap_or("bug");
            panic!("no tests found with name {}", name);
        }
    }
}

fn main() {
    let args = std::env::args().collect::<Vec<_>>();
    if args.len() > 3 {
        panic!("usage: {} [data_size] [test]", args[0])
    }
    let data_size = args
        .iter()
        .nth(1)
        .map(|x| x.parse().unwrap())
        .unwrap_or(1000000);
    let selected = args.iter().nth(2).cloned();

    let mut runner = TestRunner {
        selected: selected,
        any_matched: false,
        data_size: data_size,
    };

    let mut is = File::open(&Path::new("perftest_data.pbbin")).unwrap();
    let test_data = PerftestData::parse_from_reader(&mut is).unwrap();

    runner.test("test1", &test_data.test1);
    runner.test("test_repeated_bool", &test_data.test_repeated_bool);
    runner.test(
        "test_repeated_packed_int32",
        &test_data.test_repeated_packed_int32,
    );
    runner.test("test_repeated_messages", &test_data.test_repeated_messages);
    runner.test("test_optional_messages", &test_data.test_optional_messages);
    runner.test("test_strings", &test_data.test_strings);
    runner.test("test_small_bytearrays", &test_data.test_small_bytearrays);
    runner.test("test_large_bytearrays", &test_data.test_large_bytearrays);
    runner.check();
}
<|endoftext|>


<commit_before>static MAGIC_NUMBERS : [u8; 4] = [0x4Eu8, 0x45u8, 0x53u8, 0x1Au8];

#[derive(PartialEq, Debug)]
pub enum ScreenMode {
	Horizontal,
	Vertical,
	FourScreen
}

pub struct Rom {
	prg_rom_pages: u8,
	chr_rom_pages: u8,
	flags6: u8,
	flags7: u8,
	prg_ram_pages: u8,
	trainer: Vec<u8>,
}

fn get_bit(byte: u8, bit_num: u8) -> bool {
	!((byte & 1u8 << bit_num) == 0)
}

impl Rom {
	///Parse the given bytes as an iNES 1.0 header.
	///NES 2.0 is not supported until I can find a rom that actually uses it.
	pub fn parse(data: Vec<u8>) -> Rom {
		assert_eq!( &data[0 .. 4], MAGIC_NUMBERS );
		let prg_rom_pages = data[4];
		let chr_rom_pages = data[5];
		let flags6 = data[6];
		let flags7 = data[7];
		let prg_ram_pages = data[8];

		let mut index : usize = 16;
		let has_trainer = get_bit(flags6, 2);
		let trainer = if !has_trainer { vec!() } else  {
			index += 512;
			data[(index - 512)..index].to_vec()
		};

		Rom {
			prg_rom_pages: prg_rom_pages,
			chr_rom_pages: chr_rom_pages,
			flags6: flags6,
			flags7: flags7,
			prg_ram_pages: prg_ram_pages,
			trainer: trainer
		}
	}

	pub fn screen_mode(&self) -> ScreenMode {
		match self.flags6 & 0b0000_1001u8 {
			0b0000_0000 => ScreenMode::Horizontal,
			0b0000_0001 => ScreenMode::Vertical,
			0b0000_1000 | 0b0000_1001 => ScreenMode::FourScreen,
			_ => panic!("Math is broken!"),
		}
	}

	pub fn sram(&self) -> bool {
		get_bit(self.flags6, 1)
	}

	pub fn trainer(&self) -> &Vec<u8> {
		&self.trainer
	}

	pub fn pc10(&self) -> bool {
		get_bit(self.flags7, 0)
	}

	pub fn vs(&self) -> bool {
		get_bit(self.flags7, 1)
	}

	pub fn mapper(&self) -> u8 {
		( ( self.flags6 & 0xF0 ) >> 4 ) | ( self.flags7 & 0xF0 )
	}
}

#[cfg(test)]
mod tests {
	use super::*;
	use rand::{Rng, thread_rng};

	struct RomBuilder {
		header : Vec<u8>,
		trainer : Vec<u8>
	}

	fn set_bit(byte: &mut u8, bit_num: u8) {
		*byte = *byte | 1u8 << bit_num;
	}

	impl RomBuilder {
		fn new() -> RomBuilder {
			let mut header = vec![0x4Eu8, 0x45u8, 0x53u8, 0x1Au8];
			header.extend([0; 12].iter().cloned());
			return RomBuilder{ header: header, trainer: vec!() }
		}

		fn set_prg_page_count( &mut self, count: u8 ) {
			self.header[4] = count;
		}

		fn set_chr_page_count( &mut self, count: u8 ) {
			self.header[5] = count;
		}

		fn set_mirroring( &mut self ) {
			set_bit(&mut self.header[6], 0)
		}

		fn set_sram( &mut self ) {
			set_bit(&mut self.header[6], 1)
		}

		fn set_trainer( &mut self ) {
			set_bit(&mut self.header[6], 2);
			let mut rng = thread_rng();
			let mut trainer_data = [0u8; 512];
			rng.fill_bytes(&mut trainer_data);
			self.trainer = trainer_data.to_vec();
		}

		fn set_fourscreen( &mut self ) {
			set_bit(&mut self.header[6], 3)
		}

		fn set_pc10( &mut self ) {
			set_bit(&mut self.header[7], 0)
		}

		fn set_vs( &mut self ) {
			set_bit(&mut self.header[7], 1)
		}

		fn set_mapper( &mut self, mapper: u8 ) {
			self.header[6] = ( self.header[6] & 0x0F ) | ( ( mapper & 0x0Fu8 ) << 4 );
			self.header[7] = ( self.header[7] & 0x0F ) | ( ( mapper & 0xF0u8 ) << 0 );
		}

		fn set_prg_ram_pages( &mut self, pages: u8 ) {
			self.header[8] = pages;
		}

		fn build(&self) -> Vec<u8> {
			let mut buf = self.header.clone();
			buf.extend(self.trainer.iter().clone());
			buf
		}
	}

	#[test]
	#[should_panic]
	fn parse_panics_on_empty_input() {
		Rom::parse( vec!() );
	}

	#[test]
	fn test_prg_rom_pages() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).prg_rom_pages, 0 );

		builder.set_prg_page_count( 150 );
		assert_eq!( Rom::parse( builder.build() ).prg_rom_pages, 150 );
	}

	#[test]
	fn test_chr_rom_pages() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).chr_rom_pages, 0 );

		builder.set_chr_page_count( 150 );
		assert_eq!( Rom::parse( builder.build() ).chr_rom_pages, 150 );
	}

	#[test]
	fn test_screen_mode_without_fourscreen() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::Horizontal );

		builder.set_mirroring();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::Vertical );
	}

	#[test]
	fn test_screen_mode_with_fourscreen() {
		let mut builder = RomBuilder::new();
		builder.set_fourscreen();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::FourScreen );

		builder.set_mirroring();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::FourScreen );
	}

	#[test]
	fn test_sram() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).sram(), false );

		builder.set_sram();
		assert_eq!( Rom::parse( builder.build() ).sram(), true );
	}

	#[test]
	fn test_trainer() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).trainer(), &vec!() );

		builder.set_trainer();
		assert_eq!( Rom::parse( builder.build() ).trainer().len(), builder.trainer.len() );
		assert_eq!( Rom::parse( builder.build() ).trainer(), &builder.trainer );
	}

	#[test]
	fn test_pc10() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).pc10(), false );

		builder.set_pc10();
		assert_eq!( Rom::parse( builder.build() ).pc10(), true );
	}

	#[test]
	fn test_vs() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).vs(), false );

		builder.set_vs();
		assert_eq!( Rom::parse( builder.build() ).vs(), true );
	}

	#[test]
	fn test_mapper() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).mapper(), 0x00u8 );

		builder.set_mapper(0x0Au8);
		assert_eq!( Rom::parse( builder.build() ).mapper(), 0x0Au8 );

		builder.set_mapper(0xF0u8);
		println!( "0x{:02X}, 0x{:02X}", builder.header[6], builder.header[7] );
		assert_eq!( Rom::parse( builder.build() ).mapper(), 0xF0u8 );
	}

		#[test]
	fn test_prg_ram_pages() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).prg_ram_pages, 0 );

		builder.set_prg_ram_pages(15);
		assert_eq!( Rom::parse( builder.build() ).prg_ram_pages, 15 );
	}
}<commit_msg>Implemented reading the PRG ROM.<commit_after>const MAGIC_NUMBERS : [u8; 4] = [0x4Eu8, 0x45u8, 0x53u8, 0x1Au8];
pub const PRG_ROM_PAGE_SIZE : usize = 16384;
pub const CHR_ROM_PAGE_SIZE : usize = 8192;
pub const PRG_RAM_PAGE_SIZE : usize = 8192;

#[derive(PartialEq, Debug)]
pub enum ScreenMode {
	Horizontal,
	Vertical,
	FourScreen
}

pub struct Rom {
	prg_rom: Vec<u8>,
	chr_rom_pages: u8,
	flags6: u8,
	flags7: u8,
	prg_ram_pages: u8,
	trainer: Vec<u8>,
}

fn get_bit(byte: u8, bit_num: u8) -> bool {
	!((byte & 1u8 << bit_num) == 0)
}

fn read_byte( iter : &mut Iterator<Item=u8> ) -> u8 {
	iter.next().unwrap()
}

fn read_bytes( iter: &mut Iterator<Item=u8>, bytes: usize ) -> Vec<u8> {
	iter.take( bytes ).collect()
}

impl Rom {
	///Parse the given bytes as an iNES 1.0 header.
	///NES 2.0 is not supported until I can find a rom that actually uses it.
	pub fn parse(data: Vec<u8>) -> Rom {
		let mut iter = data.iter().cloned();
		assert_eq!( read_bytes( &mut iter, 4 ), MAGIC_NUMBERS );
		let prg_rom_pages = read_byte( &mut iter );
		let chr_rom_pages = read_byte( &mut iter );
		let flags6 = read_byte( &mut iter );
		let flags7 = read_byte( &mut iter );
		let prg_ram_pages = read_byte( &mut iter );

		read_bytes( &mut iter, 7 );

		let has_trainer = get_bit(flags6, 2);
		let trainer = match has_trainer {
			false => vec!(),
			true => read_bytes( &mut iter, 512 ),
		};

		Rom {
			prg_rom: read_bytes( &mut iter, PRG_ROM_PAGE_SIZE * prg_rom_pages as usize ),
			chr_rom_pages: chr_rom_pages,
			flags6: flags6,
			flags7: flags7,
			prg_ram_pages: prg_ram_pages,
			trainer: trainer
		}
	}

	pub fn screen_mode(&self) -> ScreenMode {
		match self.flags6 & 0b0000_1001u8 {
			0b0000_0000 => ScreenMode::Horizontal,
			0b0000_0001 => ScreenMode::Vertical,
			0b0000_1000 | 0b0000_1001 => ScreenMode::FourScreen,
			_ => panic!("Math is broken!"),
		}
	}

	pub fn sram(&self) -> bool {
		get_bit(self.flags6, 1)
	}

	pub fn trainer(&self) -> &Vec<u8> {
		&self.trainer
	}

	pub fn pc10(&self) -> bool {
		get_bit(self.flags7, 0)
	}

	pub fn vs(&self) -> bool {
		get_bit(self.flags7, 1)
	}

	pub fn mapper(&self) -> u8 {
		( ( self.flags6 & 0xF0 ) >> 4 ) | ( self.flags7 & 0xF0 )
	}
}

#[cfg(test)]
mod tests {
	use super::*;
	use rand::{Rng, thread_rng};

	struct RomBuilder {
		header : Vec<u8>,
		trainer : Vec<u8>,
		prg_rom : Vec<u8>,
	}

	fn set_bit(byte: &mut u8, bit_num: u8) {
		*byte = *byte | 1u8 << bit_num;
	}

	fn generate_bytes( size: usize ) -> Vec<u8> {
		let mut rng = thread_rng();
		let mut bytes : Vec<u8> = vec!(0u8; size);
		rng.fill_bytes(&mut bytes);
		bytes
	}

	impl RomBuilder {
		fn new() -> RomBuilder {
			let mut header = vec![0x4Eu8, 0x45u8, 0x53u8, 0x1Au8];
			header.extend([0; 12].iter().cloned());
			return RomBuilder{
				header: header,
				trainer: vec!(),
				prg_rom: vec!(),
			}
		}

		fn set_prg_page_count( &mut self, count: u8 ) {
			self.header[4] = count;
			self.prg_rom = generate_bytes( count as usize * PRG_ROM_PAGE_SIZE );
		}

		fn set_chr_page_count( &mut self, count: u8 ) {
			self.header[5] = count;
		}

		fn set_mirroring( &mut self ) {
			set_bit(&mut self.header[6], 0)
		}

		fn set_sram( &mut self ) {
			set_bit(&mut self.header[6], 1)
		}

		fn set_trainer( &mut self ) {
			set_bit(&mut self.header[6], 2);
			self.trainer = generate_bytes( 512 );
		}

		fn set_fourscreen( &mut self ) {
			set_bit(&mut self.header[6], 3)
		}

		fn set_pc10( &mut self ) {
			set_bit(&mut self.header[7], 0)
		}

		fn set_vs( &mut self ) {
			set_bit(&mut self.header[7], 1)
		}

		fn set_mapper( &mut self, mapper: u8 ) {
			self.header[6] = ( self.header[6] & 0x0F ) | ( ( mapper & 0x0Fu8 ) << 4 );
			self.header[7] = ( self.header[7] & 0x0F ) | ( ( mapper & 0xF0u8 ) << 0 );
		}

		fn set_prg_ram_pages( &mut self, pages: u8 ) {
			self.header[8] = pages;
		}

		fn build(&self) -> Vec<u8> {
			let mut buf = self.header.clone();
			buf.extend(self.trainer.iter().clone());
			buf.extend(self.prg_rom.iter().clone());
			buf
		}
	}

	#[test]
	#[should_panic]
	fn parse_panics_on_empty_input() {
		Rom::parse( vec!() );
	}

	#[test]
	fn test_prg_rom_pages() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).prg_rom, vec!() );

		builder.set_prg_page_count( 3 );
		assert_eq!( Rom::parse( builder.build() ).prg_rom, builder.prg_rom );
	}

	#[test]
	fn test_chr_rom_pages() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).chr_rom_pages, 0 );

		builder.set_chr_page_count( 150 );
		assert_eq!( Rom::parse( builder.build() ).chr_rom_pages, 150 );
	}

	#[test]
	fn test_screen_mode_without_fourscreen() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::Horizontal );

		builder.set_mirroring();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::Vertical );
	}

	#[test]
	fn test_screen_mode_with_fourscreen() {
		let mut builder = RomBuilder::new();
		builder.set_fourscreen();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::FourScreen );

		builder.set_mirroring();
		assert_eq!( Rom::parse( builder.build() ).screen_mode(), ScreenMode::FourScreen );
	}

	#[test]
	fn test_sram() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).sram(), false );

		builder.set_sram();
		assert_eq!( Rom::parse( builder.build() ).sram(), true );
	}

	#[test]
	fn test_trainer() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).trainer(), &vec!() );

		builder.set_trainer();
		assert_eq!( Rom::parse( builder.build() ).trainer().len(), builder.trainer.len() );
		assert_eq!( Rom::parse( builder.build() ).trainer(), &builder.trainer );
	}

	#[test]
	fn test_pc10() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).pc10(), false );

		builder.set_pc10();
		assert_eq!( Rom::parse( builder.build() ).pc10(), true );
	}

	#[test]
	fn test_vs() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).vs(), false );

		builder.set_vs();
		assert_eq!( Rom::parse( builder.build() ).vs(), true );
	}

	#[test]
	fn test_mapper() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).mapper(), 0x00u8 );

		builder.set_mapper(0x0Au8);
		assert_eq!( Rom::parse( builder.build() ).mapper(), 0x0Au8 );

		builder.set_mapper(0xF0u8);
		println!( "0x{:02X}, 0x{:02X}", builder.header[6], builder.header[7] );
		assert_eq!( Rom::parse( builder.build() ).mapper(), 0xF0u8 );
	}

		#[test]
	fn test_prg_ram_pages() {
		let mut builder = RomBuilder::new();
		assert_eq!( Rom::parse( builder.build() ).prg_ram_pages, 0 );

		builder.set_prg_ram_pages(15);
		assert_eq!( Rom::parse( builder.build() ).prg_ram_pages, 15 );
	}
}<|endoftext|>


<commit_before>use std::os::getenv;
use std::io::{BufferedReader, IoResult, AllPermissions};
use std::io::fs::{File, copy, rename, mkdir};
use std::io::stdio::{stdout, stderr};
use std::default::Default;

use libc::pid_t;
use collections::treemap::TreeMap;
use argparse::{ArgumentParser, Store, StoreOption, List, StoreTrue, StoreConst};
use argparse::{StoreFalse};

use super::uidmap::write_uid_map;
use super::monitor::Monitor;
use super::env::{Environ, Container};
use super::linux::{ensure_dir, RunOptions, run_container, CPipe};
use super::linux::{BindRO, BindROTmp};
use super::options::env_options;
use super::build::ensure_container;

use Pid1 = super::linux;

static DEFAULT_PATH: &'static str =
    "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin";

fn read_env_file(path: &Path, env: &mut TreeMap<String, String>)
    -> IoResult<()>
{
    let file = try!(File::open(path).map(|f| BufferedReader::new(f)));
    let mut reader = BufferedReader::new(file);
    for (n, line) in reader.lines().enumerate() {
        let line = try!(line);
        let pair: Vec<&str> = line.as_slice().splitn('=', 1).collect();
        match pair.as_slice() {
            [key, val] => {
                let nkey = key.trim().to_string();
                if !env.contains_key(&nkey) {
                    env.insert(nkey, val.trim().to_string());
                }
            }
            _ => {
                warn!("Invalid line {} in {}",
                    n+1, path.display());
            }
        }
    }
    return Ok(());
}

fn container_environ(container: &Container, env: &mut TreeMap<String, String>)
    -> Result<(), String>
{
    for (k, v) in container.environ.iter() {
        if !env.contains_key(k) {
            env.insert(k.clone(), v.clone());
        }
    }
    match container.environ_file {
        None => {}
        Some(ref suf) => {
            let path = container.container_root.as_ref().unwrap()
                       .join(suf.as_slice().trim_left_chars('/'));
            if path.exists() {
                try!(read_env_file(&path, env).map_err(|e| format!(
                    "Error reading environment file: {}", e)));
            }
        }

    }
    return Ok(());
}

pub fn run_command_line(env: &mut Environ, args: Vec<String>)
    -> Result<int, String>
{
    let mut cname = "devel".to_string();
    let mut no_wrapper = false;
    let mut use_shell = false;
    let mut command: Option<String> = None;
    let mut cmdargs: Vec<String> = Vec::new();
    let mut resolv: bool = true;
    let mut ropts: RunOptions = Default::default();
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut cname)
            .add_argument("container", box Store::<String>,
                "A name of the container to build")
            .required();
        ap.refer(&mut command)
            .add_argument("command", box StoreOption::<String>,
                "A command to run inside container")
            .required();
        ap.refer(&mut cmdargs)
            .add_argument("arguments", box List::<String>,
                "Arguments for the command");
        ap.refer(&mut no_wrapper)
            .add_option(["-N", "--no-wrapper"], box StoreTrue,
                "Do not use `command-wrapper` configured for container");
        ap.refer(&mut use_shell)
            .add_option(["-S", "--shell"], box StoreTrue,
                "Run command with `shell` configured for container");
        ap.refer(&mut use_shell)
            .add_option(["-S", "--shell"], box StoreTrue,
                "Run command with `shell` configured for container");
        ap.refer(&mut resolv)
            .add_option(["--no-resolv"], box StoreFalse,
                "Do not copy /etc/resolv.conf");
        ap.refer(&mut ropts.pid1mode)
            .add_option(["--wait"], box StoreConst(Pid1::Wait),
                "Spawn a supervisor as pid 1 and wait until target command \
                 exits. But if it spawned any children, they will be killed \
                 at the death of the target command (default)")
            .add_option(["--wait-all-children"],
                box StoreConst(Pid1::WaitAllChildren),
                "Spawn a supervisor as pid 1 and wait until target command \
                 and all of its children are dead. (Dangerous in some cases \
                 as some non useful child process may block container \
                 shutdown).")
            .add_option(["--exec"], box StoreConst(Pid1::Exec),
                "Execute the target command as pid 1. Should not be used \
                 unless the target command is a process manager itself and/or \
                 supposed to work as pid 1.");
        env_options(env, &mut ap);
        ap.stop_on_first_argument(true);
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => return Ok(122),
        }
    }
    let mut container = try!(env.get_container(&cname));

    if command.is_none() {
        if container.default_command.is_some() {
            let cmd = container.default_command.as_ref().unwrap();
            cmdargs.push_all(cmd.as_slice());
        } else {
            return Err(format!("No command specified and no default command"));
        }
    } else {
        cmdargs.insert(0, command.unwrap());
        if use_shell {
            cmdargs = container.shell.clone() + cmdargs;
        } else if !no_wrapper && container.command_wrapper.is_some() {
            cmdargs = container.command_wrapper.as_ref().unwrap().clone()+cmdargs;
        }
    }

    let cmd = cmdargs.shift().unwrap();
    try!(ensure_container(env, &mut container));

    let mut monitor = Monitor::new(true);
    let pid = try!(internal_run(env, &container, ropts, resolv,
        &env.work_dir, cmd, cmdargs, TreeMap::new()));
    monitor.add("child".to_string(), pid);
    monitor.wait_all();
    return Ok(monitor.get_status());
}

pub fn internal_run(env: &Environ, container: &Container,
    ropts: RunOptions, resolv: bool, work_dir: &Path,
    command: String, cmdargs: Vec<String>, runenv: TreeMap<String, String>)
    -> Result<pid_t, String>
{
    let mut runenv = runenv;
    env.populate_environ(&mut runenv);
    try!(container_environ(container, &mut runenv));
    let container_root = container.container_root.as_ref().unwrap();
    info!("Running {}: {} {}", container_root.display(), command, cmdargs);

    let mount_dir = env.project_root.join_many([".vagga", ".mnt"]);
    try!(ensure_dir(&mount_dir));

    if resolv {
        let etc = container_root.join("etc");
        if !etc.exists() {
            try!(mkdir(&etc, AllPermissions)
                .map_err(|e| format!("Error creating /etc: {}", e)));
        }
        try!(copy(&Path::new("/etc/resolv.conf"),
                  &etc.join("resolv.conf.tmp"))
            .map_err(|e| format!("Error copying resolv.conf: {}", e)));
        try!(rename(&etc.join("resolv.conf.tmp"),
                    &etc.join("resolv.conf"),)
            .map_err(|e| format!("Error copying resolv.conf: {}", e)));
    }

    let home = "HOME".to_string();
    if runenv.find(&home).is_none() {
        // TODO(tailhook) set home to real home if /home is mounted
        runenv.insert(home, "/homeless-shelter".to_string());
    }
    let term = "TERM".to_string();
    if runenv.find(&term).is_none() {
        runenv.insert(term, getenv("TERM").unwrap_or("linux".to_string()));
    }
    let path = "PATH".to_string();
    if runenv.find(&path).is_none() {
        runenv.insert(path, DEFAULT_PATH.to_string());
    }

    let mut ropts = ropts;
    let mount_dir = env.local_vagga.join(".mnt");
    ropts.mounts.push(
        BindRO(env.vagga_inventory.join("markerdir").to_c_str(),
               mount_dir.join("work").join(".vagga").to_c_str()));
    ropts.mounts.push(BindROTmp(env.vagga_inventory.to_c_str(),
                mount_dir.join_many(["tmp", "inventory"]).to_c_str()));

    let pipe = try!(CPipe::new());
    let pid = try!(run_container(&pipe, env,
        container.container_root.as_ref().unwrap(),
        &ropts, work_dir, &command, cmdargs.as_slice(), &runenv));

    try!(write_uid_map(pid, &container.uids, &container.gids));

    try!(pipe.wakeup());
    return Ok(pid);
}
<commit_msg>Fix `_run` command to mount `/tmp` and other container volumes<commit_after>use std::os::getenv;
use std::io::{BufferedReader, IoResult, AllPermissions};
use std::io::fs::{File, copy, rename, mkdir};
use std::io::stdio::{stdout, stderr};
use std::default::Default;

use libc::pid_t;
use collections::treemap::TreeMap;
use argparse::{ArgumentParser, Store, StoreOption, List, StoreTrue, StoreConst};
use argparse::{StoreFalse};

use super::uidmap::write_uid_map;
use super::monitor::Monitor;
use super::env::{Environ, Container};
use super::linux::{ensure_dir, RunOptions, run_container, CPipe};
use super::linux::{BindRO, BindROTmp};
use super::utils::run::{container_volumes};
use super::options::env_options;
use super::build::ensure_container;

use Pid1 = super::linux;

static DEFAULT_PATH: &'static str =
    "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin";

fn read_env_file(path: &Path, env: &mut TreeMap<String, String>)
    -> IoResult<()>
{
    let file = try!(File::open(path).map(|f| BufferedReader::new(f)));
    let mut reader = BufferedReader::new(file);
    for (n, line) in reader.lines().enumerate() {
        let line = try!(line);
        let pair: Vec<&str> = line.as_slice().splitn('=', 1).collect();
        match pair.as_slice() {
            [key, val] => {
                let nkey = key.trim().to_string();
                if !env.contains_key(&nkey) {
                    env.insert(nkey, val.trim().to_string());
                }
            }
            _ => {
                warn!("Invalid line {} in {}",
                    n+1, path.display());
            }
        }
    }
    return Ok(());
}

fn container_environ(container: &Container, env: &mut TreeMap<String, String>)
    -> Result<(), String>
{
    for (k, v) in container.environ.iter() {
        if !env.contains_key(k) {
            env.insert(k.clone(), v.clone());
        }
    }
    match container.environ_file {
        None => {}
        Some(ref suf) => {
            let path = container.container_root.as_ref().unwrap()
                       .join(suf.as_slice().trim_left_chars('/'));
            if path.exists() {
                try!(read_env_file(&path, env).map_err(|e| format!(
                    "Error reading environment file: {}", e)));
            }
        }

    }
    return Ok(());
}

pub fn run_command_line(env: &mut Environ, args: Vec<String>)
    -> Result<int, String>
{
    let mut cname = "devel".to_string();
    let mut no_wrapper = false;
    let mut use_shell = false;
    let mut command: Option<String> = None;
    let mut cmdargs: Vec<String> = Vec::new();
    let mut resolv: bool = true;
    let mut ropts: RunOptions = Default::default();
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut cname)
            .add_argument("container", box Store::<String>,
                "A name of the container to build")
            .required();
        ap.refer(&mut command)
            .add_argument("command", box StoreOption::<String>,
                "A command to run inside container")
            .required();
        ap.refer(&mut cmdargs)
            .add_argument("arguments", box List::<String>,
                "Arguments for the command");
        ap.refer(&mut no_wrapper)
            .add_option(["-N", "--no-wrapper"], box StoreTrue,
                "Do not use `command-wrapper` configured for container");
        ap.refer(&mut use_shell)
            .add_option(["-S", "--shell"], box StoreTrue,
                "Run command with `shell` configured for container");
        ap.refer(&mut use_shell)
            .add_option(["-S", "--shell"], box StoreTrue,
                "Run command with `shell` configured for container");
        ap.refer(&mut resolv)
            .add_option(["--no-resolv"], box StoreFalse,
                "Do not copy /etc/resolv.conf");
        ap.refer(&mut ropts.pid1mode)
            .add_option(["--wait"], box StoreConst(Pid1::Wait),
                "Spawn a supervisor as pid 1 and wait until target command \
                 exits. But if it spawned any children, they will be killed \
                 at the death of the target command (default)")
            .add_option(["--wait-all-children"],
                box StoreConst(Pid1::WaitAllChildren),
                "Spawn a supervisor as pid 1 and wait until target command \
                 and all of its children are dead. (Dangerous in some cases \
                 as some non useful child process may block container \
                 shutdown).")
            .add_option(["--exec"], box StoreConst(Pid1::Exec),
                "Execute the target command as pid 1. Should not be used \
                 unless the target command is a process manager itself and/or \
                 supposed to work as pid 1.");
        env_options(env, &mut ap);
        ap.stop_on_first_argument(true);
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => return Ok(122),
        }
    }
    let mut container = try!(env.get_container(&cname));

    if command.is_none() {
        if container.default_command.is_some() {
            let cmd = container.default_command.as_ref().unwrap();
            cmdargs.push_all(cmd.as_slice());
        } else {
            return Err(format!("No command specified and no default command"));
        }
    } else {
        cmdargs.insert(0, command.unwrap());
        if use_shell {
            cmdargs = container.shell.clone() + cmdargs;
        } else if !no_wrapper && container.command_wrapper.is_some() {
            cmdargs = container.command_wrapper.as_ref().unwrap().clone()+cmdargs;
        }
    }

    let cmd = cmdargs.shift().unwrap();
    try!(ensure_container(env, &mut container));

    ropts.mounts = container_volumes(env, &container);
    let mut monitor = Monitor::new(true);
    let pid = try!(internal_run(env, &container, ropts, resolv,
        &env.work_dir, cmd, cmdargs, TreeMap::new()));
    monitor.add("child".to_string(), pid);
    monitor.wait_all();
    return Ok(monitor.get_status());
}

pub fn internal_run(env: &Environ, container: &Container,
    ropts: RunOptions, resolv: bool, work_dir: &Path,
    command: String, cmdargs: Vec<String>, runenv: TreeMap<String, String>)
    -> Result<pid_t, String>
{
    let mut runenv = runenv;
    env.populate_environ(&mut runenv);
    try!(container_environ(container, &mut runenv));
    let container_root = container.container_root.as_ref().unwrap();
    info!("Running {}: {} {}", container_root.display(), command, cmdargs);

    let mount_dir = env.project_root.join_many([".vagga", ".mnt"]);
    try!(ensure_dir(&mount_dir));

    if resolv {
        let etc = container_root.join("etc");
        if !etc.exists() {
            try!(mkdir(&etc, AllPermissions)
                .map_err(|e| format!("Error creating /etc: {}", e)));
        }
        try!(copy(&Path::new("/etc/resolv.conf"),
                  &etc.join("resolv.conf.tmp"))
            .map_err(|e| format!("Error copying resolv.conf: {}", e)));
        try!(rename(&etc.join("resolv.conf.tmp"),
                    &etc.join("resolv.conf"),)
            .map_err(|e| format!("Error copying resolv.conf: {}", e)));
    }

    let home = "HOME".to_string();
    if runenv.find(&home).is_none() {
        // TODO(tailhook) set home to real home if /home is mounted
        runenv.insert(home, "/homeless-shelter".to_string());
    }
    let term = "TERM".to_string();
    if runenv.find(&term).is_none() {
        runenv.insert(term, getenv("TERM").unwrap_or("linux".to_string()));
    }
    let path = "PATH".to_string();
    if runenv.find(&path).is_none() {
        runenv.insert(path, DEFAULT_PATH.to_string());
    }

    let mut ropts = ropts;
    let mount_dir = env.local_vagga.join(".mnt");
    ropts.mounts.push(
        BindRO(env.vagga_inventory.join("markerdir").to_c_str(),
               mount_dir.join("work").join(".vagga").to_c_str()));
    ropts.mounts.push(BindROTmp(env.vagga_inventory.to_c_str(),
                mount_dir.join_many(["tmp", "inventory"]).to_c_str()));

    let pipe = try!(CPipe::new());
    let pid = try!(run_container(&pipe, env,
        container.container_root.as_ref().unwrap(),
        &ropts, work_dir, &command, cmdargs.as_slice(), &runenv));

    try!(write_uid_map(pid, &container.uids, &container.gids));

    try!(pipe.wakeup());
    return Ok(pid);
}
<|endoftext|>


<commit_before>
use std::iter;
use std::ops;
use std::convert;

use lazy::Lazy;

use finger_tree;
use finger_tree::FingerTree;
use node;
use measure::Measure;

#[derive(Debug)]
struct Item<T>(T);

impl<T> Measure<usize> for Item<T> {
    fn measure(&self) -> usize {1}
}

#[derive(Debug)]
pub struct Seq<T> (Lazy<FingerTree<Item<T>,usize>>);

impl<T:'static> Seq<T> {
    /// The empty sequence.
    ///
    /// /O(1)/
    pub fn empty() -> Seq<T> {
        Seq(finger_tree::empty())
    }

    /// A sequence with a single value.
    ///
    /// /O(1)/
    pub fn singleton(x: T) -> Seq<T> {
        Seq(finger_tree::single(node::leaf(Item(x))))
    }

    /// A new sequence that is `self` with `x` added to the front.
    ///
    /// /O(1)/
    pub fn push_front(&self, x: T) -> Seq<T> {
        Seq(finger_tree::cons_node(node::leaf(Item(x)), self.inner().clone()))
    }

    /// A new sequence that is `self` with `x` added to the back.
    ///
    /// /O(1)/
    pub fn push_back(&self, x: T) -> Seq<T> {
        Seq(finger_tree::snoc_node(self.inner().clone(), node::leaf(Item(x))))
    }

    /// The concatenation of `self` with `other`.
    ///
    /// /O(log(min(`self.len()`,`other.len()`)))/
    pub fn append(&self, other: &Seq<T>) -> Seq<T> {
        Seq(finger_tree::tree_tree(self.inner().clone(), other.inner().clone()))
    }

    /// Is the sequence empty?
    pub fn is_empty(&self) -> bool {
        self.inner().measure() == 0
    }

    /// The number of elements in the sequence
    ///
    /// /O(1)/
    pub fn len(&self) -> usize {
        self.inner().measure()
    }

    /// The first element in the sequence, if it exists.
    ///
    /// /O(1)/
    pub fn front(&self) -> Option<&T> {
        finger_tree::front(self.inner()).map(|&Item(ref x)| x)
    }

    /// The back element, if it exsts.
    ///
    /// /O(1)/
    pub fn back(&self) -> Option<&T> {
        finger_tree::back(self.inner()).map(|&Item(ref x)| x)
    }

    /// A new sequence that is `self` with the front element removed, together with the front element (if it exists).
    ///
    /// /O(1)/
    pub fn pop_front(&self) -> Seq<T> {
        Seq(finger_tree::pop_front(self.inner()))
    }

    /// A new sequence that is `self` with the back element removed, together with the back element (if it exists).
    ///
    /// /O(1)/
    pub fn pop_back(&self) -> Seq<T> {
        Seq(finger_tree::pop_back(self.inner()))
    }

    /// A new sequence with the element at index `i` replaced by `f(self[i])`.
    ///
    /// If `i` is out of range, returns a clone of `self`.
    ///
    /// /O(log(min(i,`self.len()`-i)))/
    pub fn adjust<F>(&self, i: usize, func: F) -> Seq<T>
        where F: FnOnce(&T) -> T
    {
        if i >= self.len() {
            return self.clone()
        }
        Seq(finger_tree::adjust(move |&Item(ref x)| Item(func(x)), move |j| {i < j}, 0, self.inner()))
    }

    /// A new sequence with the element at index `i` replaced by `x`.
    ///
    /// If `i` is out of range, returns a clone of `self`.
    ///
    /// /O(log(min(i,`self.len()`-i)))/
    pub fn update(&self, i: usize, x: T) -> Seq<T> {
        self.adjust(i, move |_| x)
    }

    /// A new sequence consisting of only the first `n` elements.
    ///
    /// If `n >= self.len()`, then returns a clone of `self`.
    ///
    /// /O(log(min(n,`self.len()`-n)))/
    pub fn truncate(&self, n: usize) -> Seq<T> {
        let (before,_) = self.split(n);
        before
    }

    /// A new sequence consisting of only the last `n` elements.
    ///
    /// If `n >= self.len()`, then returns a clone of `self`.
    ///
    /// /O(log(min(n,`self.len()`-n)))/
    pub fn skip(&self, n: usize) -> Seq<T> {
        let (_,after) = self.split(n);
        after
    }

    /// Two new sequences, consisting of the first `n` elements, and the remaining elements, respectively.
    ///
    /// If `n >= self.len()`, then the first sequence is a clone of `self` and the second is empty.
    ///
    /// /O(log(min(n,`self.len()`-n)))/
    pub fn split(&self, n: usize) -> (Seq<T>, Seq<T>) {
        if n >= self.len() {
            return (self.clone(), Seq::empty())
        }
        let (before,x,after) = finger_tree::split(&move |i| {n < i}, 0, self.inner());
        (Seq(before), Seq(finger_tree::cons_node(x.clone(), after)))
    }

    /// A new sequence with the element at index `i` removed, together with the element at index `i`, if it exists.
    ///
    /// If `i` is out of range, then the returned sequence is a clone of `self`, and the element is `None`.
    ///
    /// /O(log(min(i,`self.len()`-i)))/
    pub fn remove(&self, i: usize) -> Seq<T> {
        if i >= self.len() {
            return self.clone()
        }
        let (before,_,after) = finger_tree::split(&move |j| {i < j}, 0, self.inner());
        Seq(finger_tree::tree_tree(before, after))
    }

    /// A new sequence with `x` inserted at index `i`.
    ///
    /// If `i < self.len()`, then `x` will immediately precede `self[i]` in the new sequence.
    ///
    /// if `i >= self.len()`, then `x` will be the last element in the new sequence.
    ///
    /// /O(log(min(i,`self.len()`-i)))/
    pub fn insert(&self, i: usize, x: T) -> Seq<T> {
        if i >= self.len() {
            return self.push_back(x)
        }
        let (before,y,after) = finger_tree::split(&move |j| {i < j}, 0, self.inner());
        let before = finger_tree::snoc_node(before, node::leaf(Item(x)));
        let after = finger_tree::cons_node(y.clone(), after);
        Seq(finger_tree::tree_tree(before, after))
    }

    /// Get the element at index `i`, if it exists.
    ///
    /// /O(log(min(i,`self.len()`-i)))/
    pub fn get(&self, i: usize) -> Option<&T> {
        if i >= self.len() {
            return None
        }
        match finger_tree::lookup(move |j| {i < j}, 0, self.inner()) {
            (&Item(ref x), _) => Some(x)
        }
    }

    /// An iterator over the sequence.
    ///
    /// /O(1)/
    pub fn iter(&self) -> Iter<T> {
        self.into_iter()
    }

    fn inner(&self) -> &Lazy<FingerTree<Item<T>,usize>> {
        match *self {
            Seq(ref inner) => inner
        }
    }
}

#[macro_export]
macro_rules! seq {
    () => {
        Seq::empty()
    };
    ($e0: expr $(, $e: expr)*) => {
        seq!($($e),*).push_front($e0)
    };
}

impl<T:'static> Clone for Seq<T> {
    fn clone(&self) -> Seq<T> {
        Seq(self.inner().clone())
    }
}

#[derive(Debug)]
pub struct Iter<'a, T: 'a> {
    inner: finger_tree::Iter<'a, Item<T>, usize>
}

impl<'a,T:'static> Iter<'a,T> {
    fn new(seq: &'a Seq<T>) -> Iter<'a,T> {
        Iter {
            inner: seq.inner().iter()
        }
    }
}

impl<'a,T:'a> Iterator for Iter<'a,T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        match self.inner.next() {
            None => None,
            Some(&Item(ref x)) => Some(x)
        }
    }
}

impl<'a, T: 'static> iter::IntoIterator for &'a Seq<T> {
    type Item = &'a T;

    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a,T> {
        Iter::new(self)
    }
}

impl<T:'static> iter::FromIterator<T> for Seq<T> {
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item=T> {
        let mut iter = iter.into_iter();
        let mut seq = Seq::empty();
        while let Some(x) = iter.next() {
            seq = seq.push_back(x);
        }
        seq
    }
}

impl<T:'static> convert::From<Vec<T>> for Seq<T> {
    fn from(v: Vec<T>) -> Seq<T> {
        v.into_iter().collect()
    }
}

impl<T:'static> ops::Index<usize> for Seq<T> {
    type Output = T;
    fn index(&self, index: usize) -> &T {
        self.get(index).expect("Out of bounds access")
    }
}

// impl<T> ops::Index<ops::Range<usize>> for Seq<T> {
//     type Output = Seq<T>;
//     fn index(&self, index: ops::Range<usize>) -> &Seq<T> {
//         if index.start >= index.end {
//             Seq::empty()
//         } else if index.start == 0 {
//             self.index(ops::RangeTo(index.end))
//         } else if index.end >= self.len() {
//             self.index(ops::RangeFrom(index.start))
//         } else {
//             self.truncate(index.end).truncate_front(index.end - index.start)
//         }
//     }
// }

// impl<T> ops::Index<ops::RangeTo<usize>> for Seq<T> {
//     type Output = Seq<T>;
//     fn index(&self, index: ops::RangeTo<usize>) -> &Seq<T> {
//         if index.end >= self.len() {
//             self.index(ops::RangeFull)
//         } else {
//             self.truncate(index.end)
//         }
//     }
// }

// impl<T> ops::Index<ops::RangeFrom<usize>> for Seq<T> {
//     type Output = Seq<T>;
//     fn index(&self, index: ops::RangeFrom<usize>) -> &Seq<T> {
//         if index.begin >= self.len() {
//             Seq::empty()
//         }
//         if index.begin == 0 {
//             self.index(ops::RangeFull)
//         } else {
//             self.truncate_front(self.len() - index.start)
//         }
//     }
// }

// impl<T> ops::Index<ops::RangeFull> for Seq<T> {
//     type Output = Seq<T>;
//     fn index(&self, index: ops::RangeFull) -> &Seq<T> {
//         self.clone()
//     }
// }
<commit_msg>Added PartialEq, Eq, PartialOrd and Ord implementations to Seq<commit_after>
use std::iter;
use std::ops;
use std::convert;
use std::cmp;

use lazy::Lazy;

use finger_tree;
use finger_tree::FingerTree;
use node;
use measure::Measure;

#[derive(Debug)]
struct Item<T>(T);

impl<T> Measure<usize> for Item<T> {
    fn measure(&self) -> usize {1}
}

#[derive(Debug)]
pub struct Seq<T> (Lazy<FingerTree<Item<T>,usize>>);

impl<T:'static> Seq<T> {
    /// The empty sequence.
    ///
    /// /O(1)/
    pub fn empty() -> Seq<T> {
        Seq(finger_tree::empty())
    }

    /// A sequence with a single value.
    ///
    /// /O(1)/
    pub fn singleton(x: T) -> Seq<T> {
        Seq(finger_tree::single(node::leaf(Item(x))))
    }

    /// A new sequence that is `self` with `x` added to the front.
    ///
    /// /O(1)/
    pub fn push_front(&self, x: T) -> Seq<T> {
        Seq(finger_tree::cons_node(node::leaf(Item(x)), self.inner().clone()))
    }

    /// A new sequence that is `self` with `x` added to the back.
    ///
    /// /O(1)/
    pub fn push_back(&self, x: T) -> Seq<T> {
        Seq(finger_tree::snoc_node(self.inner().clone(), node::leaf(Item(x))))
    }

    /// The concatenation of `self` with `other`.
    ///
    /// /O(log(min(`self.len()`,`other.len()`)))/
    pub fn append(&self, other: &Seq<T>) -> Seq<T> {
        Seq(finger_tree::tree_tree(self.inner().clone(), other.inner().clone()))
    }

    /// Is the sequence empty?
    pub fn is_empty(&self) -> bool {
        self.inner().measure() == 0
    }

    /// The number of elements in the sequence
    ///
    /// /O(1)/
    pub fn len(&self) -> usize {
        self.inner().measure()
    }

    /// The first element in the sequence, if it exists.
    ///
    /// /O(1)/
    pub fn front(&self) -> Option<&T> {
        finger_tree::front(self.inner()).map(|&Item(ref x)| x)
    }

    /// The back element, if it exsts.
    ///
    /// /O(1)/
    pub fn back(&self) -> Option<&T> {
        finger_tree::back(self.inner()).map(|&Item(ref x)| x)
    }

    /// A new sequence that is `self` with the front element removed, together with the front element (if it exists).
    ///
    /// /O(1)/
    pub fn pop_front(&self) -> Seq<T> {
        Seq(finger_tree::pop_front(self.inner()))
    }

    /// A new sequence that is `self` with the back element removed, together with the back element (if it exists).
    ///
    /// /O(1)/
    pub fn pop_back(&self) -> Seq<T> {
        Seq(finger_tree::pop_back(self.inner()))
    }

    /// A new sequence with the element at index `i` replaced by `f(self[i])`.
    ///
    /// If `i` is out of range, returns a clone of `self`.
    ///
    /// /O(log(min(i,`self.len()`-i)))/
    pub fn adjust<F>(&self, i: usize, func: F) -> Seq<T>
        where F: FnOnce(&T) -> T
    {
        if i >= self.len() {
            return self.clone()
        }
        Seq(finger_tree::adjust(move |&Item(ref x)| Item(func(x)), move |j| {i < j}, 0, self.inner()))
    }

    /// A new sequence with the element at index `i` replaced by `x`.
    ///
    /// If `i` is out of range, returns a clone of `self`.
    ///
    /// /O(log(min(i,`self.len()`-i)))/
    pub fn update(&self, i: usize, x: T) -> Seq<T> {
        self.adjust(i, move |_| x)
    }

    /// A new sequence consisting of only the first `n` elements.
    ///
    /// If `n >= self.len()`, then returns a clone of `self`.
    ///
    /// /O(log(min(n,`self.len()`-n)))/
    pub fn truncate(&self, n: usize) -> Seq<T> {
        let (before,_) = self.split(n);
        before
    }

    /// A new sequence consisting of only the last `n` elements.
    ///
    /// If `n >= self.len()`, then returns a clone of `self`.
    ///
    /// /O(log(min(n,`self.len()`-n)))/
    pub fn skip(&self, n: usize) -> Seq<T> {
        let (_,after) = self.split(n);
        after
    }

    /// Two new sequences, consisting of the first `n` elements, and the remaining elements, respectively.
    ///
    /// If `n >= self.len()`, then the first sequence is a clone of `self` and the second is empty.
    ///
    /// /O(log(min(n,`self.len()`-n)))/
    pub fn split(&self, n: usize) -> (Seq<T>, Seq<T>) {
        if n >= self.len() {
            return (self.clone(), Seq::empty())
        }
        let (before,x,after) = finger_tree::split(&move |i| {n < i}, 0, self.inner());
        (Seq(before), Seq(finger_tree::cons_node(x.clone(), after)))
    }

    /// A new sequence with the element at index `i` removed, together with the element at index `i`, if it exists.
    ///
    /// If `i` is out of range, then the returned sequence is a clone of `self`, and the element is `None`.
    ///
    /// /O(log(min(i,`self.len()`-i)))/
    pub fn remove(&self, i: usize) -> Seq<T> {
        if i >= self.len() {
            return self.clone()
        }
        let (before,_,after) = finger_tree::split(&move |j| {i < j}, 0, self.inner());
        Seq(finger_tree::tree_tree(before, after))
    }

    /// A new sequence with `x` inserted at index `i`.
    ///
    /// If `i < self.len()`, then `x` will immediately precede `self[i]` in the new sequence.
    ///
    /// if `i >= self.len()`, then `x` will be the last element in the new sequence.
    ///
    /// /O(log(min(i,`self.len()`-i)))/
    pub fn insert(&self, i: usize, x: T) -> Seq<T> {
        if i >= self.len() {
            return self.push_back(x)
        }
        let (before,y,after) = finger_tree::split(&move |j| {i < j}, 0, self.inner());
        let before = finger_tree::snoc_node(before, node::leaf(Item(x)));
        let after = finger_tree::cons_node(y.clone(), after);
        Seq(finger_tree::tree_tree(before, after))
    }

    /// Get the element at index `i`, if it exists.
    ///
    /// /O(log(min(i,`self.len()`-i)))/
    pub fn get(&self, i: usize) -> Option<&T> {
        if i >= self.len() {
            return None
        }
        match finger_tree::lookup(move |j| {i < j}, 0, self.inner()) {
            (&Item(ref x), _) => Some(x)
        }
    }

    /// An iterator over the sequence.
    ///
    /// /O(1)/
    pub fn iter(&self) -> Iter<T> {
        self.into_iter()
    }

    fn inner(&self) -> &Lazy<FingerTree<Item<T>,usize>> {
        match *self {
            Seq(ref inner) => inner
        }
    }
}

#[macro_export]
macro_rules! seq {
    () => {
        Seq::empty()
    };
    ($e0: expr $(, $e: expr)*) => {
        seq!($($e),*).push_front($e0)
    };
}

impl<T:'static> Clone for Seq<T> {
    fn clone(&self) -> Seq<T> {
        Seq(self.inner().clone())
    }
}

impl<T:'static> PartialEq for Seq<T>
    where T: PartialEq
{
    fn eq(&self, other: &Seq<T>) -> bool {
        self.iter().eq(other.iter())
    }
}

impl<T:'static> Eq for Seq<T>
    where T: Eq
{}

impl<T:'static> PartialOrd for Seq<T>
    where T: PartialOrd
{
    fn partial_cmp(&self, other: &Seq<T>) -> Option<cmp::Ordering> {
        self.iter().partial_cmp(other.iter())
    }
}

impl<T:'static> Ord for Seq<T>
    where T: Ord
{
    fn cmp(&self, other: &Seq<T>) -> cmp::Ordering {
        self.iter().cmp(other.iter())
    }
}

#[derive(Debug)]
pub struct Iter<'a, T: 'a> {
    inner: finger_tree::Iter<'a, Item<T>, usize>
}

impl<'a,T:'static> Iter<'a,T> {
    fn new(seq: &'a Seq<T>) -> Iter<'a,T> {
        Iter {
            inner: seq.inner().iter()
        }
    }
}

impl<'a,T:'a> Iterator for Iter<'a,T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        match self.inner.next() {
            None => None,
            Some(&Item(ref x)) => Some(x)
        }
    }
}

impl<'a, T: 'static> iter::IntoIterator for &'a Seq<T> {
    type Item = &'a T;

    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a,T> {
        Iter::new(self)
    }
}

impl<T:'static> iter::FromIterator<T> for Seq<T> {
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item=T> {
        let mut iter = iter.into_iter();
        let mut seq = Seq::empty();
        while let Some(x) = iter.next() {
            seq = seq.push_back(x);
        }
        seq
    }
}

impl<T:'static> convert::From<Vec<T>> for Seq<T> {
    fn from(v: Vec<T>) -> Seq<T> {
        v.into_iter().collect()
    }
}

impl<T:'static> ops::Index<usize> for Seq<T> {
    type Output = T;
    fn index(&self, index: usize) -> &T {
        self.get(index).expect("Out of bounds access")
    }
}

// impl<T> ops::Index<ops::Range<usize>> for Seq<T> {
//     type Output = Seq<T>;
//     fn index(&self, index: ops::Range<usize>) -> &Seq<T> {
//         if index.start >= index.end {
//             Seq::empty()
//         } else if index.start == 0 {
//             self.index(ops::RangeTo(index.end))
//         } else if index.end >= self.len() {
//             self.index(ops::RangeFrom(index.start))
//         } else {
//             self.truncate(index.end).truncate_front(index.end - index.start)
//         }
//     }
// }

// impl<T> ops::Index<ops::RangeTo<usize>> for Seq<T> {
//     type Output = Seq<T>;
//     fn index(&self, index: ops::RangeTo<usize>) -> &Seq<T> {
//         if index.end >= self.len() {
//             self.index(ops::RangeFull)
//         } else {
//             self.truncate(index.end)
//         }
//     }
// }

// impl<T> ops::Index<ops::RangeFrom<usize>> for Seq<T> {
//     type Output = Seq<T>;
//     fn index(&self, index: ops::RangeFrom<usize>) -> &Seq<T> {
//         if index.begin >= self.len() {
//             Seq::empty()
//         }
//         if index.begin == 0 {
//             self.index(ops::RangeFull)
//         } else {
//             self.truncate_front(self.len() - index.start)
//         }
//     }
// }

// impl<T> ops::Index<ops::RangeFull> for Seq<T> {
//     type Output = Seq<T>;
//     fn index(&self, index: ops::RangeFull) -> &Seq<T> {
//         self.clone()
//     }
// }
<|endoftext|>


<commit_before>extern crate router;
extern crate persistent;

use std::io::Read;

use iron::prelude::*;
use iron::status;
use router::Router;
use rustc_serialize::json::{self, Json};

use super::{Globals, Index, Mapping, Document, query};

fn index_not_found_response() -> Response {
    let mut response = Response::with((status::NotFound, "{\"message\": \"Index not found\"}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    return response;
}

pub fn view_home(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "Hello World!")))
}

pub fn view_count(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load query from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    println!("{:#?}", query::parse_query(data.unwrap().as_object().unwrap().get("query").unwrap()));

    // TODO: Run query

    // Temporary count and return numbers
    let mut count = 0;
    for mapping in index.mappings.values() {
        count += mapping.docs.len();
    }

    let mut response = Response::with((status::Ok, format!("{{\"count\": {}}}", count)));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_search(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load query from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    println!("{:#?}", query::parse_query(data.unwrap().as_object().unwrap().get("query").unwrap()));

    // TODO: Run query

    let mut response = Response::with((status::Ok, "{\"hits\": {\"total\": 0, \"hits\": []}}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_get_doc(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
    let doc_id = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Find mapping
    let mapping = match index.mappings.get(mapping_name) {
        Some(mapping) => mapping,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Mapping not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    // Find document
    let doc = match mapping.docs.get(doc_id) {
        Some(doc) => doc,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Document not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    let mut response = Response::with((status::Ok, json::encode(&doc.data).unwrap()));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_doc(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
    let ref doc_id = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Find index
    let mut index = match indices.get_mut(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Find mapping
    let mut mapping = match index.mappings.get_mut(mapping_name) {
        Some(mapping) => mapping,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Mapping not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    // Create and insert document
    if let Some(data) = data {
        let doc = Document::from_json(data);
        mapping.docs.insert(doc_id.clone().to_owned(), doc);
    }

    let mut response = Response::with((status::Ok, "{}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_index(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let ref index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    // Create index
    indices.insert(index_name.clone().to_owned(), Index::new());

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_mapping(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let ref mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Find index
    let mut index = match indices.get_mut(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    if payload.is_empty() {
        // TODO: Better error
        let mut response = Response::with((status::Ok, "{\"acknowledged\": false}"));
        response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
        return Ok(response)
    }

    let data = match Json::from_str(&payload) {
        Ok(data) => data,
        Err(error) => {
            // TODO: What specifically is bad about the JSON?
            let mut response = Response::with((status::BadRequest,
                                               "{\"message\": \"Couldn't parse JSON\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    let data = data.as_object().unwrap().get(*mapping_name).unwrap();

    // Insert mapping
    let mapping = Mapping::from_json(&data);
    println!("{:#?}", mapping);
    index.mappings.insert(mapping_name.clone().to_owned(), mapping);

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_post_bulk(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    for payload_part in payload.split('\n') {
        let data = if !payload.is_empty() {
            Some(Json::from_str(&payload))
        } else {
            None
        };
    }

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn get_router() -> Router {
    router!(get "/" => view_home,
            get "/:index/_count" => view_count,
            get "/:index/_search" => view_search,
            get "/:index/:mapping/:doc" => view_get_doc,
            put "/:index/:mapping/:doc" => view_put_doc,
            put "/:index" => view_put_index,
            put "/:index/_mapping/:mapping" => view_put_mapping,
            post "/_bulk" => view_post_bulk)
}
<commit_msg>Added index refresh API<commit_after>extern crate router;
extern crate persistent;

use std::io::Read;

use iron::prelude::*;
use iron::status;
use router::Router;
use rustc_serialize::json::{self, Json};

use super::{Globals, Index, Mapping, Document, query};

fn index_not_found_response() -> Response {
    let mut response = Response::with((status::NotFound, "{\"message\": \"Index not found\"}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    return response;
}

pub fn view_home(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "Hello World!")))
}

pub fn view_count(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load query from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    println!("{:#?}", query::parse_query(data.unwrap().as_object().unwrap().get("query").unwrap()));

    // TODO: Run query

    // Temporary count and return numbers
    let mut count = 0;
    for mapping in index.mappings.values() {
        count += mapping.docs.len();
    }

    let mut response = Response::with((status::Ok, format!("{{\"count\": {}}}", count)));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_search(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load query from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    println!("{:#?}", query::parse_query(data.unwrap().as_object().unwrap().get("query").unwrap()));

    // TODO: Run query

    let mut response = Response::with((status::Ok, "{\"hits\": {\"total\": 0, \"hits\": []}}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_get_doc(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
    let doc_id = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Find mapping
    let mapping = match index.mappings.get(mapping_name) {
        Some(mapping) => mapping,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Mapping not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    // Find document
    let doc = match mapping.docs.get(doc_id) {
        Some(doc) => doc,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Document not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    let mut response = Response::with((status::Ok, json::encode(&doc.data).unwrap()));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_doc(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
    let ref doc_id = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Find index
    let mut index = match indices.get_mut(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Find mapping
    let mut mapping = match index.mappings.get_mut(mapping_name) {
        Some(mapping) => mapping,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Mapping not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    // Create and insert document
    if let Some(data) = data {
        let doc = Document::from_json(data);
        mapping.docs.insert(doc_id.clone().to_owned(), doc);
    }

    let mut response = Response::with((status::Ok, "{}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_index(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let ref index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    // Create index
    indices.insert(index_name.clone().to_owned(), Index::new());

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_mapping(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let ref mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Find index
    let mut index = match indices.get_mut(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    if payload.is_empty() {
        // TODO: Better error
        let mut response = Response::with((status::Ok, "{\"acknowledged\": false}"));
        response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
        return Ok(response)
    }

    let data = match Json::from_str(&payload) {
        Ok(data) => data,
        Err(error) => {
            // TODO: What specifically is bad about the JSON?
            let mut response = Response::with((status::BadRequest,
                                               "{\"message\": \"Couldn't parse JSON\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    let data = data.as_object().unwrap().get(*mapping_name).unwrap();

    // Insert mapping
    let mapping = Mapping::from_json(&data);
    println!("{:#?}", mapping);
    index.mappings.insert(mapping_name.clone().to_owned(), mapping);

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_post_bulk(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    for payload_part in payload.split('\n') {
        let data = if !payload.is_empty() {
            Some(Json::from_str(&payload))
        } else {
            None
        };
    }

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_post_refresh(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn get_router() -> Router {
    router!(get "/" => view_home,
            get "/:index/_count" => view_count,
            get "/:index/_search" => view_search,
            get "/:index/:mapping/:doc" => view_get_doc,
            put "/:index/:mapping/:doc" => view_put_doc,
            put "/:index" => view_put_index,
            put "/:index/_mapping/:mapping" => view_put_mapping,
            post "/_bulk" => view_post_bulk,
            post ":index/_refresh" => view_post_refresh)
}
<|endoftext|>


<commit_before>use std::ptr;

use RadioToolButton;
use ToolItem;
use ffi;
use glib::object::Downcast;
use glib::translate::*;

impl RadioToolButton {
    pub fn new() -> RadioToolButton {
        assert_initialized_main_thread!();
        unsafe {
            ToolItem::from_glib_none(ffi::gtk_radio_tool_button_new(ptr::null_mut())).downcast_unchecked()
        }
    }

    pub fn new_from_stock(stock_id: &str) -> RadioToolButton {
        assert_initialized_main_thread!();
        unsafe {
            ToolItem::from_glib_none(ffi::gtk_radio_tool_button_new_from_stock(ptr::null_mut(), stock_id.to_glib_none().0)).downcast_unchecked()
        }
    }
}
<commit_msg>Add fn join_group to RadioToolButton<commit_after>use std::ptr;

use RadioToolButton;
use ToolItem;
use ffi;
use glib::object::Downcast;
use glib::translate::*;
use glib::Value;
use gobject_ffi;

impl RadioToolButton {
    pub fn new() -> RadioToolButton {
        assert_initialized_main_thread!();
        unsafe {
            ToolItem::from_glib_none(ffi::gtk_radio_tool_button_new(ptr::null_mut())).downcast_unchecked()
        }
    }

    pub fn new_from_stock(stock_id: &str) -> RadioToolButton {
        assert_initialized_main_thread!();
        unsafe {
            ToolItem::from_glib_none(ffi::gtk_radio_tool_button_new_from_stock(ptr::null_mut(), stock_id.to_glib_none().0)).downcast_unchecked()
        }
    }

    pub fn join_group<'a, P: Into<Option<&'a RadioToolButton>>>(&self, group: P) {
        let group = group.into();
        unsafe {
            gobject_ffi::g_object_set_property(self.to_glib_none().0, "group".to_glib_none().0, Value::from(group).to_glib_none().0);
        }
    }
}
<|endoftext|>


<commit_before>//! Implementation of the Xenstore protocol

use core::result;
use core::str::FromStr;

use ffi::CString;

use cell::GlobalCell;

use self::imp::XenStoreImpl;

use hal::xen::defs::{XenstoreInterface, EvtchnPort};

pub use self::transaction::Transaction;

static STORE: GlobalCell<XenStoreImpl> = GlobalCell::new();

mod imp;
mod transaction;

/// Result of an operation within the Xen Store
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
/// Error code that can be returned by a Xen Store operation
pub enum Error {
    /// Unknown error happened
    Unknown,
    /// A type conversion error
    Conversion,
    /// Invalid argument
    Inval,
    /// Permission denied
    Acces,
    /// File exists
    Exist,
    /// Is a directory
    Isdir,
    /// No such file or directory
    Noent,
    /// Out of memory
    Nomem,
    /// No space left on device
    Nospc,
    /// I/O error
    Io,
    /// Directory not empty
    Notempty,
    /// Function not implemented
    Nosys,
    /// Read-only filesystem
    Rofs,
    /// Device or resource is busy
    Busy,
    /// Try again
    Again,
    /// Transport endpoint is already connected
    Isconn,
}

/// Main interface of the Xen Store
pub struct XenStore;

impl XenStore {
    #[doc(hidden)]
    pub unsafe fn init(interface: *mut XenstoreInterface, port: EvtchnPort) {
        STORE.set(XenStoreImpl::new(interface, port));
    }

    #[doc(hidden)]
    pub unsafe fn init_event() {
        STORE.as_mut().init_event();
    }

    /// Start a new transaction within the Xen Store
    pub fn start_transaction<'a>() -> Result<Transaction<'a>> {
        Transaction::new(STORE.as_mut())
    }

    /// Read a value from the xen store and convert it
    pub unsafe fn read_value<T: FromStr>(path: CString) -> Result<T> {
        let mut t = try!(Self::start_transaction());

        let val = try!(t.read(path));

        T::from_str(val.as_str()).or_else(|_| Err(Error::Conversion))
    }
}
<commit_msg>xen: XenStore::read_value() is now safe<commit_after>//! Implementation of the Xenstore protocol

use core::result;
use core::str::FromStr;

use ffi::CString;

use cell::GlobalCell;

use self::imp::XenStoreImpl;

use hal::xen::defs::{XenstoreInterface, EvtchnPort};

pub use self::transaction::Transaction;

static STORE: GlobalCell<XenStoreImpl> = GlobalCell::new();

mod imp;
mod transaction;

/// Result of an operation within the Xen Store
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
/// Error code that can be returned by a Xen Store operation
pub enum Error {
    /// Unknown error happened
    Unknown,
    /// A type conversion error
    Conversion,
    /// Invalid argument
    Inval,
    /// Permission denied
    Acces,
    /// File exists
    Exist,
    /// Is a directory
    Isdir,
    /// No such file or directory
    Noent,
    /// Out of memory
    Nomem,
    /// No space left on device
    Nospc,
    /// I/O error
    Io,
    /// Directory not empty
    Notempty,
    /// Function not implemented
    Nosys,
    /// Read-only filesystem
    Rofs,
    /// Device or resource is busy
    Busy,
    /// Try again
    Again,
    /// Transport endpoint is already connected
    Isconn,
}

/// Main interface of the Xen Store
pub struct XenStore;

impl XenStore {
    #[doc(hidden)]
    pub unsafe fn init(interface: *mut XenstoreInterface, port: EvtchnPort) {
        STORE.set(XenStoreImpl::new(interface, port));
    }

    #[doc(hidden)]
    pub unsafe fn init_event() {
        STORE.as_mut().init_event();
    }

    /// Start a new transaction within the Xen Store
    pub fn start_transaction<'a>() -> Result<Transaction<'a>> {
        Transaction::new(STORE.as_mut())
    }

    /// Read a value from the xen store and convert it
    pub fn read_value<T: FromStr>(path: CString) -> Result<T> {
        let mut t = try!(Self::start_transaction());

        let val = try!(t.read(path));

        T::from_str(val.as_str()).or_else(|_| Err(Error::Conversion))
    }
}
<|endoftext|>