<commit_before>//! Lua interpreter setup and configuration reading.

mod config;
mod utils;

use self::config::{get_config, load_config};
pub use self::{config::log_error, utils::*};

use clap::ArgMatches;
use glib::MainLoop;
use rlua::{self, AnyUserData, Lua, Table, Value};

use std::{cell::{Cell, RefCell},
          fs::File,
          io::{self, Read},
          path::PathBuf};

use common::signal;

/// Path to the Awesome shims.
const SHIMS_PATH: &str = "../../tests/awesome/tests/examples/shims/";
/// Shims to load
const SHIMS: [&str; 11] = ["awesome",
                           "root",
                           "tag",
                           "screen",
                           "client",
                           "mouse",
                           "drawin",
                           "button",
                           "keygrabber",
                           "mousegrabber",
                           "key"];

thread_local! {
    // NOTE The debug library does some powerful reflection that can do crazy things,
    // which is why it's unsafe to load.

    /// Global Lua state.
    pub static LUA: RefCell<Lua> = RefCell::new(unsafe { Lua::new_with_debug() });

    /// If set then we have restarted the Lua thread. We need to replace LUA when it's not borrowed.
    pub static NEXT_LUA: Cell<bool> = Cell::new(false);

    /// Main GLib loop
    static MAIN_LOOP: RefCell<MainLoop> = RefCell::new(MainLoop::new(None, false));
}

/// Loads shim code to act like Awesome.
///
/// To be compatible this must eventually be removed.
///
/// Best way to help out: comment out one of these lines, fix what breaks.
fn load_shims(lua: &Lua) {
    let globals = lua.globals();
    let package: Table = globals.get("package").unwrap();
    let mut path = package.get::<_, String>("path").unwrap();
    path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua", SHIMS_PATH));
    package.set("path", path).unwrap();
    let shims_path = PathBuf::from(SHIMS_PATH);
    for shim in SHIMS.iter() {
        let mut path = shims_path.clone();
        path.push(format!("{}.lua", shim));
        let shims_path_str = path.to_str().unwrap();
        let mut file =
            File::open(path.clone()).expect(&format!("Could not open {}", shims_path_str));
        let mut contents = String::new();
        file.read_to_string(&mut contents).expect(&format!("Could not read {}", shims_path_str));
        let obj = lua.exec::<rlua::Value>(contents.as_str(), None)
                     .expect(&format!("Could not read {}", shims_path_str));
        globals.set(*shim, obj).expect("Could not set global object");
    }
}

/// Sets up the Lua environment for the user code.
///
/// This environment is also necessary for some Wayland callbacks,
/// so it should be called as soon as possible.
pub fn init_awesome_libraries(lib_paths: &[&str]) {
    info!("Setting up Awesome libraries");
    LUA.with(|lua| {
           register_libraries(&*lua.borrow(), lib_paths).expect("Could not register lua libraries");
       });
}

/// Runs user code from the config through the awesome compatibility layer.
///
/// It then enters the glib/wayland main loop to listen for events.
pub fn run_awesome(matches: ArgMatches) {
    LUA.with(|lua| {
           let mut lua = lua.borrow_mut();
           info!("Loading Awesome configuration...");
           let lib_paths =
               matches.values_of("lua lib search").unwrap_or_default().collect::<Vec<_>>();
           let config = matches.value_of("config");
           load_config(&mut *lua, config, lib_paths.as_slice());
           load_shims(&mut *lua);
       });
    enter_glib_loop();
}

fn emit_refresh(lua: &Lua) {
    if let Err(err) = signal::global_emit_signal(lua, ("refresh".to_owned(), Value::Nil)) {
        error!("Internal error while emitting 'refresh' signal: {}", err);
    }
}

/// Main loop of the Lua thread:
///
/// * Initialise the Lua state
/// * Run a GMainLoop
pub fn enter_glib_loop() { MAIN_LOOP.with(|main_loop| main_loop.borrow().run()); }

pub fn terminate() { MAIN_LOOP.with(|main_loop| main_loop.borrow().quit()) }

/// Checks that the first configuration file used is syntactically correct.
///
/// If the inner io::Result is not `Ok(())` we could not read any config files.
pub fn syntax_check(cmdline_path: Option<&str>) -> Result<(), io::Result<rlua::Error>> {
    let (path, mut file) = get_config(cmdline_path).map_err(Err)?;
    let mut file_contents = String::new();
    file.read_to_string(&mut file_contents).map_err(Err)?;
    LUA.with(|lua| {
           let lua = lua.borrow();
           let res =
               lua.load(file_contents.as_str(), path.to_str()).map(|_| ()).map_err(|err| Ok(err));
           res
       })
}

/// Register all the Rust functions for the lua libraries
pub fn register_libraries(lua: &Lua, lib_paths: &[&str]) -> rlua::Result<()> {
    trace!("Setting up Lua libraries");
    // TODO Is this awesome init code necessary?
    let init_code = include_str!("../../../lib/lua/init.lua");
    lua.exec::<()>(init_code, Some("init.lua"))?;
    let globals = lua.globals();
    globals.set("type", lua.create_function(type_override)?)?;
    init_libs(&lua, lib_paths).expect("Could not initialize awesome compatibility modules");
    Ok(())
}

fn init_libs(lua: &Lua, lib_paths: &[&str]) -> rlua::Result<()> {
    use objects::*;
    use *;
    setup_awesome_path(lua, lib_paths)?;
    setup_global_signals(lua)?;
    setup_xcb_connection(lua)?;
    button::init(lua)?;
    awesome::init(lua)?;
    key::init(lua)?;
    client::init(lua)?;
    screen::init(lua)?;
    keygrabber::init(lua)?;
    root::init(lua)?;
    mouse::init(lua)?;
    tag::init(lua)?;
    drawin::init(lua)?;
    drawable::init(lua)?;
    mousegrabber::init(lua)?;
    dbus::lua_init(lua)?;
    Ok(())
}

/// This function behaves just like Lua's built-in type() function, but also
/// recognises classes and returns special names for them.
fn type_override(_lua: &Lua, arg: Value) -> rlua::Result<String> {
    // Lua's type() returns the result of lua_typename(), but rlua does not make
    // that available to us, so write our own.
    Ok(match arg {
           Value::Error(e) => return Err(e),
           Value::Nil => "nil",
           Value::Boolean(_) => "boolean",
           Value::LightUserData(_) => "userdata",
           Value::Integer(_) => "number",
           Value::Number(_) => "number",
           Value::String(_) => "string",
           Value::Function(_) => "function",
           Value::Thread(_) => "thread",
           Value::Table(_) => "table",
           Value::UserData(o) => {
               // Handle our own objects specially: Get the object's class from its user
               // value's metatable's __class entry. Then get the class name
               // from the class's user value's metatable's name entry.
               return o.get_user_value::<Table>()
                       .ok()
                       .and_then(|table| table.get_metatable())
                       .and_then(|meta| meta.raw_get::<_, AnyUserData>("__class").ok())
                       .and_then(|class| class.get_user_value::<Table>().ok())
                       .map(|table| table.raw_get("name"))
                       .unwrap_or_else(|| Ok("userdata".into()))
           }
       }.into())
}
<commit_msg>awesome: fix running "awesome" by "make run"<commit_after>//! Lua interpreter setup and configuration reading.

mod config;
mod utils;

use self::config::{get_config, load_config};
pub use self::{config::log_error, utils::*};

use clap::ArgMatches;
use glib::MainLoop;
use rlua::{self, AnyUserData, Lua, Table, Value};

use std::{cell::{Cell, RefCell},
          fs::File,
          io::{self, Read},
          path::PathBuf};

use common::signal;

/// Path to the Awesome shims.
const SHIMS_PATH: &str = "../../tests/awesome/tests/examples/shims/";
/// Shims to load
const SHIMS: [&str; 11] = ["awesome",
                           "root",
                           "tag",
                           "screen",
                           "client",
                           "mouse",
                           "drawin",
                           "button",
                           "keygrabber",
                           "mousegrabber",
                           "key"];

thread_local! {
    // NOTE The debug library does some powerful reflection that can do crazy things,
    // which is why it's unsafe to load.

    /// Global Lua state.
    pub static LUA: RefCell<Lua> = RefCell::new(unsafe { Lua::new_with_debug() });

    /// If set then we have restarted the Lua thread. We need to replace LUA when it's not borrowed.
    pub static NEXT_LUA: Cell<bool> = Cell::new(false);

    /// Main GLib loop
    static MAIN_LOOP: RefCell<MainLoop> = RefCell::new(MainLoop::new(None, false));
}

/// Loads shim code to act like Awesome.
///
/// To be compatible this must eventually be removed.
///
/// Best way to help out: comment out one of these lines, fix what breaks.
fn load_shims(lua: &Lua) {
    let globals = lua.globals();
    let package: Table = globals.get("package").unwrap();
    let mut path = package.get::<_, String>("path").unwrap();
    let shims_path: PathBuf = std::env::current_exe().unwrap().parent().unwrap().join(SHIMS_PATH);
    path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua", shims_path.to_str().unwrap()));
    package.set("path", path).unwrap();
    for shim in SHIMS.iter() {
        let mut path = shims_path.clone();
        path.push(format!("{}.lua", shim));
        let shims_path_str = path.to_str().unwrap();
        let mut file =
            File::open(path.clone()).expect(&format!("Could not open {}", shims_path_str));
        let mut contents = String::new();
        file.read_to_string(&mut contents).expect(&format!("Could not read {}", shims_path_str));
        let obj = lua.exec::<rlua::Value>(contents.as_str(), None)
                     .expect(&format!("Could not read {}", shims_path_str));
        globals.set(*shim, obj).expect("Could not set global object");
    }
}

/// Sets up the Lua environment for the user code.
///
/// This environment is also necessary for some Wayland callbacks,
/// so it should be called as soon as possible.
pub fn init_awesome_libraries(lib_paths: &[&str]) {
    info!("Setting up Awesome libraries");
    LUA.with(|lua| {
           register_libraries(&*lua.borrow(), lib_paths).expect("Could not register lua libraries");
       });
}

/// Runs user code from the config through the awesome compatibility layer.
///
/// It then enters the glib/wayland main loop to listen for events.
pub fn run_awesome(matches: ArgMatches) {
    LUA.with(|lua| {
           let mut lua = lua.borrow_mut();
           info!("Loading Awesome configuration...");
           let lib_paths =
               matches.values_of("lua lib search").unwrap_or_default().collect::<Vec<_>>();
           let config = matches.value_of("config");
           load_config(&mut *lua, config, lib_paths.as_slice());
           load_shims(&mut *lua);
       });
    enter_glib_loop();
}

fn emit_refresh(lua: &Lua) {
    if let Err(err) = signal::global_emit_signal(lua, ("refresh".to_owned(), Value::Nil)) {
        error!("Internal error while emitting 'refresh' signal: {}", err);
    }
}

/// Main loop of the Lua thread:
///
/// * Initialise the Lua state
/// * Run a GMainLoop
pub fn enter_glib_loop() { MAIN_LOOP.with(|main_loop| main_loop.borrow().run()); }

pub fn terminate() { MAIN_LOOP.with(|main_loop| main_loop.borrow().quit()) }

