<commit_before>#![crate_name = "rboy"]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;
                       extern crate getopts;
                       extern crate sdl2;
                       extern crate rboy;

use rboy::device::Device;
use std::time::Duration;
use std::sync::{Arc,RWLock};
use std::comm::{Sender,Receiver,Disconnected,Empty};

static SCALE: uint = 2;
static EXITCODE_INCORRECTOPTIONS: int = 1;
static EXITCODE_CPULOADFAILS: int = 2;

#[cfg(not(test))]
fn set_exit_status(exitcode: int)
{
    std::os::set_exit_status(exitcode);
}

fn main() {
	let args = std::os::args();
	let opts = &[ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free[0].clone()
	} else {
		let mut info_start = args[0].clone();
		info_start.push_str(" <filename>");
		println!("{}", getopts::usage(info_start.as_slice(), opts));
		set_exit_status(EXITCODE_INCORRECTOPTIONS);
		return;
	};

	sdl2::init(sdl2::INIT_VIDEO);
	let window = match sdl2::video::Window::new("RBoy - A gameboy in Rust",
												sdl2::video::WindowPos::PosUndefined,
												sdl2::video::WindowPos::PosUndefined,
												160*SCALE as int,
												144*SCALE as int,
												sdl2::video::WindowFlags::empty()) {
		Ok(window) => window,
		Err(err) => panic!("failed to open window: {}", err),
	};
	let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED) {
		Ok(screen) => screen,
		Err(err) => panic!("failed to open screen: {}", err),
	};

	let (sdl_tx, cpu_rx) = std::comm::channel();
	let (cpu_tx, sdl_rx) = std::comm::channel();
	let rawscreen = ::std::iter::repeat(0u8).take(160*144*3).collect();
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();

	let cpuloop_thread = std::thread::Thread::spawn(move|| cpuloop(&cpu_tx, &cpu_rx, arc2, filename.as_slice(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(Duration::milliseconds(8));

	'main : loop {
		periodic.recv();
		match sdl_rx.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&renderer, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl2::event::poll_event() {
				sdl2::event::Event::Quit(_) => break 'main,
				sdl2::event::Event::None => break 'event,
				sdl2::event::Event::KeyDown(_, _, sdl2::keycode::KeyCode::Escape, _, _, _)
					=> break 'main,
				sdl2::event::Event::KeyDown(_, _, sdl2::keycode::KeyCode::LShift, _, _, _)
					=> sdl_tx.send(GBEvent::SpeedUp),
				sdl2::event::Event::KeyUp(_, _, sdl2::keycode::KeyCode::LShift, _, _, _)
					=> sdl_tx.send(GBEvent::SlowDown),
				sdl2::event::Event::KeyDown(_, _, sdlkey, _, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdl_tx.send(GBEvent::KeyDown(key)),
						None => {},
					}
				},
				sdl2::event::Event::KeyUp(_, _, sdlkey, _, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdl_tx.send(GBEvent::KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}

    drop(sdl_tx); // Disconnect such that the cpuloop will exit
    let _ = cpuloop_thread.join();
}

fn sdl_to_keypad(key: sdl2::keycode::KeyCode) -> Option<rboy::KeypadKey> {
	match key {
		sdl2::keycode::KeyCode::Z => Some(rboy::KeypadKey::A),
		sdl2::keycode::KeyCode::X => Some(rboy::KeypadKey::B),
		sdl2::keycode::KeyCode::Up => Some(rboy::KeypadKey::Up),
		sdl2::keycode::KeyCode::Down => Some(rboy::KeypadKey::Down),
		sdl2::keycode::KeyCode::Left => Some(rboy::KeypadKey::Left),
		sdl2::keycode::KeyCode::Right => Some(rboy::KeypadKey::Right),
		sdl2::keycode::KeyCode::Space => Some(rboy::KeypadKey::Select),
		sdl2::keycode::KeyCode::Return => Some(rboy::KeypadKey::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl2::render::Renderer, arc: &Arc<RWLock<Vec<u8>>>) {
	screen.set_draw_color(sdl2::pixels::Color::RGB(0xFF, 0xFF, 0xFF)).unwrap();
	screen.clear().unwrap();

	let data =  arc.read().unwrap().clone();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.set_draw_color(sdl2::pixels::Color::RGB(data[y*160*3 + x*3 + 0],
															data[y*160*3 + x*3 + 1],
															data[y*160*3 + x*3 + 2])).unwrap();
			screen.draw_rect(&sdl2::rect::Rect::new((x*SCALE) as i32, (y*SCALE) as i32, SCALE as i32, SCALE as i32)).unwrap();
		}
	}
	screen.present();
}

enum GBEvent {
	KeyUp(rboy::KeypadKey),
	KeyDown(rboy::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(cpu_tx: &Sender<uint>, cpu_rx: &Receiver<GBEvent>, arc: Arc<RWLock<Vec<u8>>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => Device::new(filename),
		false => Device::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); set_exit_status(EXITCODE_CPULOADFAILS); return; },
	};
	c.set_stdout(matches.opt_present("serial"));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(Duration::milliseconds(8));
	let mut limit_speed = true;

	let waitticks = (4194.304f32 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.do_cycle();
			if c.check_and_reset_gpu_updated() {
				let mut data = arc.write().unwrap();
				let gpu_data = c.get_gpu_data();
				for i in range(0, data.len()) { data[i] = gpu_data[i]; }
				if cpu_tx.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		if limit_speed { periodic.recv(); }

		match cpu_rx.try_recv() {
			Ok(event) => match event {
				GBEvent::KeyUp(key) => c.keyup(key),
				GBEvent::KeyDown(key) => c.keydown(key),
				GBEvent::SpeedUp => limit_speed = false,
				GBEvent::SlowDown => limit_speed = true,
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<commit_msg>std::comm -> std::sync::mpsc<commit_after>#![crate_name = "rboy"]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;
                       extern crate getopts;
                       extern crate sdl2;
                       extern crate rboy;

use rboy::device::Device;
use std::time::Duration;
use std::sync::{Arc,RWLock};
use std::sync::mpsc::{Sender,Receiver};
use std::sync::mpsc::TryRecvError::{Disconnected,Empty};

static SCALE: uint = 2;
static EXITCODE_INCORRECTOPTIONS: int = 1;
static EXITCODE_CPULOADFAILS: int = 2;

#[cfg(not(test))]
fn set_exit_status(exitcode: int)
{
    std::os::set_exit_status(exitcode);
}

fn main() {
	let args = std::os::args();
	let opts = &[ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free[0].clone()
	} else {
		let mut info_start = args[0].clone();
		info_start.push_str(" <filename>");
		println!("{}", getopts::usage(info_start.as_slice(), opts));
		set_exit_status(EXITCODE_INCORRECTOPTIONS);
		return;
	};

	sdl2::init(sdl2::INIT_VIDEO);
	let window = match sdl2::video::Window::new("RBoy - A gameboy in Rust",
												sdl2::video::WindowPos::PosUndefined,
												sdl2::video::WindowPos::PosUndefined,
												160*SCALE as int,
												144*SCALE as int,
												sdl2::video::WindowFlags::empty()) {
		Ok(window) => window,
		Err(err) => panic!("failed to open window: {}", err),
	};
	let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED) {
		Ok(screen) => screen,
		Err(err) => panic!("failed to open screen: {}", err),
	};

	let (sdl_tx, cpu_rx) = std::sync::mpsc::channel();
	let (cpu_tx, sdl_rx) = std::sync::mpsc::channel();
	let rawscreen = ::std::iter::repeat(0u8).take(160*144*3).collect();
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();

	let cpuloop_thread = std::thread::Thread::spawn(move|| cpuloop(&cpu_tx, &cpu_rx, arc2, filename.as_slice(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(Duration::milliseconds(8));

	'main : loop {
		periodic.recv();
		match sdl_rx.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&renderer, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl2::event::poll_event() {
				sdl2::event::Event::Quit(_) => break 'main,
				sdl2::event::Event::None => break 'event,
				sdl2::event::Event::KeyDown(_, _, sdl2::keycode::KeyCode::Escape, _, _, _)
					=> break 'main,
				sdl2::event::Event::KeyDown(_, _, sdl2::keycode::KeyCode::LShift, _, _, _)
					=> { sdl_tx.send(GBEvent::SpeedUp); },
				sdl2::event::Event::KeyUp(_, _, sdl2::keycode::KeyCode::LShift, _, _, _)
					=> { sdl_tx.send(GBEvent::SlowDown); },
				sdl2::event::Event::KeyDown(_, _, sdlkey, _, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) =>  { sdl_tx.send(GBEvent::KeyDown(key)); },
						None => {},
					}
				},
				sdl2::event::Event::KeyUp(_, _, sdlkey, _, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => { sdl_tx.send(GBEvent::KeyUp(key)); },
						None => {},
					}
				},
				_ => {}
			}
		}
	}

    drop(sdl_tx); // Disconnect such that the cpuloop will exit
    let _ = cpuloop_thread.join();
}

fn sdl_to_keypad(key: sdl2::keycode::KeyCode) -> Option<rboy::KeypadKey> {
	match key {
		sdl2::keycode::KeyCode::Z => Some(rboy::KeypadKey::A),
		sdl2::keycode::KeyCode::X => Some(rboy::KeypadKey::B),
		sdl2::keycode::KeyCode::Up => Some(rboy::KeypadKey::Up),
		sdl2::keycode::KeyCode::Down => Some(rboy::KeypadKey::Down),
		sdl2::keycode::KeyCode::Left => Some(rboy::KeypadKey::Left),
		sdl2::keycode::KeyCode::Right => Some(rboy::KeypadKey::Right),
		sdl2::keycode::KeyCode::Space => Some(rboy::KeypadKey::Select),
		sdl2::keycode::KeyCode::Return => Some(rboy::KeypadKey::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl2::render::Renderer, arc: &Arc<RWLock<Vec<u8>>>) {
	screen.set_draw_color(sdl2::pixels::Color::RGB(0xFF, 0xFF, 0xFF)).unwrap();
	screen.clear().unwrap();

	let data =  arc.read().unwrap().clone();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.set_draw_color(sdl2::pixels::Color::RGB(data[y*160*3 + x*3 + 0],
															data[y*160*3 + x*3 + 1],
															data[y*160*3 + x*3 + 2])).unwrap();
			screen.draw_rect(&sdl2::rect::Rect::new((x*SCALE) as i32, (y*SCALE) as i32, SCALE as i32, SCALE as i32)).unwrap();
		}
	}
	screen.present();
}

enum GBEvent {
	KeyUp(rboy::KeypadKey),
	KeyDown(rboy::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(cpu_tx: &Sender<uint>, cpu_rx: &Receiver<GBEvent>, arc: Arc<RWLock<Vec<u8>>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => Device::new(filename),
		false => Device::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); set_exit_status(EXITCODE_CPULOADFAILS); return; },
	};
	c.set_stdout(matches.opt_present("serial"));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(Duration::milliseconds(8));
	let mut limit_speed = true;

	let waitticks = (4194.304f32 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.do_cycle();
			if c.check_and_reset_gpu_updated() {
				let mut data = arc.write().unwrap();
				let gpu_data = c.get_gpu_data();
				for i in range(0, data.len()) { data[i] = gpu_data[i]; }
				if cpu_tx.send(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		if limit_speed { periodic.recv(); }

		match cpu_rx.try_recv() {
			Ok(event) => match event {
				GBEvent::KeyUp(key) => c.keyup(key),
				GBEvent::KeyDown(key) => c.keydown(key),
				GBEvent::SpeedUp => limit_speed = false,
				GBEvent::SlowDown => limit_speed = true,
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<|endoftext|>


<commit_before>//! DNS data.
//!
//! This module provides types and traits for working with DNS data as well
//! as parsing and composing wire-format DNS messages.
//!
//! # Working with DNS Data
//!
//! The module contains abstractions for two concepts used in DNS data:
//! domain names and character strings. In both cases, the supplied types
//! internally contain the binary data and work directly on it. Similar
//! to raw bytes slices, there types for borrowed and owned domain names
//! and character strings where the owned type derefs to the borrowed one.
//! For domain names, these types are [`DNameSlice`] and [`DNameBuf`];
//! for character strings [`CharStr`] and [`CharStrBuf`].
//!
//! For domain names there is a third variant, [`ParsedDName`]. This type is
//! necessary to represent compressed names where the remainder of a name is
//! to be found elsewhere in the message. It avoids allocations when access
//! to the entire name isn’t necessary.
//!
//! Traits are used when constructing composite types to allow them to work
//! on borrowed and owned data as well as on parsed domain names. For
//! character strings and raw bytes data, `AsRef<CharStr>` and `AsRef<[u8]>`
//! are being used. For domain names, there is a separate trait, [`DName`]
//! with the same purpose. However, its functionality is limited to the
//! what parsed domain names can provide.
//!
//! A number of composite types are already defined: [`Question`] for
//! the questions of a query, [`Record`] for resource records.
//!
//! Instead of having one big enum, the data of resource records is kept
//! generic through two traits: [`RecordData`] provides functions common to
//! all variants of record data types while [`ParsedRecordData`] adds
//! the ability to construct a value from a wire-format message for those
//! variants that can use borrowed data and parsed domain names. The actual
//! types implementing these traits can by found in the crate’s [rdata]
//! module.
//!
//! # Parsing and Composing Messages
//!
//! In order to easily distinguish the process of creating and disecting
//! wire-format messages from working with master files, we use the term
//! *parsing* and *composing* for reading from and writing to wire-format
//! data.
//!
//! Both parsing and parsing happen on bytes buffers. This seems to be a
//! reasonably choice given the relatively small size of DNS messages and
//! the complexities introduced by name compression. The details are
//! explained in the [parse] and [compose] sub-modules. Unless you are
//! implementing your own resource record types, you are unlikely to ever
//! having to deal with parsing and composing directly.
//!
//! Instead, the types [`Message`] and [`MessageBuilder`] are there to make
//! parsing and constructing DNS messages easy. A [`Message`] takes the
//! binary data of a DNS message and allows iterating over its four
//! sections to look at the questions and resource records. Similarly,
//! a [`MessageBuilder`] takes a bytes vector (or creates one for you) and
//! has functionality to build the sections of the message step-by-step.
//!
//! [rdata]: ../rdata/index.html
//! [compose]: compose/index.html
//! [parse]: parse/index.html
//! [`CharStr`]: charstr/struct.CharStr.html
//! [`CharStrBuf`]: charstr/struct.CharStrBuf.html
//! [`DName`]: name/trait.DName.html
//! [`DNameBuf`]: name/struct.DNameBuf.html
//! [`DNameSlice`]: name/struct.DNameSlice.html
//! [`Message`]: message/struct.Message.html
//! [`MessageBuilder`]: message_builder/struct.MessageBuilder.html
//! [`ParsedDName`]: name/struct.ParsedDName.html
//! [`ParsedRecordData`]: rdata/trait.ParsedRecordData.html
//! [`Question`]: question/struct.Question.html
//! [`Record`]: record/struct.Record.html
//! [`RecordData`]: rdata/trait.RecordData.html

//--- Re-exports

pub use self::charstr::{CharStr, CharStrBuf};
pub use self::compose::{Composable, Composer, ComposeError, ComposeMode,
                        ComposeResult, ComposeSnapshot};
pub use self::header::{Header, HeaderCounts, HeaderSection};
pub use self::message::{Message, MessageBuf};
pub use self::message_builder::{MessageBuilder, AnswerBuilder,
                                AuthorityBuilder, AdditionalBuilder};
pub use self::name::{DName, DNameBuf, DNameSlice, ParsedDName};
pub use self::parse::{Parser, ParseError, ParseResult};
pub use self::question::Question;
pub use self::rdata::{GenericRecordData, ParsedRecordData, RecordData};
pub use self::record::{GenericRecord, Record};

//--- Modules

pub mod charstr;
pub mod compose;
pub mod header;
pub mod message;
pub mod message_builder;
pub mod name;
pub mod net;
pub mod parse;
pub mod question;
pub mod rdata;
pub mod record;

<commit_msg>Fix typo<commit_after>//! DNS data.
//!
//! This module provides types and traits for working with DNS data as well
//! as parsing and composing wire-format DNS messages.
//!
//! # Working with DNS Data
//!
//! The module contains abstractions for two concepts used in DNS data:
//! domain names and character strings. In both cases, the supplied types
//! internally contain the binary data and work directly on it. Similar
//! to raw bytes slices, there types for borrowed and owned domain names
//! and character strings where the owned type derefs to the borrowed one.
//! For domain names, these types are [`DNameSlice`] and [`DNameBuf`];
//! for character strings [`CharStr`] and [`CharStrBuf`].
//!
//! For domain names there is a third variant, [`ParsedDName`]. This type is
//! necessary to represent compressed names where the remainder of a name is
//! to be found elsewhere in the message. It avoids allocations when access
//! to the entire name isn’t necessary.
//!
//! Traits are used when constructing composite types to allow them to work
//! on borrowed and owned data as well as on parsed domain names. For
//! character strings and raw bytes data, `AsRef<CharStr>` and `AsRef<[u8]>`
//! are being used. For domain names, there is a separate trait, [`DName`]
//! with the same purpose. However, its functionality is limited to the
//! what parsed domain names can provide.
//!
//! A number of composite types are already defined: [`Question`] for
//! the questions of a query, [`Record`] for resource records.
//!
//! Instead of having one big enum, the data of resource records is kept
//! generic through two traits: [`RecordData`] provides functions common to
//! all variants of record data types while [`ParsedRecordData`] adds
//! the ability to construct a value from a wire-format message for those
//! variants that can use borrowed data and parsed domain names. The actual
//! types implementing these traits can by found in the crate’s [rdata]
//! module.
//!
//! # Parsing and Composing Messages
//!
//! In order to easily distinguish the process of creating and disecting
//! wire-format messages from working with master files, we use the term
//! *parsing* and *composing* for reading from and writing to wire-format
//! data.
//!
//! Both parsing and composing happen on bytes buffers. This seems to be a
//! reasonably choice given the relatively small size of DNS messages and
//! the complexities introduced by name compression. The details are
//! explained in the [parse] and [compose] sub-modules. Unless you are
//! implementing your own resource record types, you are unlikely to ever
//! having to deal with parsing and composing directly.
//!
//! Instead, the types [`Message`] and [`MessageBuilder`] are there to make
//! parsing and constructing DNS messages easy. A [`Message`] takes the
//! binary data of a DNS message and allows iterating over its four
//! sections to look at the questions and resource records. Similarly,
//! a [`MessageBuilder`] takes a bytes vector (or creates one for you) and
//! has functionality to build the sections of the message step-by-step.
//!
//! [rdata]: ../rdata/index.html
//! [compose]: compose/index.html
//! [parse]: parse/index.html
//! [`CharStr`]: charstr/struct.CharStr.html
//! [`CharStrBuf`]: charstr/struct.CharStrBuf.html
//! [`DName`]: name/trait.DName.html
//! [`DNameBuf`]: name/struct.DNameBuf.html
//! [`DNameSlice`]: name/struct.DNameSlice.html
//! [`Message`]: message/struct.Message.html
//! [`MessageBuilder`]: message_builder/struct.MessageBuilder.html
//! [`ParsedDName`]: name/struct.ParsedDName.html
//! [`ParsedRecordData`]: rdata/trait.ParsedRecordData.html
//! [`Question`]: question/struct.Question.html
//! [`Record`]: record/struct.Record.html
//! [`RecordData`]: rdata/trait.RecordData.html

//--- Re-exports

pub use self::charstr::{CharStr, CharStrBuf};
pub use self::compose::{Composable, Composer, ComposeError, ComposeMode,
                        ComposeResult, ComposeSnapshot};
pub use self::header::{Header, HeaderCounts, HeaderSection};
pub use self::message::{Message, MessageBuf};
pub use self::message_builder::{MessageBuilder, AnswerBuilder,
                                AuthorityBuilder, AdditionalBuilder};
pub use self::name::{DName, DNameBuf, DNameSlice, ParsedDName};
pub use self::parse::{Parser, ParseError, ParseResult};
pub use self::question::Question;
pub use self::rdata::{GenericRecordData, ParsedRecordData, RecordData};
pub use self::record::{GenericRecord, Record};

//--- Modules

pub mod charstr;
pub mod compose;
pub mod header;
pub mod message;
pub mod message_builder;
pub mod name;
pub mod net;
pub mod parse;
pub mod question;
pub mod rdata;
pub mod record;

<|endoftext|>


<commit_before><commit_msg>Adds ability to create Blake2xb instances with custom ParameterBlock<commit_after><|endoftext|>


<commit_before>use data::{Value, RuntimeError};
use scope::GlobalScope;

pub fn load(env: &mut GlobalScope)
{
    env.set_builtin("quote", false, |args, _| {
        match *args {
            Some(ref cons) => Ok(cons.car.clone()), //FIXME: should fail with extra args
            None => Err(RuntimeError::InvalidArgNum(1)),
        }
    });

    env.set_builtin("+", true, |mut args, _| {
        let mut acc = 0.0;
        while let Some(ref cons) = *args
        {
            match cons.car {
                Value::Number(n) => acc += n,
                ref other => return Err(RuntimeError::InvalidArgType("Number", other.type_name())),
            };
            args = &cons.cdr;
        }
        Ok(Value::Number(acc))
    });
}
<commit_msg>implemented builtin "set"<commit_after>use data::{Value, RuntimeError};
use scope::GlobalScope;

pub fn load(env: &mut GlobalScope)
{
    env.set_builtin("quote", false, |args, _| {
        match *args {
            Some(ref cons) => Ok(cons.car.clone()), //FIXME: should fail with extra args
            None => Err(RuntimeError::InvalidArgNum(1)),
        }
    });

    env.set_builtin("set", true, |args, env| {
        match *args {
            Some(ref c1) => match c1.cdr {
                Some (ref c2) => match c1.car {
                    Value::Symbol(ref name) => {
                        env.set(name, c2.car.clone());
                        Ok(c2.car.clone())
                    }
                    ref other => Err(RuntimeError::InvalidArgType("Symbol", other.type_name())),
                },
                None => Err(RuntimeError::InvalidArgNum(2)),
            },
            None => Err(RuntimeError::InvalidArgNum(2)),
        }
    });

    env.set_builtin("+", true, |mut args, _| {
        let mut acc = 0.0;
        while let Some(ref cons) = *args
        {
            match cons.car {
                Value::Number(n) => acc += n,
                ref other => return Err(RuntimeError::InvalidArgType("Number", other.type_name())),
            };
            args = &cons.cdr;
        }
        Ok(Value::Number(acc))
    });
}
<|endoftext|>


<commit_before>extern crate stem;

use tokenize::tokenize;
use stem::get;
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use std::num::Float;

pub struct NaiveBayesClassifier {
  documents: HashMap<String, HashMap<String, uint>>,
  total_document_count: uint
}

impl NaiveBayesClassifier {
  pub fn new() -> NaiveBayesClassifier {
    NaiveBayesClassifier{ documents: HashMap::new(), total_document_count: 0 }
  }

  pub fn train(&mut self, text: String, classification: String) {
    let classification_map = match self.documents.entry(classification) {
      Vacant(entry) => entry.set(HashMap::new()),
      Occupied(entry) => entry.into_mut()
    };

    let stemmed_and_tokenized = get_tokenized_and_stemmed(text);
    for stemmed_word in stemmed_and_tokenized.into_iter() {
      match classification_map.entry(stemmed_word) {
        Vacant(entry) => { entry.set(1); }, // Arm must return ()
        Occupied(mut entry) => *entry.get_mut() += 1
      }
    }
    self.total_document_count += 1;
  }

  pub fn guess<T:Str>(&self, text: T) -> String {
    let stemmed_and_tokenized = get_tokenized_and_stemmed(text);

    let mut label_probabilities = HashMap::new();
    for (k,v) in self.documents.iter() {
      //Get the probability that the passed-in text is each class
      let mut probability: f32 = 0.0;
      for stemmed_word in stemmed_and_tokenized.iter() {
        if v.contains_key(stemmed_word) {
          probability += (1.0 / v.len() as f32).ln();
        }
      }
      if probability.abs() < 0.0001 {
        label_probabilities.insert(k, 0.0);
      }
      else {
        label_probabilities.insert(k, (v.len() as f32 * probability.abs() / self.total_document_count as f32));
      }
    }

    let mut answer_label= "".to_string();
    let mut answer_probability = 0.0;
    for (k,v) in label_probabilities.into_iter() {
      if answer_probability <= v {
        answer_label = k.clone();
        answer_probability = v;
      }
    }
    answer_label
  }
}

fn get_tokenized_and_stemmed<T:Str>(text: T) -> Vec<String> {
  let tokenized_text = tokenize(text.as_slice());
  Vec::from_fn(tokenized_text.len(), |idx| stem::get(tokenized_text[idx]).unwrap())
}<commit_msg>Fixed entry issue.<commit_after>extern crate stem;

use tokenize::tokenize;
use stem::get;
use std::collections::HashMap;
use std::collections::hash_map::Entry;

pub struct NaiveBayesClassifier {
  documents: HashMap<String, HashMap<String, uint>>,
  total_document_count: uint
}

impl NaiveBayesClassifier {
  pub fn new() -> NaiveBayesClassifier {
    NaiveBayesClassifier{ documents: HashMap::new(), total_document_count: 0 }
  }

  pub fn train(&mut self, text: String, classification: String) {
    let classification_map = match self.documents.entry(classification) {
      Entry::Vacant(entry) => entry.set(HashMap::new()),
      Entry::Occupied(entry) => entry.into_mut()
    };

    let stemmed_and_tokenized = get_tokenized_and_stemmed(text);
    for stemmed_word in stemmed_and_tokenized.into_iter() {
      match classification_map.entry(stemmed_word) {
        Entry::Vacant(entry) => { entry.set(1); }, // Arm must return ()
        Entry::Occupied(mut entry) => *entry.get_mut() += 1
      }
    }
    self.total_document_count += 1;
  }

  pub fn guess<T:Str>(&self, text: T) -> String {
    let stemmed_and_tokenized = get_tokenized_and_stemmed(text);

    let mut label_probabilities = HashMap::new();
    for (k,v) in self.documents.iter() {
      //Get the probability that the passed-in text is each class
      let mut probability: f32 = 0.0;
      for stemmed_word in stemmed_and_tokenized.iter() {
        if v.contains_key(stemmed_word) {
          probability += (1.0 / v.len() as f32).ln();
        }
      }
      if probability.abs() < 0.0001 {
        label_probabilities.insert(k, 0.0);
      }
      else {
        label_probabilities.insert(k, (v.len() as f32 * probability.abs() / self.total_document_count as f32));
      }
    }

    let mut answer_label= "".to_string();
    let mut answer_probability = 0.0;
    for (k,v) in label_probabilities.into_iter() {
      if answer_probability <= v {
        answer_label = k.clone();
        answer_probability = v;
      }
    }
    answer_label
  }
}

fn get_tokenized_and_stemmed<T:Str>(text: T) -> Vec<String> {
  let tokenized_text = tokenize(text.as_slice());
  tokenized_text.iter()
                .map(|idx| stem::get(tokenized_text[idx]).unwrap()))
                .collect()
}
<|endoftext|>


<commit_before>use errors::{ClientError, ClientErrorKind};
use entities::{Mbid, Resource};

use reqwest_mock::Client as MockClient;
use reqwest_mock::GenericClient as HttpClient;
use reqwest_mock::Url;
use reqwest_mock::header::UserAgent;
use xpath_reader::reader::{FromXmlContained, XpathStrReader};

use std::time::{Duration, Instant};
use std::thread::sleep;

pub mod search;
use self::search::{AreaSearchBuilder, ArtistSearchBuilder, ReleaseGroupSearchBuilder};
pub use self::search::SearchBuilder;

mod error;
use self::error::check_response_error;

/// Helper extracting the number of milliseconds from a `Duration`.
fn as_millis(duration: &Duration) -> f64
{
    (duration.as_secs() as f64) + (duration.subsec_nanos() as f64) * 1e6
}

/// Returns an `Instant` at least 1000 seconds ago.
fn past_instant() -> Instant
{
    Instant::now() - Duration::new(1000, 0)
}

/// Configuration for the client.
#[derive(Clone, Debug)]
pub struct ClientConfig {
    /// The user-agent to be sent with every request to the API.
    ///
    /// Provide a meaningful one as it will be used by MusicBrainz to identify
    /// your application and
    /// without a user agent sever throttling will be undertaken. The official
    /// suggestion is to use
    /// either one of the following two options:
    ///
    /// * `Application name/<version> ( contact-url )`
    /// * `Application name/<version> ( contact-email )`
    ///
    /// For more information see:
    /// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting
    pub user_agent: String,
}

/// The main struct to be used to communicate with the MusicBrainz API.
///
/// Please create only one instance and use it troughout your application
/// as it will ensure appropriate wait times between requests to prevent
/// being blocked for making to many requests.
pub struct Client {
    http_client: HttpClient,
    config: ClientConfig,

    /// The time the last request was made.
    /// According to the documentation we have to wait at least one second
    /// between any two requests
    /// to the MusicBrainz API.
    last_request: Instant,
}

impl Client {
    /// Create a new Client instance.
    pub fn new(config: ClientConfig) -> Result<Self, ClientError>
    {
        Ok(Client {
            config: config,
            http_client: HttpClient::direct(),
            last_request: past_instant(),
        })
    }
}

impl Client {
    fn wait_if_needed(&mut self)
    {
        let now = Instant::now();
        let elapsed = now.duration_since(self.last_request);
        if as_millis(&elapsed) < 1000. {
            // We have to wait a bit.
            sleep(Duration::new(1, 0) - elapsed);
        }
        self.last_request = now;
    }

    /// Fetch the specified ressource from the server and parse it.
    pub fn get_by_mbid<Res>(&mut self, mbid: &Mbid) -> Result<Res, ClientError>
    where
        Res: Resource + FromXmlContained,
    {
        let url = Res::get_url(mbid);
        let response_body = self.get_body(url.parse()?)?;

        // Parse the response.
        let context = ::util::musicbrainz_context();
        let reader = XpathStrReader::new(&response_body[..], &context)?;
        check_response_error(&reader)?;
        Ok(Res::from_xml(&reader)?)
    }

    fn get_body(&mut self, url: Url) -> Result<String, ClientError>
    {
        self.wait_if_needed();

        let response =
            self.http_client.get(url).header(UserAgent(self.config.user_agent.clone())).send()?;
        let response_body = response.body_to_utf8()?;
        Ok(response_body)
    }

    /// Returns a search builder to search for an area.
    pub fn search_area<'cl>(&'cl mut self) -> AreaSearchBuilder<'cl>
    {
        AreaSearchBuilder::new(self)
    }

    /// Returns a search biulder to search for an artist.
    pub fn search_artist<'cl>(&'cl mut self) -> ArtistSearchBuilder<'cl>
    {
        ArtistSearchBuilder::new(self)
    }

    /// Returns a search builder to search for a release group.
    pub fn search_release_group<'cl>(&'cl mut self) -> ReleaseGroupSearchBuilder<'cl>
    {
        ReleaseGroupSearchBuilder::new(self)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use reqwest_mock::ReplayClient;

    fn get_client(testname: &str) -> Client
    {
        Client {
            config: ClientConfig { user_agent: "MusicBrainz-Rust/Testing".to_string() },
            http_client: HttpClient::replay(format!("replay/src/client/mod/{}.replay", testname)),
            last_request: past_instant(),
        }
    }

    #[test]
    fn search_release_group()
    {
        let mut client = get_client("search_release_group");
        let results = client
            .search_release_group()
            .add(search::fields::release_group::ReleaseGroupName(
                "霊魂消滅".to_owned(),
            ))
            .search()
            .unwrap();

        assert_eq!(results.len(), 1);
        assert_eq!(results[0].score, 100);
        assert_eq!(
            results[0].entity.mbid,
            "739de9cd-7e81-4bb0-9fdb-0feb7ea709c7".parse().unwrap()
        );
        assert_eq!(results[0].entity.title, "霊魂消滅".to_string());
    }
}
<commit_msg>Compatibility with most recent reqwest_mock<commit_after>use errors::{ClientError, ClientErrorKind};
use entities::{Mbid, Resource};

use reqwest_mock::Client as MockClient;
use reqwest_mock::GenericClient as HttpClient;
use reqwest_mock::Url;
use reqwest_mock::header::UserAgent;
use xpath_reader::reader::{FromXmlContained, XpathStrReader};

use std::time::{Duration, Instant};
use std::thread::sleep;

pub mod search;
use self::search::{AreaSearchBuilder, ArtistSearchBuilder, ReleaseGroupSearchBuilder};
pub use self::search::SearchBuilder;

mod error;
use self::error::check_response_error;

/// Helper extracting the number of milliseconds from a `Duration`.
fn as_millis(duration: &Duration) -> f64
{
    (duration.as_secs() as f64) + (duration.subsec_nanos() as f64) * 1e6
}

/// Returns an `Instant` at least 1000 seconds ago.
fn past_instant() -> Instant
{
    Instant::now() - Duration::new(1000, 0)
}

/// Configuration for the client.
#[derive(Clone, Debug)]
pub struct ClientConfig {
    /// The user-agent to be sent with every request to the API.
    ///
    /// Provide a meaningful one as it will be used by MusicBrainz to identify
    /// your application and
    /// without a user agent sever throttling will be undertaken. The official
    /// suggestion is to use
    /// either one of the following two options:
    ///
    /// * `Application name/<version> ( contact-url )`
    /// * `Application name/<version> ( contact-email )`
    ///
    /// For more information see:
    /// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting
    pub user_agent: String,
}

/// The main struct to be used to communicate with the MusicBrainz API.
///
/// Please create only one instance and use it troughout your application
/// as it will ensure appropriate wait times between requests to prevent
/// being blocked for making to many requests.
pub struct Client {
    http_client: HttpClient,
    config: ClientConfig,

    /// The time the last request was made.
    /// According to the documentation we have to wait at least one second
    /// between any two requests
    /// to the MusicBrainz API.
    last_request: Instant,
}

impl Client {
    /// Create a new Client instance.
    pub fn new(config: ClientConfig) -> Result<Self, ClientError>
    {
        Ok(Client {
            config: config,
            http_client: HttpClient::direct(),
            last_request: past_instant(),
        })
    }
}

impl Client {
    fn wait_if_needed(&mut self)
    {
        let now = Instant::now();
        let elapsed = now.duration_since(self.last_request);
        if as_millis(&elapsed) < 1000. {
            // We have to wait a bit.
            sleep(Duration::new(1, 0) - elapsed);
        }
        self.last_request = now;
    }

    /// Fetch the specified ressource from the server and parse it.
    pub fn get_by_mbid<Res>(&mut self, mbid: &Mbid) -> Result<Res, ClientError>
    where
        Res: Resource + FromXmlContained,
    {
        let url = Res::get_url(mbid);
        let response_body = self.get_body(url.parse()?)?;

        // Parse the response.
        let context = ::util::musicbrainz_context();
        let reader = XpathStrReader::new(&response_body[..], &context)?;
        check_response_error(&reader)?;
        Ok(Res::from_xml(&reader)?)
    }

    fn get_body(&mut self, url: Url) -> Result<String, ClientError>
    {
        self.wait_if_needed();

        let response =
            self.http_client.get(url).header(UserAgent(self.config.user_agent.clone())).send()?;
        let response_body = response.body_to_utf8()?;
        Ok(response_body)
    }

    /// Returns a search builder to search for an area.
    pub fn search_area<'cl>(&'cl mut self) -> AreaSearchBuilder<'cl>
    {
        AreaSearchBuilder::new(self)
    }

    /// Returns a search biulder to search for an artist.
    pub fn search_artist<'cl>(&'cl mut self) -> ArtistSearchBuilder<'cl>
    {
        ArtistSearchBuilder::new(self)
    }

    /// Returns a search builder to search for a release group.
    pub fn search_release_group<'cl>(&'cl mut self) -> ReleaseGroupSearchBuilder<'cl>
    {
        ReleaseGroupSearchBuilder::new(self)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use reqwest_mock::ReplayClient;

    fn get_client(testname: &str) -> Client
    {
        Client {
            config: ClientConfig { user_agent: "MusicBrainz-Rust/Testing".to_string() },
            http_client: HttpClient::replay_file(format!("replay/src/client/mod/{}.json", testname)),
            last_request: past_instant(),
        }
    }

    #[test]
    fn search_release_group()
    {
        let mut client = get_client("search_release_group");
        let results = client
            .search_release_group()
            .add(search::fields::release_group::ReleaseGroupName(
                "霊魂消滅".to_owned(),
            ))
            .search()
            .unwrap();

        assert_eq!(results.len(), 1);
        assert_eq!(results[0].score, 100);
        assert_eq!(
            results[0].entity.mbid,
            "739de9cd-7e81-4bb0-9fdb-0feb7ea709c7".parse().unwrap()
        );
        assert_eq!(results[0].entity.title, "霊魂消滅".to_string());
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut Sender<Vec<u8>>);
    fn register_stop_tx(tx: *mut Sender<()>);
}

#[no_mangle]
pub extern "C" fn some_new_fn() -> c_int {
    println!("Whatadfsasdf");
    65 as c_int
}

/// Connects to the provided address, (eg "123.123.123.123:3000") and registers
/// the on data received handler
#[no_mangle]
pub extern "C" fn connect(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");

    78 as c_int

    // let mut r_address;
    // unsafe {
    //     r_address = CStr::from_ptr(address);
    // }
    // let s_address = r_address.to_bytes();
    // let host_address = match str::from_utf8(s_address) {
    //     Ok(safe_str) => safe_str,
    //     Err(_) => {
    //         println!("Invalid host address");
    //         return -1 as c_int;
    //     }
    // };
    //
    // // Create and register a way to kill this client
    // let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    // let kill_tx = k_tx.clone();
    // let mut k_tx_ptr = Box::new(k_tx);
    // unsafe {
    //     register_stop_tx(&mut *k_tx_ptr);
    // }
    //
    // // Writer thread's channel
    // let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // let mut w_tx_ptr = Box::new(w_tx);
    // unsafe {
    //     register_writer_tx(&mut *w_tx_ptr);
    // }
    //
    // println!("Attempting connect to: {}", host_address);
    //
    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     println!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // println!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    //
    // let r_client = client.clone();
    // let r_kill_tx = kill_tx.clone();
    //
    // let w_client = client.clone();
    // let w_kill_tx = kill_tx.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, handler, r_kill_tx)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(w_rx, w_client, w_kill_tx)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         println!("Error on kill channel: {}", e);
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();
    //
    // // Exit out in standard C fashion
    // 0 as c_int
}

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<commit_msg>Debugging<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut Sender<Vec<u8>>);
    fn register_stop_tx(tx: *mut Sender<()>);
}

// #[no_mangle]
// pub extern "C" fn some_new_fn() -> c_int {
//     println!("Whatadfsasdf");
//     65 as c_int
// }

/// Connects to the provided address, (eg "123.123.123.123:3000") and registers
/// the on data received handler
#[no_mangle]
pub extern "C" fn connect(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");
    println!("Rust - connect");

    78 as c_int

    // let mut r_address;
    // unsafe {
    //     r_address = CStr::from_ptr(address);
    // }
    // let s_address = r_address.to_bytes();
    // let host_address = match str::from_utf8(s_address) {
    //     Ok(safe_str) => safe_str,
    //     Err(_) => {
    //         println!("Invalid host address");
    //         return -1 as c_int;
    //     }
    // };
    //
    // // Create and register a way to kill this client
    // let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    // let kill_tx = k_tx.clone();
    // let mut k_tx_ptr = Box::new(k_tx);
    // unsafe {
    //     register_stop_tx(&mut *k_tx_ptr);
    // }
    //
    // // Writer thread's channel
    // let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // let mut w_tx_ptr = Box::new(w_tx);
    // unsafe {
    //     register_writer_tx(&mut *w_tx_ptr);
    // }
    //
    // println!("Attempting connect to: {}", host_address);
    //
    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     println!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // println!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    //
    // let r_client = client.clone();
    // let r_kill_tx = kill_tx.clone();
    //
    // let w_client = client.clone();
    // let w_kill_tx = kill_tx.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, handler, r_kill_tx)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(w_rx, w_client, w_kill_tx)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         println!("Error on kill channel: {}", e);
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();
    //
    // // Exit out in standard C fashion
    // 0 as c_int
}

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<|endoftext|>


<commit_before>use core::clone::Clone;
use core::iter::Iterator;
use core::mem::size_of;
use core::ops::Drop;
use core::option::Option;
use core::ptr;
use core::slice;
use core::slice::SliceExt;

use syscall::call::*;

/// An iterator over a vec
pub struct VecIterator<'a, T: 'a> {
    vec: &'a Vec<T>,
    offset: usize,
}

impl <'a, T> Iterator for VecIterator<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item> {
        match self.vec.get(self.offset) {
            Option::Some(item) => {
                self.offset += 1;
                Option::Some(item)
            }
            Option::None => {
                Option::None
            }
        }
    }
}

