<commit_before>use std::time::{SystemTime, Duration};
use rand;
use rand::Rng;
use glutin;
use cgmath;
use cgmath::{Matrix4, EuclideanVector};
use render;

pub struct InputState {
	left_button_pressed: bool,
	mouse_position: b2::Vec2,
}

fn new_ball(world: &mut b2::World, pos: b2::Vec2) {
	let mut rng = rand::thread_rng();
	let radius: f32 = (rng.gen::<f32>() * 1.0) + 1.0;

	let mut circle_shape = b2::CircleShape::new();
	circle_shape.set_radius(radius);

	let mut f_def = b2::FixtureDef::new();
	f_def.density = (rng.gen::<f32>() * 1.0) + 1.0;
	f_def.restitution = 0.2;
	f_def.friction = 0.3;

	let mut b_def = b2::BodyDef::new();
	b_def.body_type = b2::BodyType::Dynamic;
	b_def.position = pos;
	let handle = world.create_body(&b_def);
	world.get_body_mut(handle)
		.create_fixture(&circle_shape, &mut f_def);
}

use wrapped2d::b2;
use std::f64::consts;

pub struct Viewport {
	width: u32,
	height: u32,
	pub ratio: f32,
	pub scale: f32,
}

impl Viewport {
	fn rect(w: u32, h: u32, scale: f32) -> Viewport {
		Viewport {
			width: w,
			height: h,
			ratio: (w as f32 / h as f32),
			scale: scale,
		}
	}

	fn to_world(&self, x: u32, y: u32) -> (f32, f32) {
		let dx = self.width as f32 / self.scale;
		let tx = (x as f32 - (self.width as f32 * 0.5)) / dx;
		let ty = ((self.height as f32 * 0.5) - y as f32) / dx;
		(tx, ty)
	}
}

struct Cycle<T: Copy> {
	items: Vec<T>,
	index: usize,
}

impl<T> Cycle<T>
    where T: Copy
{
	pub fn new(items: &[T]) -> Cycle<T> {
		Cycle {
			items: items.to_vec(),
			index: 0,
		}
	}

	pub fn get(&self) -> T {
		self.items[self.index]
	}

	pub fn next(&mut self) -> T {
		self.index = (self.index + 1) % self.items.len();
		self.items[self.index]
	}
}

pub struct App {
	pub viewport: Viewport,
	input_state: InputState,
	world: b2::World,
	wall_clock_start: SystemTime,
	frame_count: u32,
	frame_start: SystemTime,
	frame_elapsed: f32,
	frame_smooth: Smooth<f32>,
	lights: Cycle<[f32; 4]>,
	backgrounds: Cycle<[f32; 4]>,
}

pub struct Environment {
	pub light: [f32; 4],
	pub background: [f32; 4],
}

pub struct Update {
	pub frame_count: u32,
	pub wall_clock_elapsed: Duration,
	pub frame_elapsed: f32,
	pub frame_time: f32,
	pub frame_time_smooth: f32,
	pub fps: f32,
}

impl App {
	pub fn new(w: u32, h: u32, scale: f32) -> App {
		App {
			viewport: Viewport::rect(w, h, scale),
			input_state: InputState {
				left_button_pressed: false,
				mouse_position: b2::Vec2 { x: 0.0, y: 0.0 },
			},
			lights: Self::init_lights(),
			backgrounds: Self::init_backgrounds(),
			world: new_world(),
			frame_count: 0u32,
			frame_elapsed: 0.0f32,
			frame_start: SystemTime::now(),
			wall_clock_start: SystemTime::now(),
			frame_smooth: Smooth::new(120),
		}
	}

	fn init_lights() -> Cycle<[f32; 4]> {
		Cycle::new(&[[0.001, 0.001, 0.001, 1.0],
					 [0.01, 0.01, 0.01, 1.0],
		             [0.1, 0.1, 0.1, 1.0],
		             [0.31, 0.31, 0.31, 0.5],
		             [1.0, 1.0, 1.0, 1.0],
		             [3.1, 3.1, 3.1, 1.0],
		             [10.0, 10.0, 10.0, 1.0],
		             [31.0, 31.0, 31.0, 1.0],
		             [100.0, 100.0, 100.0, 1.0]])
	}

	fn init_backgrounds() -> Cycle<[f32; 4]> {
		Cycle::new(&[[0., 0., 0., 1.0],
					 [0.01, 0.01, 0.01, 1.0],
		             [0.1, 0.1, 0.1, 1.0],
		             [0.5, 0.5, 0.5, 0.5],
		             [1.0, 1.0, 1.0, 1.0],
		             [3.1, 3.1, 3.1, 1.0],
		             [10.0, 10.0, 10.0, 1.0]])
	}

	fn on_click(&mut self, btn: glutin::MouseButton, pos: b2::Vec2) {
		match btn {
			glutin::MouseButton::Left => {
				self.input_state.left_button_pressed = true;
				new_ball(&mut self.world, pos);
			}
			_ => (),
		}
	}

	fn on_drag(&mut self, pos: b2::Vec2) {
		new_ball(&mut self.world, pos);
	}

	fn on_release(&mut self, btn: glutin::MouseButton, _: b2::Vec2) {
		match btn {
			glutin::MouseButton::Left => {
				self.input_state.left_button_pressed = false;
			}
			_ => (),
		}
	}

	pub fn on_keyboard_input(&mut self, e: glutin::Event) {
		match e {
			glutin::Event::ReceivedCharacter(char) => {
				match char {
					_ => println!("Key pressed {:?}", char),
				}
			}
			glutin::Event::KeyboardInput(glutin::ElementState::Pressed, scancode, vk) => {
				match vk {
					Some(glutin::VirtualKeyCode::L) => {
						self.lights.next();
					}
					Some(glutin::VirtualKeyCode::B) => {
						self.backgrounds.next();
					}
					_ => println!("Key pressed {:?}/{:?}", scancode, vk),
				}
			}
			_ => (),
		}
	}

	pub fn on_mouse_input(&mut self, e: glutin::Event) {
		match e {
			glutin::Event::MouseInput(glutin::ElementState::Released, b) => {
				let pos = self.input_state.mouse_position;
				self.on_release(b, pos);
			}
			glutin::Event::MouseInput(glutin::ElementState::Pressed, b) => {
				let pos = self.input_state.mouse_position;
				self.on_click(b, pos);
			}
			glutin::Event::MouseMoved(x, y) => {
				fn transform_pos(viewport: &Viewport, x: u32, y: u32) -> b2::Vec2 {
					let (tx, ty) = viewport.to_world(x, y);
					return b2::Vec2 { x: tx, y: ty };
				}
				let pos = transform_pos(&self.viewport, x as u32, y as u32);
				self.input_state.mouse_position = pos;
				if self.input_state.left_button_pressed {
					self.on_drag(pos);
				}
			}
			_ => (),
		}
	}

	pub fn on_resize(&mut self, width: u32, height: u32) {
		self.viewport = Viewport::rect(width, height, self.viewport.scale);
	}

	pub fn render(&self, renderer: &mut render::Draw) {
		for (_, b) in self.world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			let angle = (*body).angle() as f32;
			use cgmath::Rotation3;
			let body_rot = Matrix4::from(cgmath::Quaternion::from_axis_angle(cgmath::Vector3::unit_z(),
			                                                                 cgmath::rad(angle)));
			let body_trans = Matrix4::from_translation(cgmath::Vector3::new(position.x, position.y, 0.0));

			let body_transform = body_trans * body_rot;

			for (_, f) in body.fixtures() {
				let fixture = f.borrow();
				let shape = (*fixture).shape();
				let density = (*fixture).density();

				match *shape {
					b2::UnknownShape::Circle(ref s) => {
						let p = s.position();
						let r = s.radius() as f32;

						let fixture_scale = Matrix4::from_scale(r);
						let fixture_trans = Matrix4::from_translation(cgmath::Vector3::new(p.x, p.y, 0.0));
						let transform = body_transform * fixture_trans * fixture_scale;

						let lightness = 1. - density * 0.5;

						let color = [0., 10. * lightness, 0., 1.];

						renderer.draw_quad(&transform.into(), color);
					}
					b2::UnknownShape::Polygon(_) => {
						// TODO: need to draw fill poly
					}
					_ => (),
				}
			}
		}
	}

	pub fn environment(&self) -> Environment {
		Environment {
			light: self.lights.get(),
			background: self.backgrounds.get(),
		}
	}

	pub fn update(&mut self) -> Result<Update, ()> {
		match self.frame_start.elapsed() {
			Ok(dt) => {
				let frame_time = (dt.as_secs() as f32) + (dt.subsec_nanos() as f32) * 1e-9;
				let frame_time_smooth = self.frame_smooth.smooth(frame_time);
				self.update_physics(frame_time_smooth);
				self.frame_elapsed += frame_time;
				self.frame_start = SystemTime::now();
				self.frame_count += 1;

				Ok(Update {
					wall_clock_elapsed: self.wall_clock_start.elapsed().unwrap_or_else(|_| Duration::new(0, 0)),
					frame_count: self.frame_count,
					frame_elapsed: self.frame_elapsed,
					frame_time: frame_time,
					frame_time_smooth: frame_time_smooth,
					fps: 1.0 / frame_time_smooth,
				})
			}

			Err(_) => Err(()),
		}
	}

	fn update_physics(&mut self, dt: f32) {
		let world = &mut self.world;
		world.step(dt, 8, 3);
		const MAX_RADIUS: f32 = 5.0;
		let (_, edge) = self.viewport.to_world(0, self.viewport.height);
		let mut v = Vec::new();
		for (h, b) in world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			if position.y < (edge - MAX_RADIUS) {
				v.push(h);
			}
		}
		for h in v {
			world.destroy_body(h);
		}
	}
}

fn new_world() -> b2::World {
	let mut world = b2::World::new(&b2::Vec2 { x: 0.0, y: -9.8 });

	let mut b_def = b2::BodyDef::new();
	b_def.body_type = b2::BodyType::Static;
	b_def.position = b2::Vec2 { x: 0.0, y: -8.0 };

	let mut ground_box = b2::PolygonShape::new();
	{
		ground_box.set_as_box(20.0, 1.0);
		let ground_handle = world.create_body(&b_def);
		let ground = &mut world.get_body_mut(ground_handle);
		ground.create_fast_fixture(&ground_box, 0.);

		ground_box.set_as_oriented_box(1.0,
		                               5.0,
		                               &b2::Vec2 { x: 21.0, y: 5.0 },
		                               (-consts::FRAC_PI_8) as f32);
		ground.create_fast_fixture(&ground_box, 0.);

		ground_box.set_as_oriented_box(1.0,
		                               5.0,
		                               &b2::Vec2 { x: -21.0, y: 5.0 },
		                               (consts::FRAC_PI_8) as f32);
		ground.create_fast_fixture(&ground_box, 0.);
	}
	world
}