/// Checks that the first configuration file used is syntactically correct.
///
/// If the inner io::Result is not `Ok(())` we could not read any config files.
pub fn syntax_check(cmdline_path: Option<&str>) -> Result<(), io::Result<rlua::Error>> {
    let (path, mut file) = get_config(cmdline_path).map_err(Err)?;
    let mut file_contents = String::new();
    file.read_to_string(&mut file_contents).map_err(Err)?;
    LUA.with(|lua| {
           let lua = lua.borrow();
           let res =
               lua.load(file_contents.as_str(), path.to_str()).map(|_| ()).map_err(|err| Ok(err));
           res
       })
}

/// Register all the Rust functions for the lua libraries
pub fn register_libraries(lua: &Lua, lib_paths: &[&str]) -> rlua::Result<()> {
    trace!("Setting up Lua libraries");
    // TODO Is this awesome init code necessary?
    let init_code = include_str!("../../../lib/lua/init.lua");
    lua.exec::<()>(init_code, Some("init.lua"))?;
    let globals = lua.globals();
    globals.set("type", lua.create_function(type_override)?)?;
    init_libs(&lua, lib_paths).expect("Could not initialize awesome compatibility modules");
    Ok(())
}

fn init_libs(lua: &Lua, lib_paths: &[&str]) -> rlua::Result<()> {
    use objects::*;
    use *;
    setup_awesome_path(lua, lib_paths)?;
    setup_global_signals(lua)?;
    setup_xcb_connection(lua)?;
    button::init(lua)?;
    awesome::init(lua)?;
    key::init(lua)?;
    client::init(lua)?;
    screen::init(lua)?;
    keygrabber::init(lua)?;
    root::init(lua)?;
    mouse::init(lua)?;
    tag::init(lua)?;
    drawin::init(lua)?;
    drawable::init(lua)?;
    mousegrabber::init(lua)?;
    dbus::lua_init(lua)?;
    Ok(())
}

/// This function behaves just like Lua's built-in type() function, but also
/// recognises classes and returns special names for them.
fn type_override(_lua: &Lua, arg: Value) -> rlua::Result<String> {
    // Lua's type() returns the result of lua_typename(), but rlua does not make
    // that available to us, so write our own.
    Ok(match arg {
           Value::Error(e) => return Err(e),
           Value::Nil => "nil",
           Value::Boolean(_) => "boolean",
           Value::LightUserData(_) => "userdata",
           Value::Integer(_) => "number",
           Value::Number(_) => "number",
           Value::String(_) => "string",
           Value::Function(_) => "function",
           Value::Thread(_) => "thread",
           Value::Table(_) => "table",
           Value::UserData(o) => {
               // Handle our own objects specially: Get the object's class from its user
               // value's metatable's __class entry. Then get the class name
               // from the class's user value's metatable's name entry.
               return o.get_user_value::<Table>()
                       .ok()
                       .and_then(|table| table.get_metatable())
                       .and_then(|meta| meta.raw_get::<_, AnyUserData>("__class").ok())
                       .and_then(|class| class.get_user_value::<Table>().ok())
                       .map(|table| table.raw_get("name"))
                       .unwrap_or_else(|| Ok("userdata".into()))
           }
       }.into())
}
<|endoftext|>


<commit_before>extern crate collections;
use std::io::{File, Open, Write, TempDir};
use std::os::args;
use std::from_str::from_str;
use collections::priority_queue::PriorityQueue;
#[cfg(test)]
use std::io::{ReadWrite, SeekSet};

/*
 * an entry is the number that we read and the file it came from, so after we took
 * out one Entry from the priority queue, we need to know where to take the next number
 * from.
 */
struct Entry {
	value: u64,
	source: File,
}

/* The priority queue depends on the ordering relation and always returns the biggest */
impl Ord for Entry {
	// lesser than implementation
	fn lt(&self, other: &Entry) -> bool {
		// we invert: for us the smallest will have the highest priority
		!(self.value < other.value)
	}
}

/* ordering needs equality for some reason, so there */
impl Eq for Entry {
	fn eq(&self, other: &Entry) -> bool {
		self.value == other.value
	}
}

/* A struct to hold our queue */
struct PriorityFile {
	queue: PriorityQueue<Entry>,
}

/*
 * 'Class' that takes a list of files and does a k-way merge of the smallest values
 * from the files
 */
impl PriorityFile {
	pub fn new(files: Vec<File>) -> PriorityFile {
		let mut queue: PriorityQueue<Entry> = PriorityQueue::new();
		// now that we got the queue, populate it with initial values

		// move_iter is required to get the values themselves, not borrowed pointers to them
		for mut f in files.move_iter() {
			// read from file, append to queue
			let number = match f.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			queue.push(Entry {value: number, source: f});
		};
		PriorityFile {queue: queue}
	}

	/* Returns the next smallest number from the list of files or None if exhausted */
	pub fn next(&mut self) -> Option<u64> {
		match self.queue.maybe_pop() {
			Some(mut res) => {
				let v = res.value;
				match res.source.read_le_u64() {
					Ok(num) => self.queue.push(Entry {value: num, source: res.source}),
					Err(_) => (),
				};
				Some(v)
			},
			None => None,
		}
	}
}

fn externalSort(mut fdInput: File, size: u64, mut fdOutput: File, memSize: u64) {
	let runs = size / memSize;
	let items_per_run = (memSize / 8) as uint;

	println!("There will be {} runs with {} elements each.", runs, items_per_run);

	/* initialize a Vector. Rust Vectors grow but this one will stay fixed */
	let mut run: Vec<u64> = Vec::with_capacity(items_per_run);
	// preallocate it with zeroes
	for _ in range(0, items_per_run) {
		run.push(0_u64);
	}

	// let's create a temporary directory to store the sorted chunks
	// neat: TempDir deletes the directory and its contents when it goes out of
	// scope
	let overflow_dir = match TempDir::new("externalsort") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let overflow_path = overflow_dir.path();
	println!("temp dir path {}", overflow_path.display());

	// start the sorting runs
	for n in range(0, runs) {
		// iterate over our 'run' buffer and read from the input file
		// I suppose the values are little endian, which considering we are most
		// likely on x86, is a reasonable assumption
		for element in run.mut_iter() {
			let number = match fdInput.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			*element = number;
		}
		// O(n log n) sort from the stdlib, hopefully more or less equivalent to
		// C++ std::sort
		run.sort();

		// now write out the results into numbered files
		let file_path = overflow_path.join(n.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};

		for &element in run.iter() {
			match file_file.write_le_u64(element) {
				Ok (_) => (),
				Err(e) => fail!("writing overflow failed: {}", e),
			};
		};
	};

	/* sorting done, now merging */

	// collect all file handles. Hopefully less than 4096
	let mut files = Vec::with_capacity(runs as uint);
	for n in range(0, runs) {
		let file_path = overflow_path.join(n.to_str());
		let fd = match File::open(&file_path) {
			Ok(f) => f,
			Err(e) => fail!("overflow file opening error {}", e),
		};
		files.push(fd);
	}

	// we got a nice class here that spits out sorted numbers until exhausted
	let mut pf = PriorityFile::new(files);
	loop {
		match pf.next() {
			// if we got a number, write it to the output
			Some (number) => match fdOutput.write_le_u64(number) {
				Ok(_) => (),
				Err(e) => fail!("writing output file failed: {}", e),
			},
			None => break,
		};
	};
}