/// A owned, heap allocated list of elements
pub struct Vec<T> {
    pub data: *mut T,
    pub length: usize,
}

impl <T> Vec<T> {
    /// Create a empty vector
    pub fn new() -> Vec<T> {
        Vec::<T> {
            data: 0 as *mut T,
            length: 0,
        }
    }

    /// Convert to pointer
    pub unsafe fn as_ptr(&self) -> *const T {
        self.data
    }

    /// Convert from a raw (unsafe) buffer
    pub unsafe fn from_raw_buf(ptr: *const T, len: usize) -> Vec<T> {
        let data = sys_alloc(size_of::<T>() * len);

        ptr::copy(ptr, data as *mut T, len);

        Vec::<T> {
            data: data as *mut T,
            length: len,
        }
    }

    /// Get the nth element. Returns None if out of bounds.
    pub fn get(&self, i: usize) -> Option<&mut T> {
        if i >= self.length {
            Option::None
        } else {
            unsafe { Option::Some(&mut *self.data.offset(i as isize)) }
        }
    }

    /// Set the nth element
    pub fn set(&self, i: usize, value: T) {
        if i <= self.length {
            unsafe {
                ptr::write(self.data.offset(i as isize), value);
            }
        }
    }

    /// Insert element at a given position
    pub fn insert(&mut self, i: usize, value: T) {
        if i <= self.length {
            self.length += 1;
            unsafe {
                self.data = sys_realloc(self.data as usize, self.length * size_of::<T>()) as *mut T;

                //Move all things ahead of insert forward one
                let mut j = self.length - 1;
                while j > i {
                    ptr::write(self.data.offset(j as isize),
                               ptr::read(self.data.offset(j as isize - 1)));
                    j -= 1;
                }

                ptr::write(self.data.offset(i as isize), value);
            }
        }
    }