pub struct Smooth<S: ::num::Num> {
	ptr: usize,
	count: usize,
	acc: S,
	last: S,
	values: Vec<S>,
}

impl<S: ::num::Num + ::num::NumCast + ::std::marker::Copy> Smooth<S> {
	pub fn new(window_size: usize) -> Smooth<S> {
		Smooth {
			ptr: 0,
			count: 0,
			last: S::zero(),
			acc: S::zero(),
			values: vec![S::zero(); window_size],
		}
	}

	pub fn smooth(&mut self, value: S) -> S {
		let len = self.values.len();
		if self.count < len {
			self.count = self.count + 1;
		} else {
			self.acc = self.acc - self.values[self.ptr];
		}
		self.acc = self.acc + value;
		self.values[self.ptr] = value;
		self.ptr = ((self.ptr + 1) % len) as usize;
		self.last = self.acc / ::num::cast(self.count).unwrap();
		self.last
	}
}
<commit_msg>Formatted<commit_after>use std::time::{SystemTime, Duration};
use rand;
use rand::Rng;
use glutin;
use cgmath;
use cgmath::{Matrix4, EuclideanVector};
use render;

pub struct InputState {
	left_button_pressed: bool,
	mouse_position: b2::Vec2,
}

fn new_ball(world: &mut b2::World, pos: b2::Vec2) {
	let mut rng = rand::thread_rng();
	let radius: f32 = (rng.gen::<f32>() * 1.0) + 1.0;

	let mut circle_shape = b2::CircleShape::new();
	circle_shape.set_radius(radius);

	let mut f_def = b2::FixtureDef::new();
	f_def.density = (rng.gen::<f32>() * 1.0) + 1.0;
	f_def.restitution = 0.2;
	f_def.friction = 0.3;

	let mut b_def = b2::BodyDef::new();
	b_def.body_type = b2::BodyType::Dynamic;
	b_def.position = pos;
	let handle = world.create_body(&b_def);
	world.get_body_mut(handle)
	     .create_fixture(&circle_shape, &mut f_def);
}

use wrapped2d::b2;
use std::f64::consts;

pub struct Viewport {
	width: u32,
	height: u32,
	pub ratio: f32,
	pub scale: f32,
}

impl Viewport {
	fn rect(w: u32, h: u32, scale: f32) -> Viewport {
		Viewport {
			width: w,
			height: h,
			ratio: (w as f32 / h as f32),
			scale: scale,
		}
	}

	fn to_world(&self, x: u32, y: u32) -> (f32, f32) {
		let dx = self.width as f32 / self.scale;
		let tx = (x as f32 - (self.width as f32 * 0.5)) / dx;
		let ty = ((self.height as f32 * 0.5) - y as f32) / dx;
		(tx, ty)
	}
}

struct Cycle<T: Copy> {
	items: Vec<T>,
	index: usize,
}

impl<T> Cycle<T>
    where T: Copy
{
	pub fn new(items: &[T]) -> Cycle<T> {
		Cycle {
			items: items.to_vec(),
			index: 0,
		}
	}

	pub fn get(&self) -> T {
		self.items[self.index]
	}

	pub fn next(&mut self) -> T {
		self.index = (self.index + 1) % self.items.len();
		self.items[self.index]
	}
}

pub struct App {
	pub viewport: Viewport,
	input_state: InputState,
	world: b2::World,
	wall_clock_start: SystemTime,
	frame_count: u32,
	frame_start: SystemTime,
	frame_elapsed: f32,
	frame_smooth: Smooth<f32>,
	lights: Cycle<[f32; 4]>,
	backgrounds: Cycle<[f32; 4]>,
}

pub struct Environment {
	pub light: [f32; 4],
	pub background: [f32; 4],
}

pub struct Update {
	pub frame_count: u32,
	pub wall_clock_elapsed: Duration,
	pub frame_elapsed: f32,
	pub frame_time: f32,
	pub frame_time_smooth: f32,
	pub fps: f32,
}

impl App {
	pub fn new(w: u32, h: u32, scale: f32) -> App {
		App {
			viewport: Viewport::rect(w, h, scale),
			input_state: InputState {
				left_button_pressed: false,
				mouse_position: b2::Vec2 { x: 0.0, y: 0.0 },
			},
			lights: Self::init_lights(),
			backgrounds: Self::init_backgrounds(),
			world: new_world(),
			frame_count: 0u32,
			frame_elapsed: 0.0f32,
			frame_start: SystemTime::now(),
			wall_clock_start: SystemTime::now(),
			frame_smooth: Smooth::new(120),
		}
	}

	fn init_lights() -> Cycle<[f32; 4]> {
		Cycle::new(&[[0.001, 0.001, 0.001, 1.0],
		             [0.01, 0.01, 0.01, 1.0],
		             [0.1, 0.1, 0.1, 1.0],
		             [0.31, 0.31, 0.31, 0.5],
		             [1.0, 1.0, 1.0, 1.0],
		             [3.1, 3.1, 3.1, 1.0],
		             [10.0, 10.0, 10.0, 1.0],
		             [31.0, 31.0, 31.0, 1.0],
		             [100.0, 100.0, 100.0, 1.0]])
	}

	fn init_backgrounds() -> Cycle<[f32; 4]> {
		Cycle::new(&[[0., 0., 0., 1.0],
		             [0.01, 0.01, 0.01, 1.0],
		             [0.1, 0.1, 0.1, 1.0],
		             [0.5, 0.5, 0.5, 0.5],
		             [1.0, 1.0, 1.0, 1.0],
		             [3.1, 3.1, 3.1, 1.0],
		             [10.0, 10.0, 10.0, 1.0]])
	}

	fn on_click(&mut self, btn: glutin::MouseButton, pos: b2::Vec2) {
		match btn {
			glutin::MouseButton::Left => {
				self.input_state.left_button_pressed = true;
				new_ball(&mut self.world, pos);
			}
			_ => (),
		}
	}

	fn on_drag(&mut self, pos: b2::Vec2) {
		new_ball(&mut self.world, pos);
	}

	fn on_release(&mut self, btn: glutin::MouseButton, _: b2::Vec2) {
		match btn {
			glutin::MouseButton::Left => {
				self.input_state.left_button_pressed = false;
			}
			_ => (),
		}
	}

	pub fn on_keyboard_input(&mut self, e: glutin::Event) {
		match e {
			glutin::Event::ReceivedCharacter(char) => {
				match char {
					_ => println!("Key pressed {:?}", char),
				}
			}
			glutin::Event::KeyboardInput(glutin::ElementState::Pressed, scancode, vk) => {
				match vk {
					Some(glutin::VirtualKeyCode::L) => {
						self.lights.next();
					}
					Some(glutin::VirtualKeyCode::B) => {
						self.backgrounds.next();
					}
					_ => println!("Key pressed {:?}/{:?}", scancode, vk),
				}
			}
			_ => (),
		}
	}

	pub fn on_mouse_input(&mut self, e: glutin::Event) {
		match e {
			glutin::Event::MouseInput(glutin::ElementState::Released, b) => {
				let pos = self.input_state.mouse_position;
				self.on_release(b, pos);
			}
			glutin::Event::MouseInput(glutin::ElementState::Pressed, b) => {
				let pos = self.input_state.mouse_position;
				self.on_click(b, pos);
			}
			glutin::Event::MouseMoved(x, y) => {
				fn transform_pos(viewport: &Viewport, x: u32, y: u32) -> b2::Vec2 {
					let (tx, ty) = viewport.to_world(x, y);
					return b2::Vec2 { x: tx, y: ty };
				}
				let pos = transform_pos(&self.viewport, x as u32, y as u32);
				self.input_state.mouse_position = pos;
				if self.input_state.left_button_pressed {
					self.on_drag(pos);
				}
			}
			_ => (),
		}
	}

	pub fn on_resize(&mut self, width: u32, height: u32) {
		self.viewport = Viewport::rect(width, height, self.viewport.scale);
	}

	pub fn render(&self, renderer: &mut render::Draw) {
		for (_, b) in self.world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			let angle = (*body).angle() as f32;
			use cgmath::Rotation3;
			let body_rot = Matrix4::from(cgmath::Quaternion::from_axis_angle(cgmath::Vector3::unit_z(),
			                                                                 cgmath::rad(angle)));
			let body_trans = Matrix4::from_translation(cgmath::Vector3::new(position.x, position.y, 0.0));

			let body_transform = body_trans * body_rot;

			for (_, f) in body.fixtures() {
				let fixture = f.borrow();
				let shape = (*fixture).shape();
				let density = (*fixture).density();

				match *shape {
					b2::UnknownShape::Circle(ref s) => {
						let p = s.position();
						let r = s.radius() as f32;

						let fixture_scale = Matrix4::from_scale(r);
						let fixture_trans = Matrix4::from_translation(cgmath::Vector3::new(p.x, p.y, 0.0));
						let transform = body_transform * fixture_trans * fixture_scale;

						let lightness = 1. - density * 0.5;

						let color = [0., 10. * lightness, 0., 1.];

						renderer.draw_quad(&transform.into(), color);
					}
					b2::UnknownShape::Polygon(_) => {
						// TODO: need to draw fill poly
					}
					_ => (),
				}
			}
		}
	}

	pub fn environment(&self) -> Environment {
		Environment {
			light: self.lights.get(),
			background: self.backgrounds.get(),
		}
	}

	pub fn update(&mut self) -> Result<Update, ()> {
		match self.frame_start.elapsed() {
			Ok(dt) => {
				let frame_time = (dt.as_secs() as f32) + (dt.subsec_nanos() as f32) * 1e-9;
				let frame_time_smooth = self.frame_smooth.smooth(frame_time);
				self.update_physics(frame_time_smooth);
				self.frame_elapsed += frame_time;
				self.frame_start = SystemTime::now();
				self.frame_count += 1;

				Ok(Update {
					wall_clock_elapsed: self.wall_clock_start.elapsed().unwrap_or_else(|_| Duration::new(0, 0)),
					frame_count: self.frame_count,
					frame_elapsed: self.frame_elapsed,
					frame_time: frame_time,
					frame_time_smooth: frame_time_smooth,
					fps: 1.0 / frame_time_smooth,
				})
			}

			Err(_) => Err(()),
		}
	}

	fn update_physics(&mut self, dt: f32) {
		let world = &mut self.world;
		world.step(dt, 8, 3);
		const MAX_RADIUS: f32 = 5.0;
		let (_, edge) = self.viewport.to_world(0, self.viewport.height);
		let mut v = Vec::new();
		for (h, b) in world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			if position.y < (edge - MAX_RADIUS) {
				v.push(h);
			}
		}
		for h in v {
			world.destroy_body(h);
		}
	}
}