fn main() {
	if args().len() < 4 {
		fail!("Argument error: <inputFile> <outputFile> <memoryBufferInMB>");
	}
	let input_file_path = &Path::new(args()[1]);
	let size = match input_file_path.stat() {
		Ok(stat) => stat.size,
		Err(e) => fail!("Couldn't read {}", e),
	};
	let fin = match File::open(input_file_path) {
		Ok(f) => f,
		Err(e) => fail!("input file error: {}", e),
	};
	let fout = match File::open_mode(&Path::new(args()[2]), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	let buffer_size:u64 = match from_str(args()[3]) {
		Some(num) => num,
		None => fail!("Not numeric input"),
	};
	println!("Input file size {}", size);

	externalSort(fin, size, fout, buffer_size * 1024 * 1024);
}

#[test]
fn generate_5gb_and_sort() {
	let mut random = match File::open(&Path::new("/dev/urandom")) {
		Ok(f) => f,
		Err(e) => fail!("Error opening urandom: {}", e),
	};

	let test_dir = match TempDir::new("externalsort-test") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let test_path = test_dir.path();

	let mut unordered_nums = match File::open_mode(&test_path.join("input"), Open, ReadWrite) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut buffer = [0, .. 1024*1024];
	let mut left = 1 * 1024;
	while left > 0 {
		random.read(buffer);
		unordered_nums.write(buffer);
		left -= 1;
	}

	unordered_nums.seek(0, SeekSet);
	let ordered_nums = match File::open_mode(&test_path.join("output"), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	externalSort(unordered_nums, 1024 * 1024 * 1024 * 1, ordered_nums, 1024 * 1024 * 200);
	let mut ordered_nums = match File::open(&test_path.join("output")) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut last = 0_u64;
	loop {
		let number = match ordered_nums.read_le_u64() {
			Ok(num) => num,
			Err(e) => fail!("failed to read u64 from file: {}", e),
		};
		assert!(number >= last);
		last = number;
	}
}
<commit_msg>Wrote a function to read n u64 values<commit_after>extern crate collections;
use std::io::{File, Open, Write, TempDir};
use std::os::args;
use std::from_str::from_str;
use collections::priority_queue::PriorityQueue;
#[cfg(test)]
use std::io::{ReadWrite, SeekSet};

/*
 * an entry is the number that we read and the file it came from, so after we took
 * out one Entry from the priority queue, we need to know where to take the next number
 * from.
 */
struct Entry {
	value: u64,
	source: File,
}

/* The priority queue depends on the ordering relation and always returns the biggest */
impl Ord for Entry {
	// lesser than implementation
	fn lt(&self, other: &Entry) -> bool {
		// we invert: for us the smallest will have the highest priority
		!(self.value < other.value)
	}
}

/* ordering needs equality for some reason, so there */
impl Eq for Entry {
	fn eq(&self, other: &Entry) -> bool {
		self.value == other.value
	}
}

/* A struct to hold our queue */
struct PriorityFile {
	queue: PriorityQueue<Entry>,
}

/*
 * 'Class' that takes a list of files and does a k-way merge of the smallest values
 * from the files
 */
impl PriorityFile {
	pub fn new(files: Vec<File>) -> PriorityFile {
		let mut queue: PriorityQueue<Entry> = PriorityQueue::new();
		// now that we got the queue, populate it with initial values

		// move_iter is required to get the values themselves, not borrowed pointers to them
		for mut f in files.move_iter() {
			// read from file, append to queue
			let number = match f.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			queue.push(Entry {value: number, source: f});
		};
		PriorityFile {queue: queue}
	}

	/* Returns the next smallest number from the list of files or None if exhausted */
	pub fn next(&mut self) -> Option<u64> {
		match self.queue.maybe_pop() {
			Some(mut res) => {
				let v = res.value;
				match res.source.read_le_u64() {
					Ok(num) => self.queue.push(Entry {value: num, source: res.source}),
					Err(_) => (),
				};
				Some(v)
			},
			None => None,
		}
	}
}

fn read_u64(mut from: File, n: uint) -> Vec<u64> {
	let mut buffer: Vec<u8> = Vec::with_capacity(n * 8);
	for _ in range(0, n*8) {
		buffer.push(0);
	};

	{
		let mut buf = buffer.as_mut_slice();
		println!("slice len {}", buf.len());
		match from.read(buf) {
			Ok(_) => (),
			Err(e) => fail!("reading failed {}", e),
		};
	};

	let mut read: Vec<u64> = unsafe { std::cast::transmute(buffer) };
	let read_len = read.len();
	unsafe { read.set_len(read_len / 8); };
	read
}

fn externalSort(mut fdInput: File, size: u64, mut fdOutput: File, memSize: u64) {
	let runs = size / memSize;
	let items_per_run = (memSize / 8) as uint;

	println!("There will be {} runs with {} elements each.", runs, items_per_run);

	/* initialize a Vector. Rust Vectors grow but this one will stay fixed */
	let mut run: Vec<u64> = Vec::with_capacity(items_per_run);
	// preallocate it with zeroes
	for _ in range(0, items_per_run) {
		run.push(0_u64);
	}

	// let's create a temporary directory to store the sorted chunks
	// neat: TempDir deletes the directory and its contents when it goes out of
	// scope
	let overflow_dir = match TempDir::new("externalsort") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let overflow_path = overflow_dir.path();
	println!("temp dir path {}", overflow_path.display());

	// start the sorting runs
	for n in range(0, runs) {
		// iterate over our 'run' buffer and read from the input file
		// I suppose the values are little endian, which considering we are most
		// likely on x86, is a reasonable assumption
		for element in run.mut_iter() {
			let number = match fdInput.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			*element = number;
		}
		// O(n log n) sort from the stdlib, hopefully more or less equivalent to
		// C++ std::sort
		run.sort();

		// now write out the results into numbered files
		let file_path = overflow_path.join(n.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};

		for &element in run.iter() {
			match file_file.write_le_u64(element) {
				Ok (_) => (),
				Err(e) => fail!("writing overflow failed: {}", e),
			};
		};
	};

	/* sorting done, now merging */

	// collect all file handles. Hopefully less than 4096
	let mut files = Vec::with_capacity(runs as uint);
	for n in range(0, runs) {
		let file_path = overflow_path.join(n.to_str());
		let fd = match File::open(&file_path) {
			Ok(f) => f,
			Err(e) => fail!("overflow file opening error {}", e),
		};
		files.push(fd);
	}

	// we got a nice class here that spits out sorted numbers until exhausted
	let mut pf = PriorityFile::new(files);
	loop {
		match pf.next() {
			// if we got a number, write it to the output
			Some (number) => match fdOutput.write_le_u64(number) {
				Ok(_) => (),
				Err(e) => fail!("writing output file failed: {}", e),
			},
			None => break,
		};
	};
}

fn main() {
	if args().len() < 4 {
		fail!("Argument error: <inputFile> <outputFile> <memoryBufferInMB>");
	}
	let input_file_path = &Path::new(args()[1]);
	let size = match input_file_path.stat() {
		Ok(stat) => stat.size,
		Err(e) => fail!("Couldn't read {}", e),
	};
	let fin = match File::open(input_file_path) {
		Ok(f) => f,
		Err(e) => fail!("input file error: {}", e),
	};
	let fout = match File::open_mode(&Path::new(args()[2]), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	let buffer_size:u64 = match from_str(args()[3]) {
		Some(num) => num,
		None => fail!("Not numeric input"),
	};
	println!("Input file size {}", size);

	//let values = read_u64(fin, 2);
	//println!("Values: {}", values);
	externalSort(fin, size, fout, buffer_size * 1024 * 1024);
}

#[test]
fn generate_5gb_and_sort() {
	let mut random = match File::open(&Path::new("/dev/urandom")) {
		Ok(f) => f,
		Err(e) => fail!("Error opening urandom: {}", e),
	};

	let test_dir = match TempDir::new("externalsort-test") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let test_path = test_dir.path();

	let mut unordered_nums = match File::open_mode(&test_path.join("input"), Open, ReadWrite) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut buffer = [0, .. 1024*1024];
	let mut left = 1 * 1024;
	while left > 0 {
		random.read(buffer);
		unordered_nums.write(buffer);
		left -= 1;
	}

	unordered_nums.seek(0, SeekSet);
	let ordered_nums = match File::open_mode(&test_path.join("output"), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	externalSort(unordered_nums, 1024 * 1024 * 1024 * 1, ordered_nums, 1024 * 1024 * 200);
	let mut ordered_nums = match File::open(&test_path.join("output")) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut last = 0_u64;
	loop {
		let number = match ordered_nums.read_le_u64() {
			Ok(num) => num,
			Err(e) => fail!("failed to read u64 from file: {}", e),
		};
		assert!(number >= last);
		last = number;
	}
}
<|endoftext|>


<commit_before>use std::str;
use std::vec::{Vec};

use super::super::error::{Result, PathfinderError};
use super::super::middleware::{Middleware};

use cli::{CliOptions};
use tungstenite::handshake::server::{Request};

/// A middleware class, that will check a specified token in WebSocket
/// headers. Otherwise returns an error, if it isn't specified or invalid.
pub struct JwtTokenMiddleware {
    jwt_secret: String
}

impl JwtTokenMiddleware {
    pub fn new(cli: &CliOptions) -> JwtTokenMiddleware {
        JwtTokenMiddleware {
            jwt_secret: cli.jwt_secret_key.clone()
        }
    }
}

impl Middleware for JwtTokenMiddleware {
    fn process_request(&self, request: &Request) -> Result<Option<Vec<(String, String)>>> {
        match request.headers.find_first("Sec-WebSocket-Protocol") {
             Some(token) => {
                 let parsed_value = str::from_utf8(token).unwrap();
                 let extra_headers = vec![
                    (String::from("Sec-WebSocket-Protocol"), String::from(parsed_value))
                 ];
                 Ok(Some(extra_headers))
             },
             None => {
                 let message = String::from("Token was not found");
                 Err(PathfinderError::AuthenticationError(message))
             }
        }
    }
}
<commit_msg>Implemented extracting token from a header<commit_after>use std::str;
use std::vec::{Vec};

use super::super::error::{Result, PathfinderError};
use super::super::middleware::{Middleware};

use cli::{CliOptions};
use tungstenite::handshake::server::{Request};

/// A middleware class, that will check a specified token in WebSocket
/// headers. Otherwise returns an error, if it isn't specified or invalid.
pub struct JwtTokenMiddleware {
    jwt_secret: String
}

impl JwtTokenMiddleware {
    pub fn new(cli: &CliOptions) -> JwtTokenMiddleware {
        JwtTokenMiddleware {
            jwt_secret: cli.jwt_secret_key.clone()
        }
    }

    fn extract_token_from_header(&self, raw_token: &[u8]) -> Result<String> {
        match str::from_utf8(raw_token) {
            Ok(parsed_value) => Ok(String::from(parsed_value)),
            Err(_) => {
                let message = String::from("Token is invalid.");
                Err(PathfinderError::AuthenticationError(message))
            }
        }
    }
}

impl Middleware for JwtTokenMiddleware {
    fn process_request(&self, request: &Request) -> Result<Option<Vec<(String, String)>>> {
        match request.headers.find_first("Sec-WebSocket-Protocol") {
             Some(raw_token) => {
                 let token = self.extract_token_from_header(raw_token)?;
                 let extra_headers = vec![(String::from("Sec-WebSocket-Protocol"), token)];
                 Ok(Some(extra_headers))
             },
             None => {
                 let message = String::from("Token was not found");
                 Err(PathfinderError::AuthenticationError(message))
             }
        }
    }
}
<|endoftext|>


<commit_before>extern crate ggez;
extern crate ggez_goodies;
use ggez::conf;
use ggez::game::{Game, GameState};
use ggez::{GameResult, Context};
use ggez::graphics;
use ggez::timer;
use std::time::Duration;

use ggez_goodies::scene::*;

struct MainState {
    font: graphics::Font,
}

struct SceneState1 {
    time_unloaded: f64,
}

struct Scene1 {
    current_time: f64,
}

impl SceneState<MainState> for SceneState1 {
    fn load(&mut self) -> Box<Scene<MainState>> {
        Box::new(Scene1 { current_time: 0.0 })
    }
    fn name(&self) -> &str {
        "Test state"
    }
}

impl Scene<MainState> for Scene1 {
    fn unload(&mut self) -> Box<SceneState<MainState>> {
        Box::new(SceneState1 { time_unloaded: 0.0 })
    }

    fn update(&mut self,
              _ctx: &mut ggez::Context,
              _dt: Duration,
              _state: &mut MainState)
              -> GameResult<()> {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut ggez::Context, state: &mut MainState) -> GameResult<()> {
        ctx.renderer.clear();
        let text = &mut graphics::Text::new(ctx, "Hello world!", &state.font)?;
        try!(graphics::draw(ctx, text, None, None));
        ctx.renderer.present();
        timer::sleep_until_next_frame(ctx, 60);
        Ok(())
    }
}

impl Loadable<MainState> for MainState {
    fn load(ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<Self>
        where Self: Sized
    {
        let font = graphics::Font::new(ctx, "DejaVuSerif.ttf", 48)?;
        Ok(MainState { font: font })
    }
    fn default_scene() -> Box<SceneState<MainState> + 'static> {
        Box::new(SceneState1 { time_unloaded: 0.0 })
    }
}

pub fn main() {
    let c = conf::Conf::new();
    let mut game: Game<SceneManager<MainState>> = Game::new("scenetest", c).unwrap();
    if let Err(e) = game.run() {
        println!("Error encountered: {:?}", e);
    } else {
        println!("Game exited cleanly.");
    }
}
<commit_msg>scene_test now does stuff!<commit_after>extern crate ggez;
extern crate ggez_goodies;
use ggez::conf;
use ggez::game::{Game, GameState};
use ggez::{GameResult, Context};
use ggez::graphics;
use ggez::timer;
use std::time::Duration;

use ggez_goodies::scene::*;

struct MainState {
    font: graphics::Font,
}

struct SceneState1 {
    time_unloaded: f64,
    name: String,
}

struct Scene1 {
    current_time: f64,
    name: String,
}

impl SceneState<MainState> for SceneState1 {
    fn load(&mut self) -> Box<Scene<MainState>> {
        Box::new(Scene1 {
            current_time: self.time_unloaded,
            name: self.name.clone(),
        })
    }
    fn name(&self) -> &str {
        &self.name
    }
}

impl Scene<MainState> for Scene1 {
    fn unload(&mut self) -> Box<SceneState<MainState>> {
        Box::new(SceneState1 {
            time_unloaded: self.current_time,
            name: self.name.clone(),
        })
    }

    fn update(&mut self,
              _ctx: &mut ggez::Context,
              dt: Duration,
              _state: &mut MainState)
              -> GameResult<()> {
        let seconds = timer::duration_to_f64(dt);
        self.current_time += seconds;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut ggez::Context, state: &mut MainState) -> GameResult<()> {
        ctx.renderer.clear();
        let message = format!("Scene '{}' has been running for {:0.2} seconds",
                              self.name,
                              self.current_time);
        let text = &mut graphics::Text::new(ctx, &message, &state.font)?;
        let text_rect = graphics::Rect::new(10, 240, text.width(), text.height());
        try!(graphics::draw(ctx, text, None, Some(text_rect)));
        ctx.renderer.present();
        timer::sleep_until_next_frame(ctx, 60);
        Ok(())
    }
}

impl Loadable<MainState> for MainState {
    fn load(ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<Self>
        where Self: Sized
    {
        let font = graphics::Font::new(ctx, "DejaVuSerif.ttf", 16)?;
        Ok(MainState { font: font })
    }
    fn default_scene() -> Box<SceneState<MainState> + 'static> {
        Box::new(SceneState1 {
            time_unloaded: 0.0,
            name: "Test scene".to_string(),
        })
    }
}

pub fn main() {
    let c = conf::Conf::new();
    let mut game: Game<SceneManager<MainState>> = Game::new("scenetest", c).unwrap();
    if let Err(e) = game.run() {
        println!("Error encountered: {:?}", e);
    } else {
        println!("Game exited cleanly.");
    }
}
<|endoftext|>


<commit_before>//! Demonstrates various projection and matrix fiddling/testing.
//!
extern crate ggez;
extern crate nalgebra;

use ggez::event;
use ggez::graphics::{self, DrawMode};
use ggez::{Context, GameResult};
use nalgebra as na;
use std::env;
use std::path;

struct MainState {
    pos_x: f32,
    gridmesh: graphics::Mesh,
    angle: graphics::Image,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let angle = graphics::Image::new(ctx, "/angle.png")?;
        let grid_interval = 100.0;
        let grid_size = 10;
        let grid_point_radius = 5.0;
        let gridmesh_builder = &mut graphics::MeshBuilder::new();
        for x in 0..grid_size {
            for y in 0..grid_size {
                let point = na::Point2::new(x as f32 * grid_interval, y as f32 * grid_interval);
                gridmesh_builder
                    .circle(DrawMode::Fill, point, grid_point_radius, 2.0);
            }
        }
        let gridmesh = gridmesh_builder.build(ctx)?;
        let s = MainState { pos_x: 0.0, gridmesh, angle };
        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        self.pos_x = self.pos_x % 800.0 + 1.0;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());

        let origin: na::Point2<f32> = na::origin();
        graphics::draw(ctx, &self.gridmesh, (origin, graphics::BLACK))?;

        let param = graphics::DrawParam::new()
            .dest(na::Point2::new(300.0, 300.0))
            .rotation(self.pos_x / 100.0)
            .offset(na::Point2::new(64.0, 64.0))
        ;
        graphics::draw(
            ctx,
            &self.angle,
            param
        )?;
        graphics::present(ctx)?;
        Ok(())
    }
}

pub fn main() -> GameResult {
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };
    let cb = ggez::ContextBuilder::new("transforms", "ggez")
        .add_resource_path(resource_dir)
        // .window_setup(ggez::conf::WindowSetup::default().srgb(false))
    ;
    let (ctx, event_loop) = &mut cb.build()?;
    let state = &mut MainState::new(ctx)?;
    event::run(ctx, event_loop, state)
}
<commit_msg>Working on transform example more.<commit_after>//! Demonstrates various projection and matrix fiddling/testing.
//!
extern crate ggez;
extern crate nalgebra;

use ggez::event::{self, KeyCode, KeyMods};
use ggez::graphics::{self, DrawMode};
use ggez::{Context, GameResult};
use nalgebra as na;
use std::env;
use std::path;

struct MainState {
    pos_x: f32,
    gridmesh: graphics::Mesh,
    angle: graphics::Image,
    screen_bounds: Vec<graphics::Rect>,
    screen_bounds_idx: usize,
}

impl MainState {
    const GRID_INTERVAL: f32 = 100.0;
    const GRID_SIZE: usize = 10;
    const GRID_POINT_RADIUS: f32 = 5.0;

    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let angle = graphics::Image::new(ctx, "/angle.png")?;
        let gridmesh_builder = &mut graphics::MeshBuilder::new();
        for x in 0..Self::GRID_SIZE {
            for y in 0..Self::GRID_SIZE {
                let point = na::Point2::new(x as f32 * Self::GRID_INTERVAL, y as f32 * Self::GRID_INTERVAL);
                gridmesh_builder
                    .circle(DrawMode::Fill, point, Self::GRID_POINT_RADIUS, 2.0);
            }
        }
        let gridmesh = gridmesh_builder.build(ctx)?;
        // An array of rects to cycle the screen coordinates through.
        let screen_bounds = vec![
            graphics::Rect::new(0.0, 0.0, 800.0, 600.0),
            graphics::Rect::new(0.0, 600.0, 800.0, -600.0),
        ];
        let screen_bounds_idx = 0;
        let s = MainState {
            pos_x: 0.0,
            gridmesh,
            angle,
            screen_bounds,
            screen_bounds_idx,
        };
        Ok(s)
    }

    fn draw_coord_labels(&self, ctx: &mut Context) -> GameResult {

        for x in 0..Self::GRID_SIZE {
            for y in 0..Self::GRID_SIZE {
                let point = na::Point2::new(x as f32 * Self::GRID_INTERVAL, y as f32 * Self::GRID_INTERVAL);
                let s = format!("({}, {})", point.x, point.y);
                let t = graphics::Text::new(s);
                graphics::queue_text(ctx, &t, point, None);
            }
        }
        graphics::draw_queued_text(ctx, graphics::DrawParam::default())
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        self.pos_x = self.pos_x % 800.0 + 1.0;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());

        let origin: na::Point2<f32> = na::origin();
        graphics::draw(ctx, &self.gridmesh, (origin, graphics::BLACK))?;

        let param = graphics::DrawParam::new()
            .dest(na::Point2::new(400.0, 800.0))
            // .rotation(self.pos_x / 100.0)
            // .offset(na::Point2::new(64.0, 64.0))
            .scale(na::Vector2::new(0.5, 0.5))
            // .src(graphics::Rect::new(0.0, 0.0, 0.5, 0.5))
            // .shear(na::Point2::new(0.0, self.pos_x / 100.0))
        ;

        self.draw_coord_labels(ctx)?;

        graphics::draw(
            ctx,
            &self.angle,
            param
        )?;
        graphics::present(ctx)?;
        Ok(())
    }

    fn key_down_event(
        &mut self,
        ctx: &mut Context,
        keycode: KeyCode,
        _keymod: KeyMods,
        _repeat: bool
    ) {
        match keycode {
            event::KeyCode::Space => {
                self.screen_bounds_idx = (self.screen_bounds_idx + 1) % self.screen_bounds.len();
                graphics::set_screen_coordinates(ctx, self.screen_bounds[self.screen_bounds_idx]).unwrap();
            },
            _ => ()
        }
    }
}