    /// Remove a element and return it as a Option
    pub fn remove(&mut self, i: usize) -> Option<T> {
        if i < self.length {
            self.length -= 1;
            unsafe {
                let item = ptr::read(self.data.offset(i as isize));

                //Move all things ahead of remove back one
                let mut j = i;
                while j < self.length {
                    ptr::write(self.data.offset(j as isize),
                               ptr::read(self.data.offset(j as isize + 1)));
                    j += 1;
                }

                self.data = sys_realloc(self.data as usize, self.length * size_of::<T>()) as *mut T;

                Option::Some(item)
            }
        } else {
            Option::None
        }
    }

    /// Push an element to a vector
    pub fn push(&mut self, value: T) {
        self.length += 1;
        unsafe {
            self.data = sys_realloc(self.data as usize, self.length * size_of::<T>()) as *mut T;
            ptr::write(self.data.offset(self.length as isize - 1), value);
        }
    }

    /// Pop the last element
    pub fn pop(&mut self) -> Option<T> {
        if self.length > 0 {
            self.length -= 1;
            unsafe {
                let item = ptr::read(self.data.offset(self.length as isize));
                self.data = sys_realloc(self.data as usize, self.length * size_of::<T>()) as *mut T;

                Option::Some(item)
            }
        } else {
            Option::None
        }
    }