fn new_world() -> b2::World {
	let mut world = b2::World::new(&b2::Vec2 { x: 0.0, y: -9.8 });

	let mut b_def = b2::BodyDef::new();
	b_def.body_type = b2::BodyType::Static;
	b_def.position = b2::Vec2 { x: 0.0, y: -8.0 };

	let mut ground_box = b2::PolygonShape::new();
	{
		ground_box.set_as_box(20.0, 1.0);
		let ground_handle = world.create_body(&b_def);
		let ground = &mut world.get_body_mut(ground_handle);
		ground.create_fast_fixture(&ground_box, 0.);

		ground_box.set_as_oriented_box(1.0,
		                               5.0,
		                               &b2::Vec2 { x: 21.0, y: 5.0 },
		                               (-consts::FRAC_PI_8) as f32);
		ground.create_fast_fixture(&ground_box, 0.);

		ground_box.set_as_oriented_box(1.0,
		                               5.0,
		                               &b2::Vec2 { x: -21.0, y: 5.0 },
		                               (consts::FRAC_PI_8) as f32);
		ground.create_fast_fixture(&ground_box, 0.);
	}
	world
}

pub struct Smooth<S: ::num::Num> {
	ptr: usize,
	count: usize,
	acc: S,
	last: S,
	values: Vec<S>,
}

impl<S: ::num::Num + ::num::NumCast + ::std::marker::Copy> Smooth<S> {
	pub fn new(window_size: usize) -> Smooth<S> {
		Smooth {
			ptr: 0,
			count: 0,
			last: S::zero(),
			acc: S::zero(),
			values: vec![S::zero(); window_size],
		}
	}

	pub fn smooth(&mut self, value: S) -> S {
		let len = self.values.len();
		if self.count < len {
			self.count = self.count + 1;
		} else {
			self.acc = self.acc - self.values[self.ptr];
		}
		self.acc = self.acc + value;
		self.values[self.ptr] = value;
		self.ptr = ((self.ptr + 1) % len) as usize;
		self.last = self.acc / ::num::cast(self.count).unwrap();
		self.last
	}
}
<|endoftext|>


<commit_before>use rusticata_macros::*;
use nom::{be_u8,be_u16,be_u32,IResult};
use method::{method,Method};
use generated::*;

named!(pub protocol_header<&[u8]>,
  preceded!(
    tag!(b"AMQP\0"),
    tag!(&[0, 9, 1])
  )
);

pub fn gen_protocol_header<'a>(x:(&'a mut [u8],usize)) -> Result<(&'a mut [u8],usize),GenError> {
  do_gen!(
    x,
    gen_slice!(b"AMQP") >>
    gen_slice!(&[0, 0, 9, 1])
  )
}

// 0      1         3             7                    size+7 size+8
// +------+---------+-------------+   +------------+   +-----------+
// | type | channel |    size     |   | payload    |   | frame-end |
// +------+---------+-------------+   +------------+   +-----------+
//   octet  short        long        size octets           octet

#[derive(Clone,Copy,Debug,PartialEq,Eq)]
pub enum FrameType {
  Method,
  Header,
  Body,
  Heartbeat
}

named!(pub frame_type<FrameType>,
  switch!(be_u8,
    1 => value!(FrameType::Method)
  | 2 => value!(FrameType::Header)
  | 3 => value!(FrameType::Body)
  | 4 => value!(FrameType::Heartbeat)
  )
);

#[derive(Clone,Copy,Debug,PartialEq,Eq)]
pub enum Channel {
  Global,
  Id(u16),
}

named!(pub channel_id<Channel>,
  switch!(be_u16,
    0 => value!(Channel::Global)
  | i => value!(Channel::Id(i))
  )
);

//FIXME: maybe parse the frame header, and leave the payload for later
#[derive(Clone,Copy,Debug,PartialEq,Eq)]
pub struct RawFrame<'a> {
  pub frame_type: FrameType,
  pub channel_id: u16,
  pub size:       u32,
  pub payload:    &'a[u8],
}

named!(pub raw_frame<RawFrame>,
  do_parse!(
    frame:   frame_type    >>
    channel: be_u16        >>
    size:    be_u32        >>
    payload: take!(size)   >>
             tag!(&[0xCE]) >>
    (RawFrame {
      frame_type: frame,
      channel_id: channel,
      size:       size,
      payload:    payload,
    })
  )
);

#[derive(Clone,Debug,PartialEq)]
pub enum Frame<'a> {
  Method(u16, Method),
  //content header
  Header(u16, ()),
  //content Body
  Body(u16, &'a[u8]),
  Heartbeat(u16)
}

pub fn frame(input: &[u8]) -> IResult<&[u8], Frame> {
  let (remaining, raw) = try_parse!(input, raw_frame);
  match raw.frame_type {
    FrameType::Header    => IResult::Done(remaining, Frame::Header(raw.channel_id, ())),
    FrameType::Body      => IResult::Done(remaining, Frame::Body(raw.channel_id, raw.payload)),
    FrameType::Heartbeat => IResult::Done(remaining, Frame::Heartbeat(raw.channel_id)),
    FrameType::Method    => {
      println!("will try to parse a method");
      let (remaining2, m) = try_parse!(raw.payload, method);
      IResult::Done(remaining2, Frame::Method(raw.channel_id, m))
    },
  }
}
<commit_msg>implement gen_method_frame<commit_after>use rusticata_macros::*;
use nom::{be_u8,be_u16,be_u32,IResult};
use method::{method,Method};
use generated::*;

named!(pub protocol_header<&[u8]>,
  preceded!(
    tag!(b"AMQP\0"),
    tag!(&[0, 9, 1])
  )
);

pub fn gen_protocol_header<'a>(x:(&'a mut [u8],usize)) -> Result<(&'a mut [u8],usize),GenError> {
  do_gen!(
    x,
    gen_slice!(b"AMQP") >>
    gen_slice!(&[0, 0, 9, 1])
  )
}

// 0      1         3             7                    size+7 size+8
// +------+---------+-------------+   +------------+   +-----------+
// | type | channel |    size     |   | payload    |   | frame-end |
// +------+---------+-------------+   +------------+   +-----------+
//   octet  short        long        size octets           octet

#[derive(Clone,Copy,Debug,PartialEq,Eq)]
pub enum FrameType {
  Method,
  Header,
  Body,
  Heartbeat
}

named!(pub frame_type<FrameType>,
  switch!(be_u8,
    1 => value!(FrameType::Method)
  | 2 => value!(FrameType::Header)
  | 3 => value!(FrameType::Body)
  | 4 => value!(FrameType::Heartbeat)
  )
);

#[derive(Clone,Copy,Debug,PartialEq,Eq)]
pub enum Channel {
  Global,
  Id(u16),
}

named!(pub channel_id<Channel>,
  switch!(be_u16,
    0 => value!(Channel::Global)
  | i => value!(Channel::Id(i))
  )
);

//FIXME: maybe parse the frame header, and leave the payload for later
#[derive(Clone,Copy,Debug,PartialEq,Eq)]
pub struct RawFrame<'a> {
  pub frame_type: FrameType,
  pub channel_id: u16,
  pub size:       u32,
  pub payload:    &'a[u8],
}

named!(pub raw_frame<RawFrame>,
  do_parse!(
    frame:   frame_type    >>
    channel: be_u16        >>
    size:    be_u32        >>
    payload: take!(size)   >>
             tag!(&[0xCE]) >>
    (RawFrame {
      frame_type: frame,
      channel_id: channel,
      size:       size,
      payload:    payload,
    })
  )
);

#[derive(Clone,Debug,PartialEq)]
pub enum Frame<'a> {
  Method(u16, Method),
  //content header
  Header(u16, ()),
  //content Body
  Body(u16, &'a[u8]),
  Heartbeat(u16)
}

pub fn frame(input: &[u8]) -> IResult<&[u8], Frame> {
  let (remaining, raw) = try_parse!(input, raw_frame);
  match raw.frame_type {
    FrameType::Header    => IResult::Done(remaining, Frame::Header(raw.channel_id, ())),
    FrameType::Body      => IResult::Done(remaining, Frame::Body(raw.channel_id, raw.payload)),
    FrameType::Heartbeat => IResult::Done(remaining, Frame::Heartbeat(raw.channel_id)),
    FrameType::Method    => {
      println!("will try to parse a method");
      let (remaining2, m) = try_parse!(raw.payload, method);
      IResult::Done(remaining2, Frame::Method(raw.channel_id, m))
    },
  }
}

pub fn gen_method_frame<'a>(input:(&'a mut [u8],usize), channel: u16, class: &Class) -> Result<(&'a mut [u8],usize),GenError> {
  if let Ok(input1) = gen_be_u8!(input, 1u8) {
    if let Ok((sl2, index2)) = gen_be_u16!(input1, channel) {
      if let Ok((sl3, index3)) = gen_class((sl2, index2 + 4), class) {
        if let Ok(input4) = gen_be_u32!((sl3, index2), index3 - index2 - 4) {
          gen_be_u8!(input4, 0xCE)
        } else {
          Err(GenError::CustomError(42))
        }
      } else {
        Err(GenError::CustomError(42))
      }
    } else {
      Err(GenError::CustomError(42))
    }
  } else {
    Err(GenError::CustomError(42))
  }
}
<|endoftext|>


<commit_before>/// mush graph backend and abstraction to swap out with custom backend

use uuid::Uuid;
use std::collections::{HashMap,HashSet,VecDeque};

/// unidirectional edge, use two edges for bidirectional/undirected graph
//#[derive(Hash, Eq, PartialEq, Debug)]
#[derive(Debug)]
struct GraphEdge<K> {
    to: Uuid,
    maybe_weight: Option<f64>,
    maybe_custom: Option<K>,
}
impl<K> GraphEdge<K> {
    // this should be private, this should be called by a graph method
    fn new (uuid: Uuid, weight: Option<f64>, custom: Option<K>) -> GraphEdge<K> {
        GraphEdge { to: uuid,
                    maybe_weight:weight,
                    maybe_custom: custom }
    }
    pub fn get_directed (&self) -> &Uuid {
        &self.to
    }

    pub fn get_weight (&self) -> Option<&f64> {
        if let Some(ref w) = self.maybe_weight { Some(w) }
        else { None }
    }
    pub fn get_weight_mut (&mut self) -> Option<&mut f64> {
        if let Some(ref mut w) = self.maybe_weight { Some(w) }
        else { None }
    }

    pub fn get_custom (&self) -> Option<&K> {
        if let Some(ref k) = self.maybe_custom { Some(k) }
        else { None }
    }
    pub fn get_custom_mut (&mut self) -> Option<&mut K> {
        if let Some(ref mut k) = self.maybe_custom { Some(k) }
        else { None }
    }
}