pub fn main() -> GameResult {
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };
    let cb = ggez::ContextBuilder::new("transforms", "ggez")
        .add_resource_path(resource_dir)
        // .window_setup(ggez::conf::WindowSetup::default().srgb(false))
    ;
    let (ctx, event_loop) = &mut cb.build()?;
    let state = &mut MainState::new(ctx)?;
    event::run(ctx, event_loop, state)
}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;
#[macro_use]
extern crate chomp;

use test::Bencher;

use std::iter;

use chomp::*;
use chomp::buffer::{Stream, IntoStream};

#[bench]
fn many_vec_1k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

    fn many_vec<I: Copy>(i: Input<I>) -> ParseResult<I, Vec<I>, Error<I>> {
        many(i, any)
    }

    b.iter(|| {
        data.into_stream().parse(many_vec)
    })
}

#[bench]
fn many_vec_10k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many_vec<I: Copy>(i: Input<I>) -> ParseResult<I, Vec<I>, Error<I>> {
        many(i, any)
    }

    b.iter(|| {
        data.into_stream().parse(many_vec)
    })
}
<commit_msg>Benches: Added combinators::many1, combinators::count<commit_after>#![feature(test)]
extern crate test;
#[macro_use]
extern crate chomp;

use test::Bencher;

use std::iter;

use chomp::*;
use chomp::buffer::{Stream, IntoStream};

#[bench]
fn count_vec_1k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

    fn count_vec<I: Copy>(i: Input<I>) -> ParseResult<I, Vec<I>, Error<I>> {
        count(i, 1024, any)
    }

    b.iter(|| {
        data.into_stream().parse(count_vec)
    })
}

#[bench]
fn count_vec_10k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn count_vec<I: Copy>(i: Input<I>) -> ParseResult<I, Vec<I>, Error<I>> {
        count(i, 10024, any)
    }

    b.iter(|| {
        data.into_stream().parse(count_vec)
    })
}

#[bench]
fn many_vec_1k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

    fn many_vec<I: Copy>(i: Input<I>) -> ParseResult<I, Vec<I>, Error<I>> {
        many(i, any)
    }

    b.iter(|| {
        data.into_stream().parse(many_vec)
    })
}

#[bench]
fn many_vec_10k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many_vec<I: Copy>(i: Input<I>) -> ParseResult<I, Vec<I>, Error<I>> {
        many(i, any)
    }

    b.iter(|| {
        data.into_stream().parse(many_vec)
    })
}

#[bench]
fn many1_vec_1k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

    fn many1_vec<I: Copy>(i: Input<I>) -> ParseResult<I, Vec<I>, Error<I>> {
        many1(i, any)
    }

    b.iter(|| {
        data.into_stream().parse(many1_vec)
    })
}

#[bench]
fn many1_vec_10k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many1_vec<I: Copy>(i: Input<I>) -> ParseResult<I, Vec<I>, Error<I>> {
        many1(i, any)
    }

    b.iter(|| {
        data.into_stream().parse(many1_vec)
    })
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate futures;
extern crate tokio_core;

use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::io;
use std::iter;
use std::net::SocketAddr;
use std::rc::Rc;

use futures::Future;
use futures::stream::{self, Stream};
use tokio_core::channel::{channel, Sender};
use tokio_core::io::{read_exact, write_all, Io};
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::{Core, Handle};

const MAX_BUFFERED: usize = 5;

fn main() {
    // Parse out what address we're going to listen on, defaulting to "something
    // reasonable"
    let addr = env::args().skip(1).next();
    let addr = addr.unwrap_or("127.0.0.1:8080".to_string());
    let addr: SocketAddr = addr.parse().unwrap();

    // Create the global state of our program. This involves the event loop (a
    // `Core`) to run all our I/O on, a TCP listener which we're going to accept
    // connections form, and finally the global hash map we're storing all
    // connection state in.
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let srv = TcpListener::bind(&addr, &handle).unwrap();
    println!("listening on {}", addr);
    let map = Rc::new(RefCell::new(HashMap::new()));

    // Create a small loop which will spawn off a new task for all accepted
    // connections. Each task will handle the messages for that connection
    // specifically, as well as listening for messages from other connections.
    //
    // Note that `futures::lazy` here is used for the call to `Io::split` below
    // in the `client` function, but it can mostly just be ignored.
    let srv = srv.incoming().for_each(|(socket, addr)| {
        let handle2 = handle.clone();
        let map = map.clone();
        handle.spawn(futures::lazy(move || {
            client(socket, &handle2, addr, map)
        }));
        Ok(())
    });

    core.run(srv).unwrap();
}

/// Internal state saved for each client.
///
/// The "global hash map" is a hash of socket addresses to instances of this
/// type. An instance is available for all connected clients.
struct Client {
    // A channel to send messages over to be received and written out.
    tx: Sender<Vec<u8>>,

    // Current number of pending messages. If too many messages are pending then
    // messages to this client are dropped on the floor.
    size: usize,
}