    /// Get the length of the vector
    pub fn len(&self) -> usize {
        self.length
    }

    /// Create an iterator
    pub fn iter(&self) -> VecIterator<T> {
        VecIterator {
            vec: self,
            offset: 0,
        }
    }

    // TODO: Consider returning a slice instead
    pub fn sub(&self, start: usize, count: usize) -> Vec<T> {
        let mut i = start;
        if i > self.len() {
            i = self.len();
        }

        let mut j = i + count;
        if j > self.len() {
            j = self.len();
        }

        let length = j - i;
        if length == 0 {
            return Vec::new();
        }

        unsafe {
            let data = sys_alloc(length * size_of::<T>()) as *mut T;

            for k in i..j {
                ptr::write(data.offset((k - i) as isize),
                           ptr::read(self.data.offset(k as isize)));
            }

            Vec {
                data: data,
                length: length,
            }
        }
    }

    pub fn as_slice(&self) -> &[T] {
        if self.data as usize > 0 && self.length > 0 {
            unsafe { slice::from_raw_parts(self.data, self.length) }
        } else {
            &[]
        }
    }
}

impl<T> Vec<T> where T: Clone {
    /// Append a vector to another vector
    pub fn push_all(&mut self, vec: &Vec<T>) {
        let mut i = self.length as isize;
        self.length += vec.len();
        unsafe {
            self.data = sys_realloc(self.data as usize, self.length * size_of::<T>()) as *mut T;

            for value in vec.iter() {
                ptr::write(self.data.offset(i), value.clone());
                i += 1;
            }
        }
    }
}