//--

#[derive(Debug)]
struct GraphNode {
    uuid: Uuid,
    edges_to: HashMap<Uuid,Option<f64>>, //to,weight //todo: turn to hashset if using graphedge struct
    edges_from: HashMap<Uuid,Option<f64>>,
}
impl GraphNode {
    fn new (uuid: Uuid) -> GraphNode {
        GraphNode { uuid: uuid,
                    edges_to: HashMap::new(),
                    edges_from: HashMap::new(), }
    }
    /// direct the node towards another node
    // todo: rename me! sounds too similar to unidirectional
    fn direct (&mut self, to:&Uuid, weight: Option<f64>) {
        self.edges_to.insert(*to,weight);
    }
    fn undirect (&mut self, to:&Uuid) {
        self.edges_to.remove(to);
    }
}

//----
#[derive(Debug)]
pub struct Graph {
    nodes: HashMap<Uuid,GraphNode>,

    // todo: as traits
    is_weighted: bool,
    is_directed: bool,
    is_tracking: bool,  // tracking from-edges
}

//todo: turn many of these methods into a trait
impl Graph {
    pub fn default() -> Graph {
        Graph { nodes: HashMap::new(),
                is_weighted: false,
                is_directed: true,
                is_tracking: false, }
    }

    /// manual accessors
    fn get_node_mut(&mut self, uuid: &Uuid) -> Option<&mut GraphNode> {
        self.nodes.get_mut(uuid)
    }
    fn get_node(&self, uuid: &Uuid) -> Option<&GraphNode> {
        self.nodes.get(uuid)
    }

    pub fn add (&mut self) -> Uuid { //todo: maybe_edges fn arg
        let uuid = Uuid::new_v4();
        let n = GraphNode::new(uuid);
        self.nodes.insert(uuid,n);
        uuid
    }
    pub fn remove(&mut self, node: &Uuid) -> bool { //Option<GraphNode> {
        self.nodes.remove(node).is_some()
    }

    pub fn direct(&mut self, from: &Uuid, to: &Uuid) -> bool {
        let mut r = true;

        if !self.get_node(to).is_some() { return false } // todo: expand on this, and impl for undirect?

        if let Some(f) = self.nodes.get_mut(from) {
            f.direct(to,None);
        }
        else { r = false; }

        if self.is_directed { return r }
        else if r {
            if let Some(t) = self.nodes.get_mut(to) {
                t.direct(from,None);
            }
            else { r = false; }
        }

        return r
    }
    pub fn undirect(&mut self, from: &Uuid, to: &Uuid) -> bool {
        let mut r = true;
        if let Some(f) = self.nodes.get_mut(from) {
            f.undirect(to);
        }
        else { r = false; }

        if self.is_directed { return r }
        else if r {
            if let Some(t) = self.nodes.get_mut(to) {
                t.undirect(from);
            }
            else { r = false; }
        }

        return r
    }

    // search functions
    // todo: consider weights between nodes to direct search, cycle-detection
    pub fn get_path(&self, s: GraphSearch) -> Option<Vec<Uuid>> {
        let mut visited: HashSet<Uuid> = HashSet::new();
        let mut result = vec!();

        match s {
            GraphSearch::Depth(from,to) => {
                let mut stack = vec!();

                stack.push(from);

                while stack.len() > 0 {
                    let cursor = *stack.last().unwrap();
                    visited.insert(cursor);

                    if let Some(ref node) = self.get_node(&cursor) {

                        //get first unvisited node
                        let not_visited = node.edges_to.iter().find(|&(n,_)| !visited.contains(n));

                        if let Some((&n,_)) = not_visited {
                            if !self.is_tracking || self.nodes.contains_key(&n) {
                                stack.push(n); //add node to check
                                result.push(n);

                                if let Some(to_node) = to {
                                    if n == to_node { break; }
                                }
                            }
                        }
                        else { stack.pop(); } //nothing left, pop off and head back a node
                    }
                    else { stack.pop(); } //invalid node?
                }

                if let Some(to_node) = to {
                    if result.contains(&to_node) {
                        return Some(result)
                    }
                }

                return None
            },
            GraphSearch::Breadth(from,to) => { // breadth first search, uses a queue
                let mut queue = VecDeque::new();

                queue.push_back(from);
                visited.insert(from);
                result.push(from);

                while queue.len() > 0 {
                    let cursor = *queue.front().unwrap();
                    if let Some(ref node) = self.get_node(&cursor) {
                        //get unvisted nodes to queue up
                        let not_visited: Vec<Option<(Uuid,Option<f64>)>> = node.edges_to.iter().map(|(&n,&v)| {
                            if !visited.contains(&n) {
                                Some((n,v))
                            }
                            else { None }
                        }).collect();

                        for maybe_node in not_visited {
                            if let Some((n,w)) = maybe_node {
                                if !self.is_tracking || self.nodes.contains_key(&n) { //node exists?
                                    queue.push_back(n);
                                    visited.insert(n);
                                    result.push(n);

                                    if let Some(to_node) = to {
                                        if n == to_node { break; }
                                    }
                                }
                            }
                        }

                        queue.pop_front();
                    }
                    else { queue.pop_front(); }
                }

                if let Some(to_node) = to {
                    if result.contains(&to_node) {
                        return Some(result)
                    }
                }

                return None
            },
            _ => None, // todo: djk algo
        }
    }

    //this is virtually the same as get_path dfs, should abstract dfs somehow to use it for this
    pub fn get_cycle(&self, from: Uuid) -> HashSet<(Uuid,Uuid)> {
        let mut stack = vec!();
        let mut visited: HashSet<Uuid> = HashSet::new();
        let mut r = HashSet::new(); //Vec::new();

        stack.push(from);

        while stack.len() > 0 {
            let cursor = *stack.last().unwrap();
            visited.insert(cursor);

            if let Some(ref node) = self.get_node(&cursor) {

                //does the cursor point to a node on stack
                for (n,_) in node.edges_to.iter() {
                    if stack.contains(&n) {
                        r.insert((*n,cursor));
                    }
                }

                //get first unvisited node
                let not_visited = node.edges_to.iter().find(|&(n,_)| !visited.contains(n));

                if let Some((&n,_)) = not_visited {
                    if !stack.contains(&n) {
                        stack.push(n); //add node to check
                    }
                }
                else { stack.pop(); } //nothing left, pop off and head back a node
            }
            else { stack.pop(); } //invalid node?
        }

        return r
    }

    /// get immediate next node from list of connected nodes for the current node
    pub fn get_next(&self, from: &Uuid) -> Option<Uuid> {
        if let Some(n) = self.nodes.get(from) {
            if let Some(next_id) = n.edges_to.iter().next() {
                return Some(*next_id.0) // grab uuid key
            }
        }

        return None

    }

    fn is_connected() -> bool { false }
    fn is_complete() -> bool { false }

    fn get_path_shortest(&self) -> bool {
        if !self.is_weighted { false } //must be weighted
        else { false } //todo: use bfs
    }
}

// todo: impl as trait instead?
pub enum GraphSearch {
    Depth(Uuid,Option<Uuid>), // used on part of graph for reachability, and all of graph for cycle-detection
    Breadth(Uuid,Option<Uuid>), // used on part of graph for reachability, and (unweighted) for shortest path
    Dijkstra(Uuid,Uuid), // used on part of graph (weighted) for shortest path
}

pub struct GraphBuilder(Graph);

impl GraphBuilder {
    pub fn new() -> GraphBuilder {
        GraphBuilder(Graph::default())
    }

    pub fn directed(mut self, d: bool) -> GraphBuilder {
        self.0.is_directed = d;
        self
    }
    pub fn weighted(mut self, w: bool) -> GraphBuilder {
        self.0.is_weighted = w;
        self
    }
    pub fn track_from_nodes(mut self, t: bool) -> GraphBuilder {
        self.0.is_tracking = t;
        self
    }
    pub fn build(mut self) -> Graph {
        self.0
    }
}

// ----
// tests
// ----
#[cfg(test)]
mod tests {
    extern crate test;

    use ::{Graph,GraphSearch};

    use uuid::Uuid;
    use std::collections::{HashMap};

    #[test]
    fn test_basic_direct() {
        let mut graph = Graph::default();
        let mut nodes = vec!();
        for _ in 0..5 {
            nodes.push(graph.add());
        }

        assert!(graph.direct(&nodes[0],&nodes[1]));

        assert!(graph.direct(&nodes[3],&nodes[0]));
        assert!(graph.direct(&nodes[4],&nodes[3]));

        graph.remove(&nodes[2]);
        assert!(!graph.direct(&nodes[4],&nodes[2]));

        let n6 = graph.add();
        assert!(graph.direct(&n6,&nodes[3]));
        assert!(graph.direct(&nodes[0],&n6));
    }

    #[test]
    fn test_basic_paths() {
        let mut graph = Graph::default();
        let mut nodes = vec!();
        for _ in 0..5 {
            nodes.push(graph.add());
        }

        graph.direct(&nodes[0],&nodes[1]);

        graph.direct(&nodes[3],&nodes[0]);
        graph.direct(&nodes[4],&nodes[3]);

        graph.remove(&nodes[2]);

        let r = graph.get_path(GraphSearch::Depth(nodes[0],Some(nodes[4])));
        assert!(!r.is_some());

        let r = graph.get_path(GraphSearch::Depth(nodes[4],Some(nodes[0])));
        assert!(r.is_some());

        let r = graph.get_path(GraphSearch::Breadth(nodes[4],Some(nodes[0])));
        assert!(r.is_some());
    }

    #[test]
    fn test_basic_cycle() {
        let mut graph = Graph::default();
        let mut nodes = vec!();
        for _ in 0..5 {
            nodes.push(graph.add());
        }

        graph.direct(&nodes[0],&nodes[1]);

        graph.direct(&nodes[3],&nodes[0]);
        graph.direct(&nodes[4],&nodes[3]);

        graph.remove(&nodes[2]);

        let r = graph.get_cycle(nodes[4]);
        assert_eq!(r.len(),0);

        let n6 = graph.add();
        graph.direct(&n6,&nodes[3]);
        graph.direct(&nodes[0],&n6);

        let n7 = graph.add();
        graph.direct(&n7,&nodes[3]);
        graph.direct(&nodes[0],&n7);

        let r = graph.get_cycle(nodes[4]);
        println!("{:?}",r);
        assert_eq!(r.len(),2);
    }
}
<commit_msg>add direct_from<commit_after>/// mush graph backend and abstraction to swap out with custom backend

use uuid::Uuid;
use std::collections::{HashMap,HashSet,VecDeque};