fn client(socket: TcpStream,
          handle: &Handle,
          addr: SocketAddr,
          map: Rc<RefCell<HashMap<SocketAddr, Client>>>)
          -> Box<Future<Item=(), Error=()>> {
    // First up, register our new client by creating an entry in the global
    // state map.
    let (tx, rx) = channel(handle).unwrap();
    assert!(map.borrow_mut().insert(addr, Client {
        tx: tx,
        size: 0,
    }).is_none());

    // Next, we call the `Io::split` function here to easily work with both
    // halves of the socket as an instance of `Read` and `Write`. This'll allow
    // us to independently define the logic below without having to worry about
    // Rust's ownership of the original value.
    let (reader, writer) = socket.split();

    // Here we define how to read the socket. A small infinite iterator is
    // created to form a loop over reading messages off the socket. We use the
    // `read_exact` combinator to read messages from the socket, and once a
    // message is read it's dispatched to all other clients.
    //
    // Note that once a message is read we finish one iteration of the `fold`
    // and the reader is then passed on to the next to execute.
    //
    // Also note that this is where the backpressure logic for connected clients
    // comes into play. We don't send messages to clients that have too many
    // messages queued up already.
    let map2 = map.clone();
    let infinite = stream::iter(iter::repeat(()).map(Ok::<(), io::Error>));
    let reader = infinite.fold(reader, move |reader, ()| {
        let size = read_exact(reader, [0u8]);

        let msg = size.and_then(|(rd, size)| {
            let buf = vec![0u8; size[0] as usize];
            read_exact(rd, buf)
        });

        let map = map2.clone();
        msg.map(move |(rd, buf)| {
            for peer in map.borrow_mut().values_mut() {
                if peer.size < MAX_BUFFERED {
                    peer.size += 1;
                    peer.tx.send(buf.clone()).unwrap();
                }
            }
            rd
        })
    });

    // Here we define how to write messages to our client. This simply involves
    // iterating over all messages coming off the channel and writing them out
    // as per our protocol.
    let map2 = map.clone();
    let writer = rx.fold(writer, move |writer, msg| {
        map2.borrow_mut().get_mut(&addr).unwrap().size -= 1;
        write_all(writer, [msg.len() as u8]).and_then(|(wr, _)| {
            write_all(wr, msg).map(|p| p.0)
        })
    });

    // Finally, we `select` over the read and the write halves. This means that
    // once either hits an error or finishes we're done. Note that the most
    // likely thing to happen here is the `reader` hits an error due to EOF (in
    // line with our use of `read_exact` above) which will cause the `select`
    // future to resolve.
    //
    // Once the reader/writer halves are done, we deregister ourselves from the
    // global map of connections. to free up our resources.
    let reader = reader.map(|_| ()).map_err(|_| ());
    let writer = writer.map(|_| ()).map_err(|_| ());
    Box::new(reader.select(writer).then(move |_| {
        assert!(map.borrow_mut().remove(&addr).is_some());
        Ok(())
    }))
}
<commit_msg>tokio_core::channel -> futures::sync::mpsc<commit_after>extern crate futures;
extern crate tokio_core;

use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::io;
use std::iter;
use std::net::SocketAddr;
use std::rc::Rc;

use futures::Future;
use futures::stream::{self, Stream};
use futures::sync::mpsc;
use tokio_core::io::{read_exact, write_all, Io};
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::Core;

const MAX_BUFFERED: usize = 5;

fn main() {
    // Parse out what address we're going to listen on, defaulting to "something
    // reasonable"
    let addr = env::args().skip(1).next();
    let addr = addr.unwrap_or("127.0.0.1:8080".to_string());
    let addr: SocketAddr = addr.parse().unwrap();

    // Create the global state of our program. This involves the event loop (a
    // `Core`) to run all our I/O on, a TCP listener which we're going to accept
    // connections form, and finally the global hash map we're storing all
    // connection state in.
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let srv = TcpListener::bind(&addr, &handle).unwrap();
    println!("listening on {}", addr);
    let map = Rc::new(RefCell::new(HashMap::new()));

    // Create a small loop which will spawn off a new task for all accepted
    // connections. Each task will handle the messages for that connection
    // specifically, as well as listening for messages from other connections.
    //
    // Note that `futures::lazy` here is used for the call to `Io::split` below
    // in the `client` function, but it can mostly just be ignored.
    let srv = srv.incoming().for_each(|(socket, addr)| {
        let map = map.clone();
        handle.spawn(futures::lazy(move || {
            client(socket, addr, map)
        }));
        Ok(())
    });

    core.run(srv).unwrap();
}

/// Internal state saved for each client.
///
/// The "global hash map" is a hash of socket addresses to instances of this
/// type. An instance is available for all connected clients.
struct Client {
    // A channel to send messages over to be received and written out.
    tx: mpsc::UnboundedSender<Vec<u8>>,

    // Current number of pending messages. If too many messages are pending then
    // messages to this client are dropped on the floor.
    size: usize,
}

fn client(socket: TcpStream,
          addr: SocketAddr,
          map: Rc<RefCell<HashMap<SocketAddr, Client>>>)
          -> Box<Future<Item=(), Error=()>> {
    // First up, register our new client by creating an entry in the global
    // state map.
    let (tx, rx) = mpsc::unbounded();
    assert!(map.borrow_mut().insert(addr, Client {
        tx: tx,
        size: 0,
    }).is_none());

    // Next, we call the `Io::split` function here to easily work with both
    // halves of the socket as an instance of `Read` and `Write`. This'll allow
    // us to independently define the logic below without having to worry about
    // Rust's ownership of the original value.
    let (reader, writer) = socket.split();

    // Here we define how to read the socket. A small infinite iterator is
    // created to form a loop over reading messages off the socket. We use the
    // `read_exact` combinator to read messages from the socket, and once a
    // message is read it's dispatched to all other clients.
    //
    // Note that once a message is read we finish one iteration of the `fold`
    // and the reader is then passed on to the next to execute.
    //
    // Also note that this is where the backpressure logic for connected clients
    // comes into play. We don't send messages to clients that have too many
    // messages queued up already.
    let map2 = map.clone();
    let infinite = stream::iter(iter::repeat(()).map(Ok::<(), io::Error>));
    let reader = infinite.fold(reader, move |reader, ()| {
        let size = read_exact(reader, [0u8]);

        let msg = size.and_then(|(rd, size)| {
            let buf = vec![0u8; size[0] as usize];
            read_exact(rd, buf)
        });

        let map = map2.clone();
        msg.map(move |(rd, buf)| {
            for peer in map.borrow_mut().values_mut() {
                if peer.size < MAX_BUFFERED {
                    peer.size += 1;
                    peer.tx.send(buf.clone()).unwrap();
                }
            }
            rd
        })
    });

    // Here we define how to write messages to our client. This simply involves
    // iterating over all messages coming off the channel and writing them out
    // as per our protocol.
    let map2 = map.clone();
    let rx1 = rx.map_err(|_| -> ::std::io::Error { unreachable!() });
    let writer = rx1.fold(writer, move |writer, msg| {
        map2.borrow_mut().get_mut(&addr).unwrap().size -= 1;
        write_all(writer, [msg.len() as u8]).and_then(|(wr, _)| {
            write_all(wr, msg).map(|p| p.0)
        })
    });

    // Finally, we `select` over the read and the write halves. This means that
    // once either hits an error or finishes we're done. Note that the most
    // likely thing to happen here is the `reader` hits an error due to EOF (in
    // line with our use of `read_exact` above) which will cause the `select`
    // future to resolve.
    //
    // Once the reader/writer halves are done, we deregister ourselves from the
    // global map of connections. to free up our resources.
    let reader = reader.map(|_| ()).map_err(|_| ());
    let writer = writer.map(|_| ()).map_err(|_| ());
    Box::new(reader.select(writer).then(move |_| {
        assert!(map.borrow_mut().remove(&addr).is_some());
        Ok(())
    }))
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![crate_type = "bin"]

extern crate capnp;
extern crate fdstream;
extern crate rand;

use capnp::{MessageReader, MessageBuilder};

pub mod common;

pub mod carsales_capnp {
  include!(concat!(env!("OUT_DIR"), "/carsales_capnp.rs"));
}
pub mod carsales;

pub mod catrank_capnp {
  include!(concat!(env!("OUT_DIR"), "/catrank_capnp.rs"));
}
pub mod catrank;

pub mod eval_capnp {
  include!(concat!(env!("OUT_DIR"), "/eval_capnp.rs"));
}

pub mod eval;

mod uncompressed {
    use capnp;

    pub fn write<T : ::std::io::Write, U : capnp::message::MessageBuilder>(
        writer: &mut T,
        message: &mut U) {
        capnp::serialize::write_message(writer, message).unwrap();
    }

    pub fn new_reader<R: ::std::io::BufRead>(
        input_stream : &mut R,
        options : capnp::message::ReaderOptions) -> capnp::serialize::OwnedSpaceMessageReader {
        capnp::serialize::read_message(input_stream, options).unwrap()
    }
}

mod packed {
    use capnp;
    use capnp::serialize_packed::{write_message};

    pub fn write<T : ::std::io::Write, U : capnp::message::MessageBuilder>(
        writer: &mut T,
        message: &mut U) {
        write_message(writer, message).unwrap();
    }

    pub fn new_reader<R: ::std::io::BufRead>(
        input_stream : &mut R,
        options : capnp::message::ReaderOptions) -> capnp::serialize::OwnedSpaceMessageReader {
        capnp::serialize_packed::read_message(input_stream, options).unwrap()
    }

}

const SCRATCH_SIZE : usize = 128 * 1024;

#[derive(Clone, Copy)]
pub struct NoScratch;

impl NoScratch {
    fn new_builder(&mut self, _idx : usize) -> capnp::message::MallocMessageBuilder {
        capnp::message::MallocMessageBuilder::new_default()
    }
}

pub struct UseScratch {
    scratch_space : ::std::vec::Vec<capnp::Word>
}

impl UseScratch {
    pub fn new() -> UseScratch {
        UseScratch {
            scratch_space : ::capnp::Word::allocate_zeroed_vec(SCRATCH_SIZE * 6)
        }
    }

    fn new_builder<'a>(&mut self, idx : usize) -> capnp::message::ScratchSpaceMallocMessageBuilder<'a> {
        assert!(idx < 6);
        unsafe {
            capnp::message::ScratchSpaceMallocMessageBuilder::new_default(
                ::std::slice::from_raw_parts_mut(self.scratch_space.get_unchecked_mut(idx * SCRATCH_SIZE),
                                                 SCRATCH_SIZE))
        }
    }
}

macro_rules! pass_by_object(
    ( $testcase:ident, $reuse:ident, $iters:expr ) => ({
            let mut rng = common::FastRand::new();
            for _ in 0..$iters {
                let mut message_req = $reuse.new_builder(0);
                let mut message_res = $reuse.new_builder(1);

                let expected = $testcase::setup_request(&mut rng,
                                                        message_req.init_root::<$testcase::RequestBuilder>());

                $testcase::handle_request(message_req.get_root::<$testcase::RequestBuilder>().unwrap().as_reader(),
                                          message_res.init_root::<$testcase::ResponseBuilder>());

                if !$testcase::check_response(
                    message_res.get_root::<$testcase::ResponseBuilder>().unwrap().as_reader(),
                    expected) {
                    panic!("Incorrect response.");
                }
            }
        });
    );

macro_rules! pass_by_bytes(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr ) => ({
        let mut request_bytes : ::std::vec::Vec<u8> =
            ::std::iter::repeat(0u8).take(SCRATCH_SIZE * 8).collect();
        let mut response_bytes : ::std::vec::Vec<u8> =
            ::std::iter::repeat(0u8).take(SCRATCH_SIZE * 8).collect();
        let mut rng = common::FastRand::new();
        for _ in 0..$iters {
            let mut message_req = $reuse.new_builder(0);
            let mut message_res = $reuse.new_builder(1);

            let expected = {
                let request = message_req.init_root::<$testcase::RequestBuilder>();
                $testcase::setup_request(&mut rng, request)
            };

            {
                let response = message_res.init_root::<$testcase::ResponseBuilder>();

                {
                    let mut writer : &mut[u8] = &mut request_bytes;
                    $compression::write(&mut writer, &mut message_req)
                }

                let mut request_bytes1 : &[u8] = &request_bytes;
                let message_reader = $compression::new_reader(
                    &mut request_bytes1,
                    capnp::message::DEFAULT_READER_OPTIONS);

                let request_reader : $testcase::RequestReader = message_reader.get_root().unwrap();
                $testcase::handle_request(request_reader, response);
            }

            {
                let mut writer : &mut [u8] = &mut response_bytes;
                $compression::write(&mut writer, &mut message_res)
            }

            let mut response_bytes1 : &[u8] = &response_bytes;
            let message_reader = $compression::new_reader(
                &mut response_bytes1,
                capnp::message::DEFAULT_READER_OPTIONS);

            let response_reader : $testcase::ResponseReader = message_reader.get_root().unwrap();
            if !$testcase::check_response(response_reader, expected) {
                panic!("Incorrect response.");
            }
        }
    });
    );