impl<T> Clone for Vec<T> where T: Clone {
    fn clone(&self) -> Vec<T> {
        let mut ret = Vec::new();
        ret.push_all(self);
        ret
    }
}

impl<T> Drop for Vec<T> {
    fn drop(&mut self) {
        unsafe {
            for i in 0..self.len() {
                ptr::read(self.data.offset(i as isize));
            }

            sys_unalloc(self.data as usize);
            self.data = 0 as *mut T;
            self.length = 0;
        }
    }
}
<commit_msg>Add vec!<commit_after>use core::clone::Clone;
use core::iter::Iterator;
use core::mem::size_of;
use core::ops::Drop;
use core::option::Option;
use core::ptr;
use core::slice;
use core::slice::SliceExt;

use syscall::call::*;

#[macro_export]
macro_rules! vec {
    ($($x:expr),*) => (
        Vec::from_slice(&[$($x),*])
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// An iterator over a vec
pub struct VecIterator<'a, T: 'a> {
    vec: &'a Vec<T>,
    offset: usize,
}

impl <'a, T> Iterator for VecIterator<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item> {
        match self.vec.get(self.offset) {
            Option::Some(item) => {
                self.offset += 1;
                Option::Some(item)
            }
            Option::None => {
                Option::None
            }
        }
    }
}