/// unidirectional edge, use two edges for bidirectional/undirected graph
//#[derive(Hash, Eq, PartialEq, Debug)]
#[derive(Debug)]
struct GraphEdge<K> {
    to: Uuid,
    maybe_weight: Option<f64>,
    maybe_custom: Option<K>, // this might
}
impl<K> GraphEdge<K> {
    // this should be private, this should be called by a graph method
    fn new (uuid: Uuid, weight: Option<f64>, custom: Option<K>) -> GraphEdge<K> {
        GraphEdge { to: uuid,
                    maybe_weight:weight,
                    maybe_custom: custom }
    }
    pub fn get_directed (&self) -> &Uuid {
        &self.to
    }

    pub fn get_weight (&self) -> Option<&f64> {
        if let Some(ref w) = self.maybe_weight { Some(w) }
        else { None }
    }
    pub fn get_weight_mut (&mut self) -> Option<&mut f64> {
        if let Some(ref mut w) = self.maybe_weight { Some(w) }
        else { None }
    }

    pub fn get_custom (&self) -> Option<&K> {
        if let Some(ref k) = self.maybe_custom { Some(k) }
        else { None }
    }
    pub fn get_custom_mut (&mut self) -> Option<&mut K> {
        if let Some(ref mut k) = self.maybe_custom { Some(k) }
        else { None }
    }
}

//--

#[derive(Debug)]
struct GraphNode {
    uuid: Uuid,
    edges_to: HashMap<Uuid,Option<f64>>, //to,weight //todo: turn to hashset if using graphedge struct
    edges_from: HashMap<Uuid,Option<f64>>,
}
impl GraphNode {
    fn new (uuid: Uuid) -> GraphNode {
        GraphNode { uuid: uuid,
                    edges_to: HashMap::new(),
                    edges_from: HashMap::new(), }
    }
    /// direct the node towards another node
    // todo: rename me! sounds too similar to unidirectional
    fn direct (&mut self, to:&Uuid, weight: Option<f64>) {
        self.edges_to.insert(*to,weight);
    }
    fn direct_from (&mut self, to:&Uuid, weight: Option<f64>) {
        self.edges_from.insert(*to,weight);
    }
    fn undirect (&mut self, to:&Uuid) {
        self.edges_to.remove(to);
    }
    fn undirect_from (&mut self, to:&Uuid) {
        self.edges_from.remove(to);
    }
}

//----
#[derive(Debug)]
pub struct Graph {
    nodes: HashMap<Uuid,GraphNode>,

    // todo: as traits
    is_weighted: bool,
    is_directed: bool,
    is_tracking: bool,  // tracking from-edges
}

//todo: turn many of these methods into a trait
impl Graph {
    pub fn default() -> Graph {
        Graph { nodes: HashMap::new(),
                is_weighted: false,
                is_directed: true,
                is_tracking: false, }
    }

    /// manual accessors
    fn get_node_mut(&mut self, uuid: &Uuid) -> Option<&mut GraphNode> {
        self.nodes.get_mut(uuid)
    }
    fn get_node(&self, uuid: &Uuid) -> Option<&GraphNode> {
        self.nodes.get(uuid)
    }

    pub fn add (&mut self) -> Uuid { //todo: maybe_edges fn arg
        let uuid = Uuid::new_v4();
        let n = GraphNode::new(uuid);
        self.nodes.insert(uuid,n);
        uuid
    }
    pub fn remove(&mut self, node: &Uuid) -> bool { //Option<GraphNode> {
        self.nodes.remove(node).is_some()
    }

    pub fn direct(&mut self, from: &Uuid, to: &Uuid) -> bool {
        let mut r = false;

        if !self.get_node(to).is_some() { return false } // todo: expand on this, and impl for undirect?

        if let Some(f) = self.nodes.get_mut(from) {
            f.direct(to,None);
            r = true;
        }

        if r && self.is_tracking { let t = self.nodes.get_mut(to).unwrap();
                                   t.direct_from(from,None); }

        if self.is_directed { return r }
        else if r {
            if let Some(t) = self.nodes.get_mut(to) {
                t.direct(from,None);
            }
            else { r = false; }
        }

        r
    }
    pub fn undirect(&mut self, from: &Uuid, to: &Uuid) -> bool {
        let mut r = false;

        if !self.get_node(to).is_some() { return false }

        if let Some(f) = self.nodes.get_mut(from) {
            f.undirect(to);
            r = true;
        }

        if r && self.is_tracking {  let t = self.nodes.get_mut(to).unwrap();
                                    t.undirect_from(from); }

        if self.is_directed { return r }
        else if r {
            if let Some(t) = self.nodes.get_mut(to) {
                t.undirect(from);
            }
            else { r = false; }
        }

        r
    }

    // search functions
    // todo: consider weights between nodes to direct search
    pub fn get_path(&self, s: GraphSearch) -> Option<Vec<Uuid>> {
        let mut visited: HashSet<Uuid> = HashSet::new();
        let mut result = vec!();

        match s {
            GraphSearch::Depth(from,to) => {
                let mut stack = vec!();

                stack.push(from);

                while stack.len() > 0 {
                    let cursor = *stack.last().unwrap();
                    visited.insert(cursor);

                    if let Some(ref node) = self.get_node(&cursor) {

                        //get first unvisited node
                        let not_visited = node.edges_to.iter().find(|&(n,_)| !visited.contains(n));

                        if let Some((&n,_)) = not_visited {
                            if !self.is_tracking || self.nodes.contains_key(&n) {
                                stack.push(n); //add node to check
                                result.push(n);

                                if let Some(to_node) = to {
                                    if n == to_node { break; }
                                }
                            }
                        }
                        else { stack.pop(); } //nothing left, pop off and head back a node
                    }
                    else { stack.pop(); } //invalid node?
                }

                if let Some(to_node) = to {
                    if result.contains(&to_node) {
                        return Some(result)
                    }
                }

                return None
            },
            GraphSearch::Breadth(from,to) => { // breadth first search, uses a queue
                let mut queue = VecDeque::new();

                queue.push_back(from);
                visited.insert(from);
                result.push(from);

                while queue.len() > 0 {
                    let cursor = *queue.front().unwrap();
                    if let Some(ref node) = self.get_node(&cursor) {
                        //get unvisted nodes to queue up
                        let not_visited: Vec<Option<(Uuid,Option<f64>)>> = node.edges_to.iter().map(|(&n,&v)| {
                            if !visited.contains(&n) {
                                Some((n,v))
                            }
                            else { None }
                        }).collect();

                        for maybe_node in not_visited {
                            if let Some((n,w)) = maybe_node {
                                if !self.is_tracking || self.nodes.contains_key(&n) { //node exists?
                                    queue.push_back(n);
                                    visited.insert(n);
                                    result.push(n);

                                    if let Some(to_node) = to {
                                        if n == to_node { break; }
                                    }
                                }
                            }
                        }

                        queue.pop_front();
                    }
                    else { queue.pop_front(); }
                }

                if let Some(to_node) = to {
                    if result.contains(&to_node) {
                        return Some(result)
                    }
                }

                return None
            },
            _ => None, // todo: djk algo
        }
    }

    //this is virtually the same as get_path dfs, should abstract dfs somehow to use it for this
    pub fn get_cycle(&self, from: Uuid) -> HashSet<(Uuid,Uuid)> {
        let mut stack = vec!();
        let mut visited: HashSet<Uuid> = HashSet::new();
        let mut r = HashSet::new(); //Vec::new();

        stack.push(from);

        while stack.len() > 0 {
            let cursor = *stack.last().unwrap();
            visited.insert(cursor);

            if let Some(ref node) = self.get_node(&cursor) {

                //does the cursor point to a node on stack
                for (n,_) in node.edges_to.iter() {
                    if stack.contains(&n) {
                        r.insert((*n,cursor));
                    }
                }

                //get first unvisited node
                let not_visited = node.edges_to.iter().find(|&(n,_)| !visited.contains(n));

                if let Some((&n,_)) = not_visited {
                    if !stack.contains(&n) {
                        if !self.is_tracking || self.nodes.contains_key(&n) {
                            stack.push(n); //add node to check
                        }
                    }
                }
                else { stack.pop(); } //nothing left, pop off and head back a node
            }
            else { stack.pop(); } //invalid node?
        }

        return r
    }

    /// get immediate next node from list of connected nodes for the current node
    pub fn get_next(&self, from: &Uuid) -> Option<Uuid> {
        if let Some(n) = self.nodes.get(from) {
            if let Some((next_id,_)) = n.edges_to.iter().next() {
                if !self.is_tracking || self.nodes.contains_key(&next_id) {
                    return Some(*next_id) // grab uuid key
                }
            }
        }
        None
    }

    fn is_connected() -> bool { false }
    fn is_complete() -> bool { false }

    fn get_path_shortest(&self) -> bool {
        if !self.is_weighted { false } //must be weighted
        else { false } //todo: use bfs
    }
}

// todo: impl as trait instead?
pub enum GraphSearch {
    Depth(Uuid,Option<Uuid>), // used on part of graph for reachability, and all of graph for cycle-detection
    Breadth(Uuid,Option<Uuid>), // used on part of graph for reachability, and (unweighted) for shortest path
    Dijkstra(Uuid,Uuid), // used on part of graph (weighted) for shortest path
}

pub struct GraphBuilder(Graph);

/// tracking specifies that you wish to track the from-node connections
impl GraphBuilder {
    pub fn new() -> GraphBuilder {
        GraphBuilder(Graph::default())
    }

    pub fn directed(mut self, d: bool) -> GraphBuilder {
        self.0.is_directed = d;
        self
    }
    pub fn weighted(mut self, w: bool) -> GraphBuilder {
        self.0.is_weighted = w;
        self
    }
    pub fn tracking(mut self, t: bool) -> GraphBuilder {
        self.0.is_tracking = t;
        self
    }
    pub fn build(mut self) -> Graph {
        self.0
    }
}

// ----
// tests
// ----
#[cfg(test)]
mod tests {
    extern crate test;

    use ::{Graph,GraphSearch};

    use uuid::Uuid;
    use std::collections::{HashMap};

    #[test]
    fn test_basic_direct() {
        let mut graph = Graph::default();
        let mut nodes = vec!();
        for _ in 0..5 {
            nodes.push(graph.add());
        }

        assert!(graph.direct(&nodes[0],&nodes[1]));

        assert!(graph.direct(&nodes[3],&nodes[0]));
        assert!(graph.direct(&nodes[4],&nodes[3]));

        graph.remove(&nodes[2]);
        assert!(!graph.direct(&nodes[4],&nodes[2]));

        let n6 = graph.add();
        assert!(graph.direct(&n6,&nodes[3]));
        assert!(graph.direct(&nodes[0],&n6));
    }