macro_rules! server(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr, $input:expr, $output:expr) => ({
            let mut out_buffered = ::std::io::BufWriter::new(&mut $output);
            let mut in_buffered = ::std::io::BufReader::new(&mut $input);
            for _ in 0..$iters {
                let mut message_res = $reuse.new_builder(0);

                {
                    let response = message_res.init_root::<$testcase::ResponseBuilder>();
                    let message_reader = $compression::new_reader(
                        &mut in_buffered,
                        capnp::message::DEFAULT_READER_OPTIONS);
                    let request_reader : $testcase::RequestReader = message_reader.get_root().unwrap();
                    $testcase::handle_request(request_reader, response);
                }

                $compression::write(&mut out_buffered, &mut message_res);
                out_buffered.flush().unwrap();
            }
        });
    );

macro_rules! sync_client(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr) => ({
            let mut out_stream = ::fdstream::FdStream::new(1);
            let mut in_stream = ::fdstream::FdStream::new(0);
            let mut in_buffered = ::std::io::BufReader::new(&mut in_stream);
            let mut out_buffered = ::std::io::BufWriter::new(&mut out_stream);
            let mut rng = common::FastRand::new();
            for _ in 0..$iters {
                let mut message_req = $reuse.new_builder(0);

                let expected = {
                    let request = message_req.init_root::<$testcase::RequestBuilder>();
                    $testcase::setup_request(&mut rng, request)
                };
                $compression::write(&mut out_buffered, &mut message_req);
                out_buffered.flush().unwrap();

                let message_reader = $compression::new_reader(
                    &mut in_buffered,
                    capnp::message::DEFAULT_READER_OPTIONS);
                let response_reader : $testcase::ResponseReader = message_reader.get_root().unwrap();
                assert!($testcase::check_response(response_reader, expected));

            }
        });
    );

macro_rules! pass_by_pipe(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr) => ({
        use std::process;

        let mut args : Vec<String> = ::std::env::args().collect();
        args[2] = "client".to_string();

        let mut command = process::Command::new(&args[0]);
        command.args(&args[1..args.len()]);
        command.stdin(process::Stdio::piped());
        command.stdout(process::Stdio::piped());
        command.stderr(process::Stdio::null());
        match command.spawn() {
            Ok(ref mut p) => {
                let mut child_std_out = p.stdout.take().unwrap();
                let mut child_std_in = p.stdin.take().unwrap();

                server!($testcase, $reuse, $compression, $iters, child_std_out, child_std_in);
                println!("{}", p.wait().unwrap());
            }
            Err(e) => {
                println!("could not start process: {}", e);
            }
        }
    });
    );

macro_rules! do_testcase(
    ( $testcase:ident, $mode:expr, $reuse:ident, $compression:ident, $iters:expr ) => ({
            match &*$mode {
                "object" => pass_by_object!($testcase, $reuse, $iters),
                "bytes" => pass_by_bytes!($testcase, $reuse, $compression, $iters),
                "client" => sync_client!($testcase, $reuse, $compression, $iters),
                "server" => {
                    let mut input = ::fdstream::FdStream::new(0);
                    let mut output = ::fdstream::FdStream::new(1);
                    server!($testcase, $reuse, $compression, $iters, input, output)
                }
                "pipe" => pass_by_pipe!($testcase, $reuse, $compression, $iters),
                s => panic!("unrecognized mode: {}", s)
            }
        });
    );

macro_rules! do_testcase1(
    ( $testcase:expr, $mode:expr, $reuse:ident, $compression:ident, $iters:expr) => ({
            match &*$testcase {
                "carsales" => do_testcase!(carsales, $mode, $reuse, $compression, $iters),
                "catrank" => do_testcase!(catrank, $mode, $reuse, $compression, $iters),
                "eval" => do_testcase!(eval, $mode, $reuse, $compression, $iters),
                s => panic!("unrecognized test case: {}", s)
            }
        });
    );

macro_rules! do_testcase2(
    ( $testcase:expr, $mode:expr, $reuse:expr, $compression:ident, $iters:expr) => ({
            match &*$reuse {
                "no-reuse" => {
                    let mut scratch = NoScratch;
                    do_testcase1!($testcase, $mode, scratch, $compression, $iters)
                }
                "reuse" => {
                    let mut scratch = UseScratch::new();
                    do_testcase1!($testcase, $mode, scratch, $compression, $iters)
                }
                s => panic!("unrecognized reuse option: {}", s)
            }
        });
    );

pub fn main() {
    use ::std::io::{Read, Write};
    let args : Vec<String> = ::std::env::args().collect();

    assert!(args.len() == 6,
            "USAGE: {} CASE MODE REUSE COMPRESSION ITERATION_COUNT",
            args[0]);

    let iters = match args[5].parse::<u64>() {
        Ok(n) => n,
        Err(_) => {
            panic!("Could not parse a u64 from: {}", args[5]);
        }
    };

    match &*args[4] {
        "none" => do_testcase2!(args[1], args[2],  args[3], uncompressed, iters),
        "packed" => do_testcase2!(args[1], args[2], args[3], packed, iters),
        s => panic!("unrecognized compression: {}", s)
    }
}
<commit_msg>simplify benchmark packed/none abstraction<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![crate_type = "bin"]

extern crate capnp;
extern crate fdstream;
extern crate rand;

use capnp::{MessageReader, MessageBuilder};

pub mod common;

pub mod carsales_capnp {
  include!(concat!(env!("OUT_DIR"), "/carsales_capnp.rs"));
}
pub mod carsales;

pub mod catrank_capnp {
  include!(concat!(env!("OUT_DIR"), "/catrank_capnp.rs"));
}
pub mod catrank;

pub mod eval_capnp {
  include!(concat!(env!("OUT_DIR"), "/eval_capnp.rs"));
}

pub mod eval;

mod uncompressed {
    pub use capnp::serialize::{read_message, write_message};
}

mod packed {
    pub use capnp::serialize_packed::{read_message, write_message};
}

const SCRATCH_SIZE : usize = 128 * 1024;

#[derive(Clone, Copy)]
pub struct NoScratch;

impl NoScratch {
    fn new_builder(&mut self, _idx : usize) -> capnp::message::MallocMessageBuilder {
        capnp::message::MallocMessageBuilder::new_default()
    }
}

pub struct UseScratch {
    scratch_space : ::std::vec::Vec<capnp::Word>
}

impl UseScratch {
    pub fn new() -> UseScratch {
        UseScratch {
            scratch_space : ::capnp::Word::allocate_zeroed_vec(SCRATCH_SIZE * 6)
        }
    }

    fn new_builder<'a>(&mut self, idx : usize) -> capnp::message::ScratchSpaceMallocMessageBuilder<'a> {
        assert!(idx < 6);
        unsafe {
            capnp::message::ScratchSpaceMallocMessageBuilder::new_default(
                ::std::slice::from_raw_parts_mut(self.scratch_space.get_unchecked_mut(idx * SCRATCH_SIZE),
                                                 SCRATCH_SIZE))
        }
    }
}

macro_rules! pass_by_object(
    ( $testcase:ident, $reuse:ident, $iters:expr ) => ({
            let mut rng = common::FastRand::new();
            for _ in 0..$iters {
                let mut message_req = $reuse.new_builder(0);
                let mut message_res = $reuse.new_builder(1);

                let expected = $testcase::setup_request(&mut rng,
                                                        message_req.init_root::<$testcase::RequestBuilder>());

                $testcase::handle_request(message_req.get_root::<$testcase::RequestBuilder>().unwrap().as_reader(),
                                          message_res.init_root::<$testcase::ResponseBuilder>());

                if !$testcase::check_response(
                    message_res.get_root::<$testcase::ResponseBuilder>().unwrap().as_reader(),
                    expected) {
                    panic!("Incorrect response.");
                }
            }
        });
    );

macro_rules! pass_by_bytes(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr ) => ({
        let mut request_bytes : ::std::vec::Vec<u8> =
            ::std::iter::repeat(0u8).take(SCRATCH_SIZE * 8).collect();
        let mut response_bytes : ::std::vec::Vec<u8> =
            ::std::iter::repeat(0u8).take(SCRATCH_SIZE * 8).collect();
        let mut rng = common::FastRand::new();
        for _ in 0..$iters {
            let mut message_req = $reuse.new_builder(0);
            let mut message_res = $reuse.new_builder(1);

            let expected = {
                let request = message_req.init_root::<$testcase::RequestBuilder>();
                $testcase::setup_request(&mut rng, request)
            };

            {
                let response = message_res.init_root::<$testcase::ResponseBuilder>();

                {
                    let mut writer : &mut[u8] = &mut request_bytes;
                    $compression::write_message(&mut writer, &mut message_req).unwrap()
                }

                let mut request_bytes1 : &[u8] = &request_bytes;
                let message_reader = $compression::read_message(
                    &mut request_bytes1,
                    capnp::message::DEFAULT_READER_OPTIONS).unwrap();

                let request_reader : $testcase::RequestReader = message_reader.get_root().unwrap();
                $testcase::handle_request(request_reader, response);
            }

            {
                let mut writer : &mut [u8] = &mut response_bytes;
                $compression::write_message(&mut writer, &mut message_res).unwrap()
            }

            let mut response_bytes1 : &[u8] = &response_bytes;
            let message_reader = $compression::read_message(
                &mut response_bytes1,
                capnp::message::DEFAULT_READER_OPTIONS).unwrap();

            let response_reader : $testcase::ResponseReader = message_reader.get_root().unwrap();
            if !$testcase::check_response(response_reader, expected) {
                panic!("Incorrect response.");
            }
        }
    });
    );

macro_rules! server(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr, $input:expr, $output:expr) => ({
            let mut out_buffered = ::std::io::BufWriter::new(&mut $output);
            let mut in_buffered = ::std::io::BufReader::new(&mut $input);
            for _ in 0..$iters {
                let mut message_res = $reuse.new_builder(0);

                {
                    let response = message_res.init_root::<$testcase::ResponseBuilder>();
                    let message_reader = $compression::read_message(
                        &mut in_buffered,
                        capnp::message::DEFAULT_READER_OPTIONS).unwrap();
                    let request_reader : $testcase::RequestReader = message_reader.get_root().unwrap();
                    $testcase::handle_request(request_reader, response);
                }

                $compression::write_message(&mut out_buffered, &mut message_res).unwrap();
                out_buffered.flush().unwrap();
            }
        });
    );