/// A owned, heap allocated list of elements
pub struct Vec<T> {
    pub data: *mut T,
    pub length: usize,
}

impl <T> Vec<T> {
    /// Create a empty vector
    pub fn new() -> Vec<T> {
        Vec::<T> {
            data: 0 as *mut T,
            length: 0,
        }
    }

    /// Convert to pointer
    pub unsafe fn as_ptr(&self) -> *const T {
        self.data
    }

    /// Convert from a raw (unsafe) buffer
    pub unsafe fn from_raw_buf(ptr: *const T, len: usize) -> Vec<T> {
        let data = sys_alloc(size_of::<T>() * len) as *mut T;

        ptr::copy(ptr, data, len);

        Vec::<T> {
            data: data,
            length: len,
        }
    }

    pub fn from_slice(slice: &[T]) -> Vec<T> {
        let data;
        unsafe{
            data = sys_alloc(size_of::<T>() * slice.len()) as *mut T;

            ptr::copy(slice.as_ptr(), data, slice.len());
        }

        Vec::<T> {
            data: data,
            length: slice.len()
        }
    }

    /// Get the nth element. Returns None if out of bounds.
    pub fn get(&self, i: usize) -> Option<&mut T> {
        if i >= self.length {
            Option::None
        } else {
            unsafe { Option::Some(&mut *self.data.offset(i as isize)) }
        }
    }

    /// Set the nth element
    pub fn set(&self, i: usize, value: T) {
        if i <= self.length {
            unsafe {
                ptr::write(self.data.offset(i as isize), value);
            }
        }
    }

    /// Insert element at a given position
    pub fn insert(&mut self, i: usize, value: T) {
        if i <= self.length {
            self.length += 1;
            unsafe {
                self.data = sys_realloc(self.data as usize, self.length * size_of::<T>()) as *mut T;

                //Move all things ahead of insert forward one
                let mut j = self.length - 1;
                while j > i {
                    ptr::write(self.data.offset(j as isize),
                               ptr::read(self.data.offset(j as isize - 1)));
                    j -= 1;
                }

                ptr::write(self.data.offset(i as isize), value);
            }
        }
    }

    /// Remove a element and return it as a Option
    pub fn remove(&mut self, i: usize) -> Option<T> {
        if i < self.length {
            self.length -= 1;
            unsafe {
                let item = ptr::read(self.data.offset(i as isize));

                //Move all things ahead of remove back one
                let mut j = i;
                while j < self.length {
                    ptr::write(self.data.offset(j as isize),
                               ptr::read(self.data.offset(j as isize + 1)));
                    j += 1;
                }

                self.data = sys_realloc(self.data as usize, self.length * size_of::<T>()) as *mut T;

                Option::Some(item)
            }
        } else {
            Option::None
        }
    }

    /// Push an element to a vector
    pub fn push(&mut self, value: T) {
        self.length += 1;
        unsafe {
            self.data = sys_realloc(self.data as usize, self.length * size_of::<T>()) as *mut T;
            ptr::write(self.data.offset(self.length as isize - 1), value);
        }
    }

    /// Pop the last element
    pub fn pop(&mut self) -> Option<T> {
        if self.length > 0 {
            self.length -= 1;
            unsafe {
                let item = ptr::read(self.data.offset(self.length as isize));
                self.data = sys_realloc(self.data as usize, self.length * size_of::<T>()) as *mut T;

                Option::Some(item)
            }
        } else {
            Option::None
        }
    }

    /// Get the length of the vector
    pub fn len(&self) -> usize {
        self.length
    }

    /// Create an iterator
    pub fn iter(&self) -> VecIterator<T> {
        VecIterator {
            vec: self,
            offset: 0,
        }
    }

    // TODO: Consider returning a slice instead
    pub fn sub(&self, start: usize, count: usize) -> Vec<T> {
        let mut i = start;
        if i > self.len() {
            i = self.len();
        }

        let mut j = i + count;
        if j > self.len() {
            j = self.len();
        }

        let length = j - i;
        if length == 0 {
            return Vec::new();
        }

        unsafe {
            let data = sys_alloc(length * size_of::<T>()) as *mut T;

            for k in i..j {
                ptr::write(data.offset((k - i) as isize),
                           ptr::read(self.data.offset(k as isize)));
            }

            Vec {
                data: data,
                length: length,
            }
        }
    }