    #[test]
    fn test_basic_paths() {
        let mut graph = Graph::default();
        let mut nodes = vec!();
        for _ in 0..5 {
            nodes.push(graph.add());
        }

        graph.direct(&nodes[0],&nodes[1]);

        graph.direct(&nodes[3],&nodes[0]);
        graph.direct(&nodes[4],&nodes[3]);

        graph.remove(&nodes[2]);

        let r = graph.get_path(GraphSearch::Depth(nodes[0],Some(nodes[4])));
        assert!(!r.is_some());

        let r = graph.get_path(GraphSearch::Depth(nodes[4],Some(nodes[0])));
        assert!(r.is_some());

        let r = graph.get_path(GraphSearch::Breadth(nodes[4],Some(nodes[0])));
        assert!(r.is_some());
    }

    #[test]
    fn test_basic_cycle() {
        let mut graph = Graph::default();
        let mut nodes = vec!();
        for _ in 0..5 {
            nodes.push(graph.add());
        }

        graph.direct(&nodes[0],&nodes[1]);

        graph.direct(&nodes[3],&nodes[0]);
        graph.direct(&nodes[4],&nodes[3]);

        graph.remove(&nodes[2]);

        let r = graph.get_cycle(nodes[4]);
        assert_eq!(r.len(),0);

        let n6 = graph.add();
        graph.direct(&n6,&nodes[3]);
        graph.direct(&nodes[0],&n6);

        let n7 = graph.add();
        graph.direct(&n7,&nodes[3]);
        graph.direct(&nodes[0],&n7);

        let r = graph.get_cycle(nodes[4]);
        println!("{:?}",r);
        assert_eq!(r.len(),2);
    }
}
<|endoftext|>


<commit_before>#![allow(unused_imports, unused_must_use, unused_variables, dead_code)]

extern crate combine;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::str;
use std::collections::HashMap;
use std::marker::PhantomData;
use combine::{spaces, parser, between, many, many1, digit, char, any, string, token, Parser, ParserExt, ParseError};
use combine::primitives::{State, Stream, ParseResult, Consumed};
use combine::combinator::{Between, Token, FnParser, satisfy};

//my own bencode stuff!
//
fn open_file <P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut fd = File::open(path).unwrap();
    let mut buffer:Vec<u8> = Vec::new();
    fd.read_to_end(&mut buffer);
    buffer
}

#[derive(Debug, Eq, PartialEq)]
enum Bencode {
    Int(i64),
    String(String),
    List(Vec<Bencode>),
    Dict(HashMap<String, Bencode>)
}

fn bencode_integer<I>(input: State<I>) -> ParseResult<i64, I> where I: Stream<Item=char> {
    let (open, close) = (char('i'), char('e'));
    let mut int = between(open, close, many1::<String, _>(digit())).map(|x| {
        x.parse::<i64>().unwrap()
    });
    int.parse_state(input)
}

fn bencode_string<I>(input: State<I>) -> ParseResult<String, I> where I: Stream<Item=char> {
    let (len, input_) = try!(bencode_string_length_prefix(input));
    input_.combine(|input__| take(len).parse_state(input__))
}

fn bencode_string_length_prefix<I>(input: State<I>) -> ParseResult<i32, I> where I:Stream<Item=char> {
    let many_digit = many1::<String, _>(digit());
    let mut get_len = (many_digit, char(':')).map(|(length, _)| length.parse::<i32>().unwrap());
    get_len.parse_state(input)
}

fn bencode_list<I>(input: State<I>) -> ParseResult<Vec<Bencode>, I> where I: Stream<Item=char> {
    let (open, close) = (char('l'), char('e'));
    let list_contents = many::<Vec<Bencode>, _>(bencode_any());
    let mut list = between(open, close, list_contents);
    list.parse_state(input)
}

fn bencode_dict<I>(input: State<I>) -> ParseResult<HashMap<String, Bencode>, I> where I: Stream<Item=char> {
    let (open, close) = (char('d'), char('e'));
    let pairs = (parser(bencode_string), bencode_any());
    let mut dict = between(open, close, many(pairs)).map(|entries:Vec<(String, Bencode)>|{
        let mut hash_map = HashMap::new();
        for (k, v) in entries {
            hash_map.insert(k, v);
        }
        hash_map
    });
    dict.parse_state(input)
}

fn bencode_any<I>() -> FnParser<I, fn (State<I>) -> ParseResult<Bencode, I>> where I: Stream<Item=char> {
    fn bencode_any_<I>(input: State<I>) -> ParseResult<Bencode, I> where I: Stream<Item=char> {
        parser(bencode_integer).map(Bencode::Int)
            .or(parser(bencode_string).map(Bencode::String))
            .or(parser(bencode_list).map(Bencode::List))
            .or(parser(bencode_dict).map(Bencode::Dict)).parse_state(input)
    }
    parser(bencode_any_)
}

fn take <I> (num: i32) -> SizedBuffer<I> where I: Stream<Item=char> {
    SizedBuffer(num, PhantomData)
}

#[derive(Clone)]
pub struct SizedBuffer <I>(i32, PhantomData<I>);
impl <I> Parser for SizedBuffer<I> where I: Stream<Item=char> {
    type Input = I;
    type Output = String;
    fn parse_lazy(&mut self, mut input: State<I>) -> ParseResult<String, I> {
        let start = input.position;
        let mut vec_buf:Vec<char> = Vec::new();
        for _ in 0..self.0 {
            match input.uncons() {
                Ok((other, rest)) => {
                    vec_buf.push(other);
                    input = rest.into_inner();
                }
                Err(error) => {
                    return error.combine(|mut error| {
                        error.position = start;
                        Err(Consumed::Consumed(error))
                    })
                }
            };
        }
        Ok((vec_buf.into_iter().collect(), Consumed::Consumed(input)))
    }
}

fn main () {
    let file_contents = open_file("t-test.torrent");
    match str::from_utf8(&file_contents) {
        Ok(v) => {
            let (result, _) = many::<Vec<Bencode>, _>(bencode_any()).parse(v).unwrap();
            println!("res: {:?}", result);
            println!("file: {}", v)
        },
        Err(e) => panic!("Not a UTF-8 String: {}", e)
    };
}

#[test]
fn test_integer() {
    let result = parser(bencode_integer).parse("i57e");
    assert_eq!(result, Ok((57,"")));
}

#[test]
fn test_string() {
    let result = parser(bencode_string).parse("5:abcde");
    assert_eq!(result, Ok(("abcde".to_string(), "")));;
}

#[test]
fn test_list() {
    let homogenous_int_list = parser(bencode_list).parse("li57ei32ee");
    assert_eq!(homogenous_int_list, Ok((vec![Bencode::Int(57), Bencode::Int(32)], "")));

    let homogenous_str_list = parser(bencode_list).parse("l3:abc5:defghe");
    assert_eq!(homogenous_str_list, Ok((vec![Bencode::String("abc".to_string()), Bencode::String("defgh".to_string())], "")));

    let hetero_list = parser(bencode_list).parse("li32e3:abce");
    assert_eq!(hetero_list, Ok((vec![Bencode::Int(32), Bencode::String("abc".to_string())], "")));
}

#[test]
fn test_dict() {
    let (dict_result, _) = parser(bencode_dict).parse("d3:abci4e4:andyli5eee").unwrap();
    assert_eq!(*dict_result.get("abc").unwrap(), Bencode::Int(4));
    assert_eq!(*dict_result.get("andy").unwrap(), Bencode::List(vec![Bencode::Int(5)]));
    assert_eq!(dict_result.len(), 2);
}

<commit_msg>adding deserialize, deserialize_file to bencode<commit_after>//#![allow(unused_imports, unused_must_use, unused_variables, dead_code)]

extern crate combine;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::collections::HashMap;
use std::marker::PhantomData;
use std::env;
use combine::{parser, between, many, many1, digit, char, Parser, ParserExt};
use combine::primitives::{State, Stream, ParseResult, Consumed};
use combine::combinator::FnParser;

//my own bencode stuff!
#[derive(Debug, Eq, PartialEq)]
enum Bencode {
    Int(i64),
    String(String),
    List(Vec<Bencode>),
    Dict(HashMap<String, Bencode>)
}

fn bencode_integer<I>(input: State<I>) -> ParseResult<i64, I> where I: Stream<Item=char> {
    let (open, close) = (char('i'), char('e'));
    let mut int = between(open, close, many1::<String, _>(digit())).map(|x| {
        x.parse::<i64>().unwrap()
    });
    int.parse_state(input)
}

fn bencode_string<I>(input: State<I>) -> ParseResult<String, I> where I: Stream<Item=char> {
    let (len, input_) = try!(bencode_string_length_prefix(input));
    input_.combine(|input__| take(len).parse_state(input__))
}

fn bencode_string_length_prefix<I>(input: State<I>) -> ParseResult<i32, I> where I:Stream<Item=char> {
    let many_digit = many1::<String, _>(digit());
    let mut get_len = (many_digit, char(':')).map(|(length, _)| length.parse::<i32>().unwrap());
    get_len.parse_state(input)
}

fn bencode_list<I>(input: State<I>) -> ParseResult<Vec<Bencode>, I> where I: Stream<Item=char> {
    let (open, close) = (char('l'), char('e'));
    let list_contents = many::<Vec<Bencode>, _>(bencode_any());
    let mut list = between(open, close, list_contents);
    list.parse_state(input)
}

fn bencode_dict<I>(input: State<I>) -> ParseResult<HashMap<String, Bencode>, I> where I: Stream<Item=char> {
    let (open, close) = (char('d'), char('e'));
    let pairs = (parser(bencode_string), bencode_any());
    let mut dict = between(open, close, many(pairs)).map(|entries:Vec<(String, Bencode)>|{
        let mut hash_map = HashMap::new();
        for (k, v) in entries {
            hash_map.insert(k, v);
        }
        hash_map
    });
    dict.parse_state(input)
}

fn bencode_any<I>() -> FnParser<I, fn (State<I>) -> ParseResult<Bencode, I>> where I: Stream<Item=char> {
    fn bencode_any_<I>(input: State<I>) -> ParseResult<Bencode, I> where I: Stream<Item=char> {
        parser(bencode_integer).map(Bencode::Int)
            .or(parser(bencode_string).map(Bencode::String))
            .or(parser(bencode_list).map(Bencode::List))
            .or(parser(bencode_dict).map(Bencode::Dict)).parse_state(input)
    }
    parser(bencode_any_)
}

fn take <I> (num: i32) -> SizedBuffer<I> where I: Stream<Item=char> {
    SizedBuffer(num, PhantomData)
}