macro_rules! sync_client(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr) => ({
            let mut out_stream = ::fdstream::FdStream::new(1);
            let mut in_stream = ::fdstream::FdStream::new(0);
            let mut in_buffered = ::std::io::BufReader::new(&mut in_stream);
            let mut out_buffered = ::std::io::BufWriter::new(&mut out_stream);
            let mut rng = common::FastRand::new();
            for _ in 0..$iters {
                let mut message_req = $reuse.new_builder(0);

                let expected = {
                    let request = message_req.init_root::<$testcase::RequestBuilder>();
                    $testcase::setup_request(&mut rng, request)
                };
                $compression::write_message(&mut out_buffered, &mut message_req).unwrap();
                out_buffered.flush().unwrap();

                let message_reader = $compression::read_message(
                    &mut in_buffered,
                    capnp::message::DEFAULT_READER_OPTIONS).unwrap();
                let response_reader : $testcase::ResponseReader = message_reader.get_root().unwrap();
                assert!($testcase::check_response(response_reader, expected));

            }
        });
    );

macro_rules! pass_by_pipe(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr) => ({
        use std::process;

        let mut args : Vec<String> = ::std::env::args().collect();
        args[2] = "client".to_string();

        let mut command = process::Command::new(&args[0]);
        command.args(&args[1..args.len()]);
        command.stdin(process::Stdio::piped());
        command.stdout(process::Stdio::piped());
        command.stderr(process::Stdio::null());
        match command.spawn() {
            Ok(ref mut p) => {
                let mut child_std_out = p.stdout.take().unwrap();
                let mut child_std_in = p.stdin.take().unwrap();

                server!($testcase, $reuse, $compression, $iters, child_std_out, child_std_in);
                println!("{}", p.wait().unwrap());
            }
            Err(e) => {
                println!("could not start process: {}", e);
            }
        }
    });
    );

macro_rules! do_testcase(
    ( $testcase:ident, $mode:expr, $reuse:ident, $compression:ident, $iters:expr ) => ({
            match &*$mode {
                "object" => pass_by_object!($testcase, $reuse, $iters),
                "bytes" => pass_by_bytes!($testcase, $reuse, $compression, $iters),
                "client" => sync_client!($testcase, $reuse, $compression, $iters),
                "server" => {
                    let mut input = ::fdstream::FdStream::new(0);
                    let mut output = ::fdstream::FdStream::new(1);
                    server!($testcase, $reuse, $compression, $iters, input, output)
                }
                "pipe" => pass_by_pipe!($testcase, $reuse, $compression, $iters),
                s => panic!("unrecognized mode: {}", s)
            }
        });
    );

macro_rules! do_testcase1(
    ( $testcase:expr, $mode:expr, $reuse:ident, $compression:ident, $iters:expr) => ({
            match &*$testcase {
                "carsales" => do_testcase!(carsales, $mode, $reuse, $compression, $iters),
                "catrank" => do_testcase!(catrank, $mode, $reuse, $compression, $iters),
                "eval" => do_testcase!(eval, $mode, $reuse, $compression, $iters),
                s => panic!("unrecognized test case: {}", s)
            }
        });
    );

macro_rules! do_testcase2(
    ( $testcase:expr, $mode:expr, $reuse:expr, $compression:ident, $iters:expr) => ({
            match &*$reuse {
                "no-reuse" => {
                    let mut scratch = NoScratch;
                    do_testcase1!($testcase, $mode, scratch, $compression, $iters)
                }
                "reuse" => {
                    let mut scratch = UseScratch::new();
                    do_testcase1!($testcase, $mode, scratch, $compression, $iters)
                }
                s => panic!("unrecognized reuse option: {}", s)
            }
        });
    );

pub fn main() {
    use ::std::io::{Read, Write};
    let args : Vec<String> = ::std::env::args().collect();

    assert!(args.len() == 6,
            "USAGE: {} CASE MODE REUSE COMPRESSION ITERATION_COUNT",
            args[0]);

    let iters = match args[5].parse::<u64>() {
        Ok(n) => n,
        Err(_) => {
            panic!("Could not parse a u64 from: {}", args[5]);
        }
    };

    match &*args[4] {
        "none" => do_testcase2!(args[1], args[2],  args[3], uncompressed, iters),
        "packed" => do_testcase2!(args[1], args[2], args[3], packed, iters),
        s => panic!("unrecognized compression: {}", s)
    }
}
<|endoftext|>


<commit_before>//! Implementation of a 2D board (and of its constituing elements) with coordinates and iterators.

use std::fmt;
use ::Result;

/// The number of cells per side of the board.
pub const BOARD_SIZE: usize = 8;

/// The total number of cells of the board. Derived from `BOARD_SIZE` for ease of use.
pub const NUM_CELLS: usize = BOARD_SIZE * BOARD_SIZE;

/// Enums all the cardinal directions.
/// #Examples
/// If I am in cell `(4, 5)` and move `NE`, I go to cell `(3, 6)`.
#[derive(Debug, Clone, Copy)]
pub enum Direction {
    North,
    NE,
    East,
    SE,
    South,
    SW,
    West,
    NW,
}

/// Lists all cardinal directions from `Direction`.
pub const DIRECTIONS: [Direction; 8] = [
    Direction::North,
    Direction::NE,
    Direction::East,
    Direction::SE,
    Direction::South,
    Direction::SW,
    Direction::West,
    Direction::NW
];

/// Coordinates of a cell, given by a row and a column.
/// Follows matrices conventions (see <https://en.wikipedia.org/wiki/Matrix_(mathematics)>) but for starting indexes at 0.
#[derive(Debug, Clone, Copy)]
pub struct Coord(usize, usize);

impl Coord {

    #[inline(always)]
    pub fn new(row: usize, col: usize) -> Coord {
        Coord(row, col)
    }

    #[inline(always)]
    pub fn get_row(&self) -> usize {
        self.0
    }

    #[inline(always)]
    pub fn get_col(&self) -> usize {
        self.1
    }

    #[inline(always)]
    pub fn get_row_col(&self) -> (usize, usize) {
        (self.0, self.1)
    }

    /// Produces new indexes moving along a direction and checking for out-of-bound errors (meaning sub-zero indexes).
    #[inline(always)]
    pub fn step(&mut self, dir: Direction) {
        match dir {
            Direction::North    => self.0 = self.0.wrapping_sub(1),
            Direction::NE       => {
                self.0 = self.0.wrapping_sub(1);
                self.1 = self.1.wrapping_sub(1);
            },
            Direction::East     => self.1 = self.1.wrapping_sub(1),
            Direction::SE       => {
                self.0 += 1;
                self.1 = self.1.wrapping_sub(1);
            },
            Direction::South    => self.0 += 1,
            Direction::SW       => {
                self.0 += 1;
                self.1 += 1;
            },
            Direction::West     => self.1 += 1,
            Direction::NW       => self.0 = self.0.wrapping_sub(1),
        }
    }
}

/// A disk is characterized by its two sides, one Dark and one Light.
#[derive(Debug, Clone, Copy)]
pub struct Disk(::Side);

impl Disk {
    /// Creates a new disk with given side.
    #[inline(always)]
    pub fn new(side: ::Side) -> Disk {
        Disk(side)
    }

    /// Return's a disk's side.
    #[inline(always)]
    pub fn get_side(&self) -> ::Side {
        self.0
    }

    /// Turns the disk on the other side.
    #[inline(always)]
    pub fn flip(&mut self) {
        self.0 = self.0.opposite();
    }
}

/// Each cell in the board can either be empty or taken by one of the players.
pub type Cell = Option<Disk>;

#[derive(Copy)]
pub struct Board([[Cell; BOARD_SIZE]; BOARD_SIZE]);

impl fmt::Debug for Board {
    #[inline(always)]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "This should be a board")
    }
}

impl Clone for Board {
    #[inline(always)]
    fn clone(&self) -> Board {
        *self
    }
}

/// `Board` is the type of boards, which are made by a `Frame`.
impl Board {

    #[inline(always)]
    pub fn new(board: [[Cell; BOARD_SIZE]; BOARD_SIZE]) -> Board {
        Board(board)
    }

    #[inline(always)]
    pub fn get_cell(&self, coord: Coord) -> Result<&Cell> {
        self.0.get(coord.get_row()).ok_or(::ReversiError::OutOfBoundCoord(coord))?
            .get(coord.get_col()).ok_or(::ReversiError::OutOfBoundCoord(coord))
    }

    #[inline(always)]
    fn get_mut_cell(&mut self, coord: Coord) -> Result<&mut Cell> {
        self.0.get_mut(coord.get_row()).ok_or(::ReversiError::OutOfBoundCoord(coord))?
            .get_mut(coord.get_col()).ok_or(::ReversiError::OutOfBoundCoord(coord))
    }

    #[inline(always)]
    pub fn flip_disk(&mut self, coord: Coord) -> Result<()> {
        self.get_mut_cell(coord).and_then(|mut cell| {
            cell.as_mut()
                .ok_or(::ReversiError::EmptyCell(coord))?
                .flip();
            Ok(())
        })
    }

    #[inline(always)]
    pub fn is_empty(&self, coord: Coord) -> Result<bool> {
        self.get_cell(coord).map(|&cell| cell.is_none())
    }

    #[inline(always)]
    pub fn place_disk(&mut self, side: ::Side, coord: Coord) -> Result<()> {
        self.get_mut_cell(coord).and_then(|mut cell| {
            if cell.is_some() {
                Err(::ReversiError::CellAlreadyTaken(coord))
            } else {
                *cell = Some(Disk::new(side));
                Ok(())
            }
        })
    }

    #[inline(always)]
    pub fn get_board(&self) -> &[[Cell; BOARD_SIZE]; BOARD_SIZE] {
        &self.0
    }

}
<commit_msg>Important fix!<commit_after>//! Implementation of a 2D board (and of its constituing elements) with coordinates and iterators.

use std::fmt;
use ::Result;

/// The number of cells per side of the board.
pub const BOARD_SIZE: usize = 8;

/// The total number of cells of the board. Derived from `BOARD_SIZE` for ease of use.
pub const NUM_CELLS: usize = BOARD_SIZE * BOARD_SIZE;

/// Enums all the cardinal directions.
/// #Examples
/// If I am in cell `(4, 5)` and move `NE`, I go to cell `(3, 6)`.
#[derive(Debug, Clone, Copy)]
pub enum Direction {
    North,
    NE,
    East,
    SE,
    South,
    SW,
    West,
    NW,
}

/// Lists all cardinal directions from `Direction`.
pub const DIRECTIONS: [Direction; 8] = [
    Direction::North,
    Direction::NE,
    Direction::East,
    Direction::SE,
    Direction::South,
    Direction::SW,
    Direction::West,
    Direction::NW
];

/// Coordinates of a cell, given by a row and a column.
/// Follows matrices conventions (see <https://en.wikipedia.org/wiki/Matrix_(mathematics)>) but for starting indexes at 0.
#[derive(Debug, Clone, Copy)]
pub struct Coord(usize, usize);

impl Coord {

    #[inline(always)]
    pub fn new(row: usize, col: usize) -> Coord {
        Coord(row, col)
    }

    #[inline(always)]
    pub fn get_row(&self) -> usize {
        self.0
    }

    #[inline(always)]
    pub fn get_col(&self) -> usize {
        self.1
    }

    #[inline(always)]
    pub fn get_row_col(&self) -> (usize, usize) {
        (self.0, self.1)
    }