    pub fn as_slice(&self) -> &[T] {
        if self.data as usize > 0 && self.length > 0 {
            unsafe { slice::from_raw_parts(self.data, self.length) }
        } else {
            &[]
        }
    }
}

impl<T> Vec<T> where T: Clone {
    /// Append a vector to another vector
    pub fn push_all(&mut self, vec: &Vec<T>) {
        let mut i = self.length as isize;
        self.length += vec.len();
        unsafe {
            self.data = sys_realloc(self.data as usize, self.length * size_of::<T>()) as *mut T;

            for value in vec.iter() {
                ptr::write(self.data.offset(i), value.clone());
                i += 1;
            }
        }
    }
}

impl<T> Clone for Vec<T> where T: Clone {
    fn clone(&self) -> Vec<T> {
        let mut ret = Vec::new();
        ret.push_all(self);
        ret
    }
}

impl<T> Drop for Vec<T> {
    fn drop(&mut self) {
        unsafe {
            for i in 0..self.len() {
                ptr::read(self.data.offset(i as isize));
            }

            sys_unalloc(self.data as usize);
            self.data = 0 as *mut T;
            self.length = 0;
        }
    }
}
<|endoftext|>


<commit_before>//! Semi-internal functionality related to networking.
use std::fmt;

use {hyper, serde_json, serde_ignored};

use futures::{Poll, Future, Stream};
use url::Url;

use {Token, TokenStorage, EndpointType, Error};

/// Struct mirroring `hyper`'s FutureResponse, but with parsing that happens after the request is finished.
#[must_use = "futures do nothing unless polled"]
pub struct FutureResponse<R: EndpointType>(Box<Future<Item = R, Error = Error>>);

impl<R: EndpointType> fmt::Debug for FutureResponse<R> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("ScreepsFutureResponse")
            .field("inner", &"<boxed future>")
            .finish()
    }
}

impl<R> Future for FutureResponse<R>
    where R: EndpointType
{
    type Item = R;
    type Error = Error;

    fn poll(&mut self) -> Poll<R, Error> {
        self.0.poll()
    }
}

/// Interpret a hyper result as the result from a specific endpoint.
///
/// The returned future will:
///
/// - Wait for the hyper request to finish
/// - Send any auth token found in headers back to token storage
/// - Wait for hyper request body, collecting it into a single chunk
/// - Parse JSON body as the given `EndpointType`, and return result/error.
///
/// All errors returned will have the given `Url` contained as part of the context.
///
/// # Parameters
///
/// - `token_storage`: token storage to store any tokens that were refreshed.
/// - `used_token`: token that was used when sending this request, if any.
///   if the server doesn't return a new token, and this is Some, the inner
///   token will be returned to the token storage.
/// - `url`: url that is being queried, used only for error and warning messages.
/// - `response`: actual hyper response that we're interpreting
pub fn interpret<T, R>(token_storage: T,
                       used_token: Option<Token>,
                       url: Url,
                       response: hyper::client::FutureResponse)
                       -> FutureResponse<R>
    where T: TokenStorage,
          R: EndpointType
{
    FutureResponse(Box::new(response.then(move |result| {
            let new_result = match result {
                Ok(v) => Ok((token_storage, used_token, url, v)),
                Err(e) => Err(Error::with_url(e, Some(url))),
            };

            new_result
        })
        .and_then(|(token_storage, used_token, url, mut response)| {
            let token_to_return = {
                header! { (TokenHeader, "X-Token") => [String] }

                let new_token = response.headers_mut().remove::<TokenHeader>().map(|h| h.0);

                match new_token {
                    Some(token) => {
                        if token.is_empty() {
                            Some(token)
                        } else {
                            used_token
                        }
                    }
                    None => used_token,
                }
            };

            if let Some(token) = token_to_return {
                token_storage.return_token(token);
            }

            Ok((url, response))
        })
        .and_then(|(url, response)| {
            let status = response.status();

            response.body().concat2().then(move |result| match result {
                Ok(v) => Ok((status, url, v)),
                Err(e) => Err(Error::with_url(e, Some(url))),
            })
        })
        .and_then(|(status, url, data): (hyper::StatusCode, _, hyper::Chunk)| {
            let json_result = serde_json::from_slice(&data);

            // insert this check here so we can include response body in status errors.
            if !status.is_success() {
                if let Ok(json) = json_result {
                    return Err(Error::with_json(status, Some(url), Some(json)));
                } else {
                    return Err(Error::with_body(status, Some(url), Some(data)));
                }
            }

            let parsed = match json_result {
                Ok(json) => deserialize_with_warnings::<R>(&json, &url)?,
                Err(e) => return Err(Error::with_body(e, Some(url), Some(data))),
            };

            R::from_raw(parsed)
        })))
}

fn deserialize_with_warnings<T: EndpointType>(input: &serde_json::Value, url: &Url) -> Result<T::RequestResult, Error> {
    let mut unused = Vec::new();

    let res = match serde_ignored::deserialize::<_, _, T::RequestResult>(input, |path| unused.push(path.to_string())) {
        Ok(v) => Ok(v),
        Err(e1) => {
            unused.clear();
            match serde_ignored::deserialize::<_, _, T::ErrorResult>(input, |path| unused.push(path.to_string())) {
                Ok(v) => Err(Error::with_json(v, Some(url.clone()), Some(input.clone()))),
                // Favor the primary parsing error if one occurs parsing the error type as well.
                Err(_) => Err(Error::with_json(e1, Some(url.clone()), Some(input.clone()))),
            }
        }
    };

    if !unused.is_empty() {
        warn!("screeps API lib didn't parse some data retrieved from: {}\n\
               full data: {}\n\
               unparsed fields: {:?}",
              url,
              serde_json::to_string(input).unwrap(),
              unused);
    }

    res
}
<commit_msg>Include json data in errors for parsing failure.<commit_after>//! Semi-internal functionality related to networking.
use std::fmt;

use {hyper, serde_json, serde_ignored};

use futures::{Poll, Future, Stream};
use url::Url;

use {Token, TokenStorage, EndpointType, Error};

/// Struct mirroring `hyper`'s FutureResponse, but with parsing that happens after the request is finished.
#[must_use = "futures do nothing unless polled"]
pub struct FutureResponse<R: EndpointType>(Box<Future<Item = R, Error = Error>>);

impl<R: EndpointType> fmt::Debug for FutureResponse<R> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("ScreepsFutureResponse")
            .field("inner", &"<boxed future>")
            .finish()
    }
}

impl<R> Future for FutureResponse<R>
    where R: EndpointType
{
    type Item = R;
    type Error = Error;

    fn poll(&mut self) -> Poll<R, Error> {
        self.0.poll()
    }
}

/// Interpret a hyper result as the result from a specific endpoint.
///
/// The returned future will:
///
/// - Wait for the hyper request to finish
/// - Send any auth token found in headers back to token storage
/// - Wait for hyper request body, collecting it into a single chunk
/// - Parse JSON body as the given `EndpointType`, and return result/error.
///
/// All errors returned will have the given `Url` contained as part of the context.
///
/// # Parameters
///
/// - `token_storage`: token storage to store any tokens that were refreshed.
/// - `used_token`: token that was used when sending this request, if any.
///   if the server doesn't return a new token, and this is Some, the inner
///   token will be returned to the token storage.
/// - `url`: url that is being queried, used only for error and warning messages.
/// - `response`: actual hyper response that we're interpreting
pub fn interpret<T, R>(token_storage: T,
                       used_token: Option<Token>,
                       url: Url,
                       response: hyper::client::FutureResponse)
                       -> FutureResponse<R>
    where T: TokenStorage,
          R: EndpointType
{
    FutureResponse(Box::new(response.then(move |result| {
            let new_result = match result {
                Ok(v) => Ok((token_storage, used_token, url, v)),
                Err(e) => Err(Error::with_url(e, Some(url))),
            };

            new_result
        })
        .and_then(|(token_storage, used_token, url, mut response)| {
            let token_to_return = {
                header! { (TokenHeader, "X-Token") => [String] }

                let new_token = response.headers_mut().remove::<TokenHeader>().map(|h| h.0);

                match new_token {
                    Some(token) => {
                        if token.is_empty() {
                            Some(token)
                        } else {
                            used_token
                        }
                    }
                    None => used_token,
                }
            };

            if let Some(token) = token_to_return {
                token_storage.return_token(token);
            }

            Ok((url, response))
        })
        .and_then(|(url, response)| {
            let status = response.status();

            response.body().concat2().then(move |result| match result {
                Ok(v) => Ok((status, url, v)),
                Err(e) => Err(Error::with_url(e, Some(url))),
            })
        })
        .and_then(|(status, url, data): (hyper::StatusCode, _, hyper::Chunk)| {
            let json_result = serde_json::from_slice(&data);

            // insert this check here so we can include response body in status errors.
            if !status.is_success() {
                if let Ok(json) = json_result {
                    return Err(Error::with_json(status, Some(url), Some(json)));
                } else {
                    return Err(Error::with_body(status, Some(url), Some(data)));
                }
            }

            let json = match json_result {
                Ok(v) => v,
                Err(e) => return Err(Error::with_body(e, Some(url), Some(data))),
            };
            let parsed = match deserialize_with_warnings::<R>(&json, &url) {
                Ok(v) => v,
                Err(e) => return Err(Error::with_json(e, Some(url), Some(json))),
            };

            R::from_raw(parsed).map_err(|e| Error::with_json(e, Some(url), Some(json)))
        })))
}