#[derive(Clone)]
pub struct SizedBuffer <I>(i32, PhantomData<I>);
impl <I> Parser for SizedBuffer<I> where I: Stream<Item=char> {
    type Input = I;
    type Output = String;
    fn parse_lazy(&mut self, mut input: State<I>) -> ParseResult<String, I> {
        let start = input.position;
        let mut vec_buf:Vec<char> = Vec::new();
        for _ in 0..self.0 {
            match input.uncons() {
                Ok((other, rest)) => {
                    vec_buf.push(other);
                    input = rest.into_inner();
                }
                Err(error) => {
                    return error.combine(|mut error| {
                        error.position = start;
                        Err(Consumed::Consumed(error))
                    })
                }
            };
        }
        Ok((vec_buf.into_iter().collect(), Consumed::Consumed(input)))
    }
}

fn open_file <P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut fd = File::open(path).unwrap();
    let mut buffer:Vec<u8> = Vec::new();
    let _ = fd.read_to_end(&mut buffer);
    buffer
}

//there's probably an argument that this should be a Result as opposed to an Option, as you
//could potentially be losing error pertinent information in an Option. not going to change it over
//right now
fn deserialize (byte_vector: Vec<u8>) -> Option<Vec<Bencode>> {
    //hack to coerce ascii byte values to rust array sliceof char (UTF-8). necessary to avoid substantial
    //writing of existing combine parser builtins
    let as_string: Vec<char> = byte_vector.iter().map(|x| *x as char).collect();
    match many::<Vec<Bencode>, _>(bencode_any()).parse(&as_string[..]) {
        Ok((result, _)) => Some(result),
        Err(_) => None
    }
}

fn deserialize_file<P: AsRef<Path>>(path: P) -> Option<Vec<Bencode>> {
    deserialize(open_file(path))
}

fn main () {
    let path = env::args().nth(1).unwrap();
    let cont = deserialize_file(path).unwrap();
    println!("{:?}", cont);
}

#[test]
fn test_integer() {
    let result = parser(bencode_integer).parse("i57e");
    assert_eq!(result, Ok((57,"")));
}

#[test]
fn test_string() {
    let result = parser(bencode_string).parse("5:abcde");
    assert_eq!(result, Ok(("abcde".to_string(), "")));;
}

#[test]
fn test_list() {
    let homogenous_int_list = parser(bencode_list).parse("li57ei32ee");
    assert_eq!(homogenous_int_list, Ok((vec![Bencode::Int(57), Bencode::Int(32)], "")));

    let homogenous_str_list = parser(bencode_list).parse("l3:abc5:defghe");
    assert_eq!(homogenous_str_list, Ok((vec![Bencode::String("abc".to_string()), Bencode::String("defgh".to_string())], "")));

    let hetero_list = parser(bencode_list).parse("li32e3:abce");
    assert_eq!(hetero_list, Ok((vec![Bencode::Int(32), Bencode::String("abc".to_string())], "")));
}

#[test]
fn test_dict() {
    let (dict_result, _) = parser(bencode_dict).parse("d3:abci4e4:andyli5eee").unwrap();
    assert_eq!(*dict_result.get("abc").unwrap(), Bencode::Int(4));
    assert_eq!(*dict_result.get("andy").unwrap(), Bencode::List(vec![Bencode::Int(5)]));
    assert_eq!(dict_result.len(), 2);
}

#[test]
fn test_many() {
    let input_string = "i1ei2ei3ei10el3:abc4:defged1:ai10ee";
    let (result, _) = many::<Vec<Bencode>, _>(bencode_any()).parse(input_string).unwrap();
    let mut my_map = HashMap::new();
    my_map.insert("a".to_string(), Bencode::Int(10));
    assert_eq!(result, vec![
        Bencode::Int(1),
        Bencode::Int(2),
        Bencode::Int(3),
        Bencode::Int(10),
        Bencode::List(vec![
            Bencode::String("abc".to_string()),
            Bencode::String("defg".to_string())
            ]),
        Bencode::Dict(my_map)
    ]);
}
<|endoftext|>


<commit_before>use std::io::Cursor;
use std::io::prelude::*;
use std::net::TcpStream;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

const RECV_BUF_SIZE: usize = 8192;
const GQTP_HEADER_SIZE: usize = 24;

#[derive(Debug)]
pub enum GQTPError {
    InvalidProtocol,
    InvalidBodySize,
    StatusError(u16),
}

/// Request [GQTP protocol](http://groonga.org/docs/spec/gqtp.html) over TcpStream
pub struct GQTPRequest<'a> {
    addr: &'a str,
}

impl<'a> Default for GQTPRequest<'a> {
    fn default() -> GQTPRequest<'a> {
        GQTPRequest { addr: "127.0.0.1:10043" }
    }
}

impl<'a> GQTPRequest<'a> {
    /// Create a GQTP client.
    pub fn new() -> GQTPRequest<'a> {
        GQTPRequest::default()
    }

    /// Set host address for GQTP server.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate ruroonga_client as groonga;
    ///
    /// groonga::GQTPRequest::new().with_addr("127.0.0.1:20043");
    /// ```
    pub fn with_addr(mut self, addr: &'a str) -> GQTPRequest<'a> {
        self.addr = addr;
        self
    }

    /// Send request and Receive response.
    pub fn call<C>(&self, command: C) -> Result<String, GQTPError>
        where C: AsRef<str>
    {
        // send
        let mut stream = TcpStream::connect(self.addr).unwrap();
        let mut send_buf = vec![];
        send_buf.write_u8(0xc7).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_i16::<BigEndian>(0).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_u8(0x02).unwrap();   // flags
        send_buf.write_u16::<BigEndian>(0).unwrap();
        send_buf.write_u32::<BigEndian>(command.as_ref().len() as u32).unwrap();
        send_buf.write_u32::<BigEndian>(0).unwrap();
        send_buf.write_u64::<BigEndian>(0).unwrap();
        send_buf.extend_from_slice(command.as_ref().as_bytes());
        let _ = stream.write_all(send_buf.as_slice());

        // receive and check protocol header value
        let mut read_buf = vec![0; RECV_BUF_SIZE];
        let _ = stream.read(&mut read_buf);
        let mut buf = Cursor::new(read_buf);

        let protocol = buf.read_u8().unwrap();
        let query_type = buf.read_u8().unwrap();
        if protocol != 0xc7 || query_type > 5 {
            return Err(GQTPError::InvalidProtocol);
        }
        let _ = buf.read_i16::<BigEndian>().unwrap();
        let _ = buf.read_u8().unwrap();

        let flags = buf.read_u8().unwrap();
        if !((flags & 0x01) == 0x01 || (flags & 0x02) == 0x02) {
            return Err(GQTPError::InvalidProtocol);
        }

        let status = buf.read_u16::<BigEndian>().unwrap();
        if status != 0 && status != 1 {
            return Err(GQTPError::StatusError(status));
        }
        let size = buf.read_i32::<BigEndian>().unwrap();
        let _ = buf.read_i32::<BigEndian>().unwrap();    // opaque
        let _ = buf.read_i64::<BigEndian>().unwrap();    // cas

        // read body
        let mut msg_buf_len = if (size as usize + GQTP_HEADER_SIZE) > RECV_BUF_SIZE {
            RECV_BUF_SIZE - GQTP_HEADER_SIZE
        } else {
            size as usize
        };
        let mut msg = vec![0; msg_buf_len];
        let _ = buf.read(&mut msg).unwrap();
        if (size as usize + GQTP_HEADER_SIZE) > RECV_BUF_SIZE {
            loop {
                let mut read_buf = vec![0; RECV_BUF_SIZE];
                let rsize = stream.read(&mut read_buf).unwrap();
                msg.extend_from_slice(read_buf.as_ref());
                msg_buf_len += rsize;
                println!("msglen={}", msg_buf_len);
                if msg_buf_len >= size as usize {
                    break;
                }
            }
        }

        Ok(String::from_utf8(msg).unwrap())
    }
}

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

    #[test]
    fn smoke_gqtp() {
        let req = GQTPRequest::new();
        assert_eq!("127.0.0.1:10043", req.addr)
    }

    #[test]
    fn smoke_gqtp_with_addr() {
        let req = GQTPRequest::new().with_addr("127.0.0.1:20043");
        assert_eq!("127.0.0.1:20043", req.addr)
    }
}
<commit_msg>remove print line<commit_after>use std::io::Cursor;
use std::io::prelude::*;
use std::net::TcpStream;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

const RECV_BUF_SIZE: usize = 8192;
const GQTP_HEADER_SIZE: usize = 24;

#[derive(Debug)]
pub enum GQTPError {
    InvalidProtocol,
    InvalidBodySize,
    StatusError(u16),
}

/// Request [GQTP protocol](http://groonga.org/docs/spec/gqtp.html) over TcpStream
pub struct GQTPRequest<'a> {
    addr: &'a str,
}

impl<'a> Default for GQTPRequest<'a> {
    fn default() -> GQTPRequest<'a> {
        GQTPRequest { addr: "127.0.0.1:10043" }
    }
}

impl<'a> GQTPRequest<'a> {
    /// Create a GQTP client.
    pub fn new() -> GQTPRequest<'a> {
        GQTPRequest::default()
    }

    /// Set host address for GQTP server.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate ruroonga_client as groonga;
    ///
    /// groonga::GQTPRequest::new().with_addr("127.0.0.1:20043");
    /// ```
    pub fn with_addr(mut self, addr: &'a str) -> GQTPRequest<'a> {
        self.addr = addr;
        self
    }

    /// Send request and Receive response.
    pub fn call<C>(&self, command: C) -> Result<String, GQTPError>
        where C: AsRef<str>
    {
        // send
        let mut stream = TcpStream::connect(self.addr).unwrap();
        let mut send_buf = vec![];
        send_buf.write_u8(0xc7).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_i16::<BigEndian>(0).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_u8(0x02).unwrap();   // flags
        send_buf.write_u16::<BigEndian>(0).unwrap();
        send_buf.write_u32::<BigEndian>(command.as_ref().len() as u32).unwrap();
        send_buf.write_u32::<BigEndian>(0).unwrap();
        send_buf.write_u64::<BigEndian>(0).unwrap();
        send_buf.extend_from_slice(command.as_ref().as_bytes());
        let _ = stream.write_all(send_buf.as_slice());

        // receive and check protocol header value
        let mut read_buf = vec![0; RECV_BUF_SIZE];
        let _ = stream.read(&mut read_buf);
        let mut buf = Cursor::new(read_buf);

        let protocol = buf.read_u8().unwrap();
        let query_type = buf.read_u8().unwrap();
        if protocol != 0xc7 || query_type > 5 {
            return Err(GQTPError::InvalidProtocol);
        }
        let _ = buf.read_i16::<BigEndian>().unwrap();
        let _ = buf.read_u8().unwrap();

        let flags = buf.read_u8().unwrap();
        if !((flags & 0x01) == 0x01 || (flags & 0x02) == 0x02) {
            return Err(GQTPError::InvalidProtocol);
        }

        let status = buf.read_u16::<BigEndian>().unwrap();
        if status != 0 && status != 1 {
            return Err(GQTPError::StatusError(status));
        }
        let size = buf.read_i32::<BigEndian>().unwrap();
        let _ = buf.read_i32::<BigEndian>().unwrap();    // opaque
        let _ = buf.read_i64::<BigEndian>().unwrap();    // cas

        // read body
        let mut msg_buf_len = if (size as usize + GQTP_HEADER_SIZE) > RECV_BUF_SIZE {
            RECV_BUF_SIZE - GQTP_HEADER_SIZE
        } else {
            size as usize
        };
        let mut msg = vec![0; msg_buf_len];
        let _ = buf.read(&mut msg).unwrap();
        if (size as usize + GQTP_HEADER_SIZE) > RECV_BUF_SIZE {
            loop {
                let mut read_buf = vec![0; RECV_BUF_SIZE];
                let rsize = stream.read(&mut read_buf).unwrap();
                msg.extend_from_slice(read_buf.as_ref());
                msg_buf_len += rsize;
                if msg_buf_len >= size as usize {
                    break;
                }
            }
        }

        Ok(String::from_utf8(msg).unwrap())
    }
}

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

    #[test]
    fn smoke_gqtp() {
        let req = GQTPRequest::new();
        assert_eq!("127.0.0.1:10043", req.addr)
    }

    #[test]
    fn smoke_gqtp_with_addr() {
        let req = GQTPRequest::new().with_addr("127.0.0.1:20043");
        assert_eq!("127.0.0.1:20043", req.addr)
    }
}
<|endoftext|>