    /// Produces new indexes moving along a direction and checking for out-of-bound errors (meaning sub-zero indexes).
    #[inline(always)]
    pub fn step(&mut self, dir: Direction) {
        match dir {
            Direction::North    => self.0 = self.0.wrapping_sub(1),
            Direction::NE       => {
                self.0 = self.0.wrapping_sub(1);
                self.1 += 1;
            },
            Direction::East     => self.1 += 1,
            Direction::SE       => {
                self.0 += 1;
                self.1 += 1;
            },
            Direction::South    => self.0 += 1,
            Direction::SW       => {
                self.0 += 1;
                self.1 = self.1.wrapping_sub(1);
            },
            Direction::West     => self.1 = self.1.wrapping_sub(1),
            Direction::NW       => {
                self.0 = self.0.wrapping_sub(1);
                self.1 = self.1.wrapping_sub(1);
            }
        }
    }
}

/// A disk is characterized by its two sides, one Dark and one Light.
#[derive(Debug, Clone, Copy)]
pub struct Disk(::Side);

impl Disk {
    /// Creates a new disk with given side.
    #[inline(always)]
    pub fn new(side: ::Side) -> Disk {
        Disk(side)
    }

    /// Return's a disk's side.
    #[inline(always)]
    pub fn get_side(&self) -> ::Side {
        self.0
    }

    /// Turns the disk on the other side.
    #[inline(always)]
    pub fn flip(&mut self) {
        self.0 = self.0.opposite();
    }
}

/// Each cell in the board can either be empty or taken by one of the players.
pub type Cell = Option<Disk>;

#[derive(Copy)]
pub struct Board([[Cell; BOARD_SIZE]; BOARD_SIZE]);

impl fmt::Debug for Board {
    #[inline(always)]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "This should be a board")
    }
}

impl Clone for Board {
    #[inline(always)]
    fn clone(&self) -> Board {
        *self
    }
}

/// `Board` is the type of boards, which are made by a `Frame`.
impl Board {

    #[inline(always)]
    pub fn new(board: [[Cell; BOARD_SIZE]; BOARD_SIZE]) -> Board {
        Board(board)
    }

    #[inline(always)]
    pub fn get_cell(&self, coord: Coord) -> Result<&Cell> {
        self.0.get(coord.get_row()).ok_or(::ReversiError::OutOfBoundCoord(coord))?
            .get(coord.get_col()).ok_or(::ReversiError::OutOfBoundCoord(coord))
    }

    #[inline(always)]
    fn get_mut_cell(&mut self, coord: Coord) -> Result<&mut Cell> {
        self.0.get_mut(coord.get_row()).ok_or(::ReversiError::OutOfBoundCoord(coord))?
            .get_mut(coord.get_col()).ok_or(::ReversiError::OutOfBoundCoord(coord))
    }

    #[inline(always)]
    pub fn flip_disk(&mut self, coord: Coord) -> Result<()> {
        self.get_mut_cell(coord).and_then(|mut cell| {
            cell.as_mut()
                .ok_or(::ReversiError::EmptyCell(coord))?
                .flip();
            Ok(())
        })
    }

    #[inline(always)]
    pub fn is_empty(&self, coord: Coord) -> Result<bool> {
        self.get_cell(coord).map(|&cell| cell.is_none())
    }

    #[inline(always)]
    pub fn place_disk(&mut self, side: ::Side, coord: Coord) -> Result<()> {
        self.get_mut_cell(coord).and_then(|mut cell| {
            if cell.is_some() {
                Err(::ReversiError::CellAlreadyTaken(coord))
            } else {
                *cell = Some(Disk::new(side));
                Ok(())
            }
        })
    }

    #[inline(always)]
    pub fn get_board(&self) -> &[[Cell; BOARD_SIZE]; BOARD_SIZE] {
        &self.0
    }

}
<|endoftext|>


<commit_before>mod buffer;
mod schema;

struct BTree<K> {
	dummy: K
}

impl<K: TotalOrd> BTree<K> {
	fn new(segment_id: u64, dummy: K) -> BTree<K> {
		BTree { dummy: dummy }
	}

	fn insert(&mut self, key: K, value: schema::TID) {
	}

	fn erase(&mut self, key: K) {
	}

	fn lookup(self, key: K) -> Option<schema::TID> {
		None
	}
}

#[test]
fn simple_insert() {
	let bt = BTree::new(23, 42);
}
<commit_msg>Added a page casting mechanic<commit_after>use std::cast;
use std::mem::size_of;
use std::raw::Slice;

mod buffer;
mod schema;

struct BTree<K> {
	dummy: K
}

impl<K: TotalOrd> BTree<K> {
	fn new(segment_id: u64, dummy: K) -> BTree<K> {
		BTree { dummy: dummy }
	}

	fn insert(&mut self, key: K, value: schema::TID) {
	}

	fn erase(&mut self, key: K) {
	}

	fn lookup(self, key: K) -> Option<schema::TID> {
		None
	}
}

/*
enum Node<K> {
	Inner(BranchPage<K>),
	Leaf(LeafPage<K>),
}
*/

struct LeafEntry<K> {
	key: K,
	tid: schema::TID,
}

struct BranchEntry<K> {
	key: K,
	page_id: u64,
}

struct LeafPage<'a, K> {
	entries: &'a [LeafEntry<K>],
}

impl<'a, K> LeafPage<'a, K> {
	fn new(page: &[u8]) -> LeafPage<'a, K> {
		let entry_size = size_of::<LeafEntry<K>>();
		//let mut r: &[LeafEntry<K>] = unsafe { cast::transmute(page) };
		//unsafe { r.set_len(buffer::PAGE_SIZE / entry_size) };
		let r = unsafe {
			cast::transmute(
				Slice::<LeafEntry<K>> {
					data: page.as_ptr() as *() as *LeafEntry<K>,
					len: page.len() / entry_size,
				}
			)
		};
		LeafPage { entries: r }
	}
}

struct BranchPage<'a, K> {
	entries: &'a [BranchEntry<K>],
}

#[test]
fn simple_insert() {
	let bt = BTree::new(23, 42);
}

#[test]
fn create_leaf_page() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let pagelock = manager.fix_page(0).unwrap();
	let page = pagelock.read();
	let lp: LeafPage<u64> = LeafPage::new(page.get_data());
	println!("lp len: {}", lp.entries.len());
	assert!(false);
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

use rayon::prelude::*;
use syntect::parsing::SyntaxSet;

use crate::config::Config;
use crate::page::source::Source;
use crate::page::Page;

pub fn build(in_dir: PathBuf) -> Result<(), String> {
    let data_file = in_dir.join("_data/config.json5");
    let data = std::fs::read_to_string(&data_file)
        .map_err(|e| format!("could not read '{}'\n{}", &data_file.to_string_lossy(), e))?;
    let config: Config = json5::from_str(&data)
        .map_err(|e| format!("could not parse '{}':\n{}", &data_file.display(), e))?;

    let syntax_set = load_syntaxes();

    let all_contents = get_files_to_load(in_dir)
        .into_par_iter()
        .map(|path| {
            std::fs::read_to_string(&path)
                .map(|contents| Source { path, contents })
                .map_err(|e| format!("{}", e))
        })
        .map(|result| result.and_then(|source| Page::new(source, &config, &syntax_set)))
        .collect::<Vec<Result<Page, String>>>();

    let page = all_contents
        .into_iter()
        .find(|result| match result {
            Ok(page) => page.contents.contains("lightweight reactivity system"),
            _ => false,
        })
        .expect("srsly tho")
        .expect("PLS");

    std::fs::write("/Users/chris/Desktop/cool.html", page.contents).expect("YEAH");
    Ok(())
}

fn get_files_to_load(in_dir: PathBuf) -> Vec<PathBuf> {
    let content_dir = in_dir.join("content");
    let content_glob = content_dir.to_string_lossy() + "/**/*.md";

    type Partitioned = Vec<Result<PathBuf, String>>;
    let (ok_files, err_files): (Partitioned, Partitioned) = glob::glob(&content_glob)
        .unwrap_or_else(|_| panic!("bad glob: '{}'", &content_glob))
        .map(|result| result.map_err(|e| format!("{}", e)))
        .partition(Result::is_ok);

    for err in err_files {
        eprintln!("problem with {}", err.unwrap_err());
    }

    ok_files.into_iter().map(|result| result.unwrap()).collect()
}

fn load_syntaxes() -> SyntaxSet {
    // let mut extra_syntaxes_dir = std::env::current_dir().map_err(|e| format!("{}", e))?;
    // extra_syntaxes_dir.push("syntaxes");

    let syntax_builder = SyntaxSet::load_defaults_newlines().into_builder();
    // let mut syntax_builder = SyntaxSet::load_defaults_newlines().into_builder();
    // syntax_builder
    //     .add_from_folder(&extra_syntaxes_dir, false)
    //     .map_err(|e| format!("could not load {}: {}", &extra_syntaxes_dir.display(), e))?;

    syntax_builder.build()
}
<commit_msg>Fewer iterations! Yeah! By being less dumb! Go me!<commit_after>use std::path::PathBuf;

use rayon::prelude::*;
use syntect::parsing::SyntaxSet;

use crate::config::Config;
use crate::page::source::Source;
use crate::page::Page;

pub fn build(in_dir: PathBuf) -> Result<(), String> {
    let data_file = in_dir.join("_data/config.json5");
    let data = std::fs::read_to_string(&data_file)
        .map_err(|e| format!("could not read '{}'\n{}", &data_file.to_string_lossy(), e))?;
    let config: Config = json5::from_str(&data)
        .map_err(|e| format!("could not parse '{}':\n{}", &data_file.display(), e))?;

    let syntax_set = load_syntaxes();

    let all_contents = get_files_to_load(in_dir)
        .into_par_iter()
        .map(|path| {
            std::fs::read_to_string(&path)
                .map(|contents| Source { path, contents })
                .map_err(|e| format!("{}", e))
        })
        .map(|result| result.and_then(|source| Page::new(source, &config, &syntax_set)))
        .collect::<Vec<Result<Page, String>>>();

    let page = all_contents
        .into_iter()
        .find(|result| match result {
            Ok(page) => page.contents.contains("lightweight reactivity system"),
            _ => false,
        })
        .expect("srsly tho")
        .expect("PLS");

    std::fs::write("/Users/chris/Desktop/cool.html", page.contents).expect("YEAH");
    Ok(())
}

fn get_files_to_load(in_dir: PathBuf) -> Vec<PathBuf> {
    let content_dir = in_dir.join("content");
    let content_glob = content_dir.to_string_lossy() + "/**/*.md";

    let (ok_files, err_files): (Vec<PathBuf>, Vec<String>) = glob::glob(&content_glob)
        .unwrap_or_else(|_| panic!("bad glob: '{}'", &content_glob))
        .fold((vec![], vec![]), |(mut good, mut bad), result| {
            match result {
                Ok(path) => good.push(path),
                Err(e) => bad.push(e.to_string()),
            };

            (good, bad)
        });

    for err in err_files {
        eprintln!("problem with {}", err);
    }

    ok_files
}

fn load_syntaxes() -> SyntaxSet {
    // let mut extra_syntaxes_dir = std::env::current_dir().map_err(|e| format!("{}", e))?;
    // extra_syntaxes_dir.push("syntaxes");

    let syntax_builder = SyntaxSet::load_defaults_newlines().into_builder();
    // let mut syntax_builder = SyntaxSet::load_defaults_newlines().into_builder();
    // syntax_builder
    //     .add_from_folder(&extra_syntaxes_dir, false)
    //     .map_err(|e| format!("could not load {}: {}", &extra_syntaxes_dir.display(), e))?;

    syntax_builder.build()
}
<|endoftext|>