fn deserialize_with_warnings<T: EndpointType>(input: &serde_json::Value, url: &Url) -> Result<T::RequestResult, Error> {
    let mut unused = Vec::new();

    let res = match serde_ignored::deserialize::<_, _, T::RequestResult>(input, |path| unused.push(path.to_string())) {
        Ok(v) => Ok(v),
        Err(e1) => {
            unused.clear();
            match serde_ignored::deserialize::<_, _, T::ErrorResult>(input, |path| unused.push(path.to_string())) {
                Ok(v) => Err(Error::with_json(v, Some(url.clone()), Some(input.clone()))),
                // Favor the primary parsing error if one occurs parsing the error type as well.
                Err(_) => Err(Error::with_json(e1, Some(url.clone()), Some(input.clone()))),
            }
        }
    };

    if !unused.is_empty() {
        warn!("screeps API lib didn't parse some data retrieved from: {}\n\
               full data: {}\n\
               unparsed fields: {:?}",
              url,
              serde_json::to_string(input).unwrap(),
              unused);
    }

    res
}
<|endoftext|>


<commit_before>use {Error, Result, Statement};
use types::ToSql;

impl<'conn> Statement<'conn> {
    /// Execute an INSERT and return the ROWID.
    ///
    /// # Failure
    /// Will return `Err` if no row is inserted or many rows are inserted.
    pub fn insert(&mut self, params: &[&ToSql]) -> Result<i64> {
        // Some non-insertion queries could still return 1 change (an UPDATE, for example), so
        // to guard against that we can check that the connection's last_insert_rowid() changes
        // after we execute the statement.
        let prev_rowid = self.conn.last_insert_rowid();
        let changes = try!(self.execute(params));
        let new_rowid = self.conn.last_insert_rowid();
        match changes {
            1 if prev_rowid != new_rowid => Ok(new_rowid),
            1 if prev_rowid == new_rowid => Err(Error::StatementFailedToInsertRow),
            _ => Err(Error::StatementChangedRows(changes)),
        }
    }

    /// Return `true` if a query in the SQL statement it executes returns one or more rows
    /// and `false` if the SQL returns an empty set.
    pub fn exists(&mut self, params: &[&ToSql]) -> Result<bool> {
        self.reset_if_needed();
        let mut rows = try!(self.query(params));
        match rows.next() {
            Some(_) => Ok(true),
            None => Ok(false),
        }
    }
}

#[cfg(test)]
mod test {
    use {Connection, Error};

    #[test]
    fn test_insert() {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)").unwrap();
        let mut stmt = db.prepare("INSERT OR IGNORE INTO foo (x) VALUES (?)").unwrap();
        assert_eq!(stmt.insert(&[&1i32]).unwrap(), 1);
        assert_eq!(stmt.insert(&[&2i32]).unwrap(), 2);
        match stmt.insert(&[&1i32]).unwrap_err() {
            Error::StatementChangedRows(0) => (),
            err => panic!("Unexpected error {}", err),
        }
        let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4").unwrap();
        match multi.insert(&[]).unwrap_err() {
            Error::StatementChangedRows(2) => (),
            err => panic!("Unexpected error {}", err),
        }
    }

    #[test]
    fn test_insert_failures() {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)").unwrap();
        let mut insert = db.prepare("INSERT INTO foo (x) VALUES (?)").unwrap();
        let mut update = db.prepare("UPDATE foo SET x = ?").unwrap();

        assert_eq!(insert.insert(&[&1i32]).unwrap(), 1);

        match update.insert(&[&2i32]) {
            Err(Error::StatementFailedToInsertRow) => (),
            r => panic!("Unexpected result {:?}", r),
        }
    }

    #[test]
    fn test_exists() {
        let db = Connection::open_in_memory().unwrap();
        let sql = "BEGIN;
                   CREATE TABLE foo(x INTEGER);
                   INSERT INTO foo VALUES(1);
                   INSERT INTO foo VALUES(2);
                   END;";
        db.execute_batch(sql).unwrap();
        let mut stmt = db.prepare("SELECT 1 FROM foo WHERE x = ?").unwrap();
        assert!(stmt.exists(&[&1i32]).unwrap());
        assert!(stmt.exists(&[&2i32]).unwrap());
        assert!(!stmt.exists(&[&0i32]).unwrap());
    }
}
<commit_msg>Reset as soon as possible.<commit_after>use {Error, Result, Statement};
use types::ToSql;

impl<'conn> Statement<'conn> {
    /// Execute an INSERT and return the ROWID.
    ///
    /// # Failure
    /// Will return `Err` if no row is inserted or many rows are inserted.
    pub fn insert(&mut self, params: &[&ToSql]) -> Result<i64> {
        // Some non-insertion queries could still return 1 change (an UPDATE, for example), so
        // to guard against that we can check that the connection's last_insert_rowid() changes
        // after we execute the statement.
        let prev_rowid = self.conn.last_insert_rowid();
        let changes = try!(self.execute(params));
        let new_rowid = self.conn.last_insert_rowid();
        match changes {
            1 if prev_rowid != new_rowid => Ok(new_rowid),
            1 if prev_rowid == new_rowid => Err(Error::StatementFailedToInsertRow),
            _ => Err(Error::StatementChangedRows(changes)),
        }
    }

    /// Return `true` if a query in the SQL statement it executes returns one or more rows
    /// and `false` if the SQL returns an empty set.
    pub fn exists(&mut self, params: &[&ToSql]) -> Result<bool> {
        self.reset_if_needed();
        let exists = {
            let mut rows = try!(self.query(params));
            match rows.next() {
                Some(_) => Ok(true),
                None => Ok(false),
            }
        };
        self.reset_if_needed();
        return exists;
    }
}

#[cfg(test)]
mod test {
    use {Connection, Error};

    #[test]
    fn test_insert() {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)").unwrap();
        let mut stmt = db.prepare("INSERT OR IGNORE INTO foo (x) VALUES (?)").unwrap();
        assert_eq!(stmt.insert(&[&1i32]).unwrap(), 1);
        assert_eq!(stmt.insert(&[&2i32]).unwrap(), 2);
        match stmt.insert(&[&1i32]).unwrap_err() {
            Error::StatementChangedRows(0) => (),
            err => panic!("Unexpected error {}", err),
        }
        let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4").unwrap();
        match multi.insert(&[]).unwrap_err() {
            Error::StatementChangedRows(2) => (),
            err => panic!("Unexpected error {}", err),
        }
    }

    #[test]
    fn test_insert_failures() {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)").unwrap();
        let mut insert = db.prepare("INSERT INTO foo (x) VALUES (?)").unwrap();
        let mut update = db.prepare("UPDATE foo SET x = ?").unwrap();

        assert_eq!(insert.insert(&[&1i32]).unwrap(), 1);

        match update.insert(&[&2i32]) {
            Err(Error::StatementFailedToInsertRow) => (),
            r => panic!("Unexpected result {:?}", r),
        }
    }

    #[test]
    fn test_exists() {
        let db = Connection::open_in_memory().unwrap();
        let sql = "BEGIN;
                   CREATE TABLE foo(x INTEGER);
                   INSERT INTO foo VALUES(1);
                   INSERT INTO foo VALUES(2);
                   END;";
        db.execute_batch(sql).unwrap();
        let mut stmt = db.prepare("SELECT 1 FROM foo WHERE x = ?").unwrap();
        assert!(stmt.exists(&[&1i32]).unwrap());
        assert!(stmt.exists(&[&2i32]).unwrap());
        assert!(!stmt.exists(&[&0i32]).unwrap());
    }
}
<|endoftext|>