<commit_before>//! # Completion
//!

#![allow(unused_variables)]

use parser::nodes::*;
use tokenizer::Token;
use util::longest_common_prefix;

/// Represents a single option returned by `complete`.
///
/// An option may be `complete`, which means that it represents
/// a syntactically complete parameter value which can be used
/// as-is, whereas incomplete options are not valid values.
pub struct CompletionOption {
    /// String for this option.
    pub option_string: String,
    /// True if this option is complete and a valid value.
    pub complete: bool,
}

impl CompletionOption {
    /// CompletionOption constructor
    pub fn new(option_string: String, complete: bool) -> CompletionOption {
        CompletionOption {
            option_string: option_string,
            complete: complete,
        }
    }
}

/// Represents the result of completing a node.
///
/// This may be hinted by a pre-existing token.
///
/// If a completion is exhaustive, then only the `CompletionOption`s
/// provided are valid.
///
/// The lifetime parameter `'t` refers to the lifetime of the
/// body of text which generated the `Token`.
pub struct Completion<'t> {
    /// Value placeholder for help.
    pub help_symbol: String,
    /// Main help text.
    pub help_text: String,
    /// Token used to hint the completion, if provided.
    pub token: Option<&'t Token<'t>>,
    /// Was this completion exhaustive? If yes, then only
    /// the given completion options are valid.
    pub exhaustive: bool,
    /// The actual completion options.
    pub options: Vec<CompletionOption>,
}

impl<'t> Completion<'t> {
    /// Construct a new Completion.
    pub fn new(help_symbol: String,
               help_text: String,
               token: Option<&'t Token<'t>>,
               exhaustive: bool,
               complete_options: Vec<&str>,
               other_options: Vec<&str>)
               -> Completion<'t> {
        // Preserve all of the options while still &str so that
        // we can use this with longest_common_prefix later.
        let mut all_options = complete_options.clone();
        all_options.extend(other_options.iter().cloned());

        // Convert to String...
        let mut complete_options = complete_options.into_iter()
                                                   .map(|o| o.to_string())
                                                   .collect::<Vec<_>>();
        let mut other_options = other_options.into_iter()
                                             .map(|o| o.to_string())
                                             .collect::<Vec<_>>();
        // Apply token restrictions
        if let Some(t) = token {
            // Filter options using token.
            let token_text = t.text.to_string();
            complete_options.retain(|o| o.starts_with(t.text));
            other_options.retain(|o| o.starts_with(t.text));
            // If not exhaustive, then add the current token as
            // an incomplete option.
            if !exhaustive && !complete_options.contains(&token_text) &&
               !other_options.contains(&token_text) {
                other_options.push(token_text);
            }
        }
        // Add longest common prefix as an incomplete options, but
        // filter it against the existing options and the token.
        let lcp = longest_common_prefix(all_options).to_string();
        if !complete_options.contains(&lcp) && !other_options.contains(&lcp) {
            match token {
                Some(t) => {
                    if lcp != t.text {
                        other_options.push(lcp)
                    }
                }
                None => other_options.push(lcp),
            }
        }
        // Convert options to CompletionOption.
        let mut options = complete_options.into_iter()
                                          .map(|o| CompletionOption::new(o, true))
                                          .collect::<Vec<_>>();
        options.extend(other_options.into_iter().map(|o| CompletionOption::new(o, false)));
        Completion {
            help_symbol: help_symbol,
            help_text: help_text,
            token: token,
            exhaustive: exhaustive,
            options: options,
        }
    }
}

/// Trait for nodes that support completion.
pub trait Complete<'t> {
    /// Given a node and an optional token, provide the completion options.
    fn complete(&self, token: Option<&'t Token<'t>>) -> Completion<'t>;
}

impl<'t> Complete<'t> for Node {
    fn complete(&self, token: Option<&'t Token<'t>>) -> Completion<'t> {
        Completion::new(self.help_symbol().clone(),
                        self.help_text().clone(),
                        token,
                        true,
                        vec![],
                        vec![])
    }
}

impl<'t> Complete<'t> for CommandNode {
    fn complete(&self, token: Option<&'t Token<'t>>) -> Completion<'t> {
        Completion::new(self.help_symbol().clone(),
                        self.help_text().clone(),
                        token,
                        true,
                        vec![self.name()],
                        vec![])
    }
}

impl<'t> Complete<'t> for ParameterNameNode {
    fn complete(&self, token: Option<&'t Token<'t>>) -> Completion<'t> {
        Completion::new(self.help_symbol().clone(),
                        self.help_text().clone(),
                        token,
                        true,
                        vec![self.name()],
                        vec![])
    }
}
<commit_msg>Completion: Remove allowing unused variables.<commit_after>//! # Completion
//!

use parser::nodes::*;
use tokenizer::Token;
use util::longest_common_prefix;

/// Represents a single option returned by `complete`.
///
/// An option may be `complete`, which means that it represents
/// a syntactically complete parameter value which can be used
/// as-is, whereas incomplete options are not valid values.
pub struct CompletionOption {
    /// String for this option.
    pub option_string: String,
    /// True if this option is complete and a valid value.
    pub complete: bool,
}

impl CompletionOption {
    /// CompletionOption constructor
    pub fn new(option_string: String, complete: bool) -> CompletionOption {
        CompletionOption {
            option_string: option_string,
            complete: complete,
        }
    }
}

/// Represents the result of completing a node.
///
/// This may be hinted by a pre-existing token.
///
/// If a completion is exhaustive, then only the `CompletionOption`s
/// provided are valid.
///
/// The lifetime parameter `'t` refers to the lifetime of the
/// body of text which generated the `Token`.
pub struct Completion<'t> {
    /// Value placeholder for help.
    pub help_symbol: String,
    /// Main help text.
    pub help_text: String,
    /// Token used to hint the completion, if provided.
    pub token: Option<&'t Token<'t>>,
    /// Was this completion exhaustive? If yes, then only
    /// the given completion options are valid.
    pub exhaustive: bool,
    /// The actual completion options.
    pub options: Vec<CompletionOption>,
}

impl<'t> Completion<'t> {
    /// Construct a new Completion.
    pub fn new(help_symbol: String,
               help_text: String,
               token: Option<&'t Token<'t>>,
               exhaustive: bool,
               complete_options: Vec<&str>,
               other_options: Vec<&str>)
               -> Completion<'t> {
        // Preserve all of the options while still &str so that
        // we can use this with longest_common_prefix later.
        let mut all_options = complete_options.clone();
        all_options.extend(other_options.iter().cloned());

        // Convert to String...
        let mut complete_options = complete_options.into_iter()
                                                   .map(|o| o.to_string())
                                                   .collect::<Vec<_>>();
        let mut other_options = other_options.into_iter()
                                             .map(|o| o.to_string())
                                             .collect::<Vec<_>>();
        // Apply token restrictions
        if let Some(t) = token {
            // Filter options using token.
            let token_text = t.text.to_string();
            complete_options.retain(|o| o.starts_with(t.text));
            other_options.retain(|o| o.starts_with(t.text));
            // If not exhaustive, then add the current token as
            // an incomplete option.
            if !exhaustive && !complete_options.contains(&token_text) &&
               !other_options.contains(&token_text) {
                other_options.push(token_text);
            }
        }
        // Add longest common prefix as an incomplete options, but
        // filter it against the existing options and the token.
        let lcp = longest_common_prefix(all_options).to_string();
        if !complete_options.contains(&lcp) && !other_options.contains(&lcp) {
            match token {
                Some(t) => {
                    if lcp != t.text {
                        other_options.push(lcp)
                    }
                }
                None => other_options.push(lcp),
            }
        }
        // Convert options to CompletionOption.
        let mut options = complete_options.into_iter()
                                          .map(|o| CompletionOption::new(o, true))
                                          .collect::<Vec<_>>();
        options.extend(other_options.into_iter().map(|o| CompletionOption::new(o, false)));
        Completion {
            help_symbol: help_symbol,
            help_text: help_text,
            token: token,
            exhaustive: exhaustive,
            options: options,
        }
    }
}

/// Trait for nodes that support completion.
pub trait Complete<'t> {
    /// Given a node and an optional token, provide the completion options.
    fn complete(&self, token: Option<&'t Token<'t>>) -> Completion<'t>;
}

impl<'t> Complete<'t> for Node {
    fn complete(&self, token: Option<&'t Token<'t>>) -> Completion<'t> {
        Completion::new(self.help_symbol().clone(),
                        self.help_text().clone(),
                        token,
                        true,
                        vec![],
                        vec![])
    }
}

impl<'t> Complete<'t> for CommandNode {
    fn complete(&self, token: Option<&'t Token<'t>>) -> Completion<'t> {
        Completion::new(self.help_symbol().clone(),
                        self.help_text().clone(),
                        token,
                        true,
                        vec![self.name()],
                        vec![])
    }
}

impl<'t> Complete<'t> for ParameterNameNode {
    fn complete(&self, token: Option<&'t Token<'t>>) -> Completion<'t> {
        Completion::new(self.help_symbol().clone(),
                        self.help_text().clone(),
                        token,
                        true,
                        vec![self.name()],
                        vec![])
    }
}
<|endoftext|>