<commit_before>// Copyright 2017 Flier Lu
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt::{self, Display};
use std::marker::PhantomData;

use core::*;

pub struct AnyOf<T, M>(M, PhantomData<T>);

pub fn any_of<T, M>(matchers: M) -> AnyOf<T, M> {
    AnyOf(matchers, PhantomData)
}

#[macro_export]
macro_rules! any_of {
    ($( $arg:expr ),*) => ($crate::matchers::any_of::any_of(($( $arg ),*)))
}

impl<T, M0, M1> Display for AnyOf<T, (M0, M1)>
where
    M0: Display,
    M1: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (ref m0, ref m1) = self.0;

        write!(f, "any of ({}, {})", m0, m1)
    }
}

impl<T, M0, M1> Matcher<T> for AnyOf<T, (M0, M1)>
where
    T: Clone,
    M0: Matcher<T>,
    M1: Matcher<T>,
{
    fn matches(&self, actual: T) -> MatchResult {
        let (ref m0, ref m1) = self.0;

        m0.matches(actual.clone())
            .or_else(|_| m1.matches(actual.clone()))
    }
}

impl<T, M0, M1, M2> Display for AnyOf<T, (M0, M1, M2)>
where
    M0: Display,
    M1: Display,
    M2: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (ref m0, ref m1, ref m2) = self.0;

        write!(f, "any of ({}, {}, {})", m0, m1, m2)
    }
}

impl<T, M0, M1, M2> Matcher<T> for AnyOf<T, (M0, M1, M2)>
where
    T: Clone,
    M0: Matcher<T>,
    M1: Matcher<T>,
    M2: Matcher<T>,
{
    fn matches(&self, actual: T) -> MatchResult {
        let (ref m0, ref m1, ref m2) = self.0;

        m0.matches(actual.clone())
            .or_else(|_| m1.matches(actual.clone()))
            .or_else(|_| m2.matches(actual.clone()))
    }
}

impl<T, M0, M1, M2, M3> Display for AnyOf<T, (M0, M1, M2, M3)>
where
    M0: Display,
    M1: Display,
    M2: Display,
    M3: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (ref m0, ref m1, ref m2, ref m3) = self.0;

        write!(f, "any of ({}, {}, {}, {})", m0, m1, m2, m3)
    }
}

impl<T, M0, M1, M2, M3> Matcher<T> for AnyOf<T, (M0, M1, M2, M3)>
where
    T: Clone,
    M0: Matcher<T>,
    M1: Matcher<T>,
    M2: Matcher<T>,
    M3: Matcher<T>,
{
    fn matches(&self, actual: T) -> MatchResult {
        let (ref m0, ref m1, ref m2, ref m3) = self.0;

        m0.matches(actual.clone())
            .or_else(|_| m1.matches(actual.clone()))
            .or_else(|_| m2.matches(actual.clone()))
            .or_else(|_| m3.matches(actual.clone()))
    }
}

impl<T, M0, M1, M2, M3, M4> Display for AnyOf<T, (M0, M1, M2, M3, M4)>
where
    M0: Display,
    M1: Display,
    M2: Display,
    M3: Display,
    M4: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (ref m0, ref m1, ref m2, ref m3, ref m4) = self.0;

        write!(f, "any of ({}, {}, {}, {}, {})", m0, m1, m2, m3, m4)
    }
}

impl<T, M0, M1, M2, M3, M4> Matcher<T> for AnyOf<T, (M0, M1, M2, M3, M4)>
where
    T: Clone,
    M0: Matcher<T>,
    M1: Matcher<T>,
    M2: Matcher<T>,
    M3: Matcher<T>,
    M4: Matcher<T>,
{
    fn matches(&self, actual: T) -> MatchResult {
        let (ref m0, ref m1, ref m2, ref m3, ref m4) = self.0;

        m0.matches(actual.clone())
            .or_else(|_| m1.matches(actual.clone()))
            .or_else(|_| m2.matches(actual.clone()))
            .or_else(|_| m3.matches(actual.clone()))
            .or_else(|_| m4.matches(actual.clone()))
    }
}

impl<T, M0, M1, M2, M3, M4, M5> Display for AnyOf<T, (M0, M1, M2, M3, M4, M5)>
where
    M0: Display,
    M1: Display,
    M2: Display,
    M3: Display,
    M4: Display,
    M5: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (ref m0, ref m1, ref m2, ref m3, ref m4, ref m5) = self.0;

        write!(f, "any of ({}, {}, {}, {}, {}, {})", m0, m1, m2, m3, m4, m5)
    }
}

impl<T, M0, M1, M2, M3, M4, M5> Matcher<T> for AnyOf<T, (M0, M1, M2, M3, M4, M5)>
where
    T: Clone,
    M0: Matcher<T>,
    M1: Matcher<T>,
    M2: Matcher<T>,
    M3: Matcher<T>,
    M4: Matcher<T>,
    M5: Matcher<T>,
{
    fn matches(&self, actual: T) -> MatchResult {
        let (ref m0, ref m1, ref m2, ref m3, ref m4, ref m5) = self.0;

        m0.matches(actual.clone())
            .or_else(|_| m1.matches(actual.clone()))
            .or_else(|_| m2.matches(actual.clone()))
            .or_else(|_| m3.matches(actual.clone()))
            .or_else(|_| m4.matches(actual.clone()))
            .or_else(|_| m5.matches(actual.clone()))
    }
}
<commit_msg>run `cargo fmt`<commit_after>// Copyright 2017 Flier Lu
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt::{self, Display};
use std::marker::PhantomData;

use core::*;

pub struct AnyOf<T, M>(M, PhantomData<T>);

pub fn any_of<T, M>(matchers: M) -> AnyOf<T, M> {
    AnyOf(matchers, PhantomData)
}

#[macro_export]
macro_rules! any_of {
    ($( $arg:expr ),*) => ($crate::matchers::any_of::any_of(($( $arg ),*)))
}

impl<T, M0, M1> Display for AnyOf<T, (M0, M1)>
where
    M0: Display,
    M1: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (ref m0, ref m1) = self.0;

        write!(f, "any of ({}, {})", m0, m1)
    }
}

impl<T, M0, M1> Matcher<T> for AnyOf<T, (M0, M1)>
where
    T: Clone,
    M0: Matcher<T>,
    M1: Matcher<T>,
{
    fn matches(&self, actual: T) -> MatchResult {
        let (ref m0, ref m1) = self.0;

        m0.matches(actual.clone()).or_else(
            |_| m1.matches(actual.clone()),
        )
    }
}

impl<T, M0, M1, M2> Display for AnyOf<T, (M0, M1, M2)>
where
    M0: Display,
    M1: Display,
    M2: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (ref m0, ref m1, ref m2) = self.0;

        write!(f, "any of ({}, {}, {})", m0, m1, m2)
    }
}

impl<T, M0, M1, M2> Matcher<T> for AnyOf<T, (M0, M1, M2)>
where
    T: Clone,
    M0: Matcher<T>,
    M1: Matcher<T>,
    M2: Matcher<T>,
{
    fn matches(&self, actual: T) -> MatchResult {
        let (ref m0, ref m1, ref m2) = self.0;

        m0.matches(actual.clone())
            .or_else(|_| m1.matches(actual.clone()))
            .or_else(|_| m2.matches(actual.clone()))
    }
}

impl<T, M0, M1, M2, M3> Display for AnyOf<T, (M0, M1, M2, M3)>
where
    M0: Display,
    M1: Display,
    M2: Display,
    M3: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (ref m0, ref m1, ref m2, ref m3) = self.0;

        write!(f, "any of ({}, {}, {}, {})", m0, m1, m2, m3)
    }
}

impl<T, M0, M1, M2, M3> Matcher<T> for AnyOf<T, (M0, M1, M2, M3)>
where
    T: Clone,
    M0: Matcher<T>,
    M1: Matcher<T>,
    M2: Matcher<T>,
    M3: Matcher<T>,
{
    fn matches(&self, actual: T) -> MatchResult {
        let (ref m0, ref m1, ref m2, ref m3) = self.0;

        m0.matches(actual.clone())
            .or_else(|_| m1.matches(actual.clone()))
            .or_else(|_| m2.matches(actual.clone()))
            .or_else(|_| m3.matches(actual.clone()))
    }
}

impl<T, M0, M1, M2, M3, M4> Display for AnyOf<T, (M0, M1, M2, M3, M4)>
where
    M0: Display,
    M1: Display,
    M2: Display,
    M3: Display,
    M4: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (ref m0, ref m1, ref m2, ref m3, ref m4) = self.0;

        write!(f, "any of ({}, {}, {}, {}, {})", m0, m1, m2, m3, m4)
    }
}

impl<T, M0, M1, M2, M3, M4> Matcher<T> for AnyOf<T, (M0, M1, M2, M3, M4)>
where
    T: Clone,
    M0: Matcher<T>,
    M1: Matcher<T>,
    M2: Matcher<T>,
    M3: Matcher<T>,
    M4: Matcher<T>,
{
    fn matches(&self, actual: T) -> MatchResult {
        let (ref m0, ref m1, ref m2, ref m3, ref m4) = self.0;

        m0.matches(actual.clone())
            .or_else(|_| m1.matches(actual.clone()))
            .or_else(|_| m2.matches(actual.clone()))
            .or_else(|_| m3.matches(actual.clone()))
            .or_else(|_| m4.matches(actual.clone()))
    }
}

impl<T, M0, M1, M2, M3, M4, M5> Display for AnyOf<T, (M0, M1, M2, M3, M4, M5)>
where
    M0: Display,
    M1: Display,
    M2: Display,
    M3: Display,
    M4: Display,
    M5: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (ref m0, ref m1, ref m2, ref m3, ref m4, ref m5) = self.0;

        write!(f, "any of ({}, {}, {}, {}, {}, {})", m0, m1, m2, m3, m4, m5)
    }
}

impl<T, M0, M1, M2, M3, M4, M5> Matcher<T> for AnyOf<T, (M0, M1, M2, M3, M4, M5)>
where
    T: Clone,
    M0: Matcher<T>,
    M1: Matcher<T>,
    M2: Matcher<T>,
    M3: Matcher<T>,
    M4: Matcher<T>,
    M5: Matcher<T>,
{
    fn matches(&self, actual: T) -> MatchResult {
        let (ref m0, ref m1, ref m2, ref m3, ref m4, ref m5) = self.0;

        m0.matches(actual.clone())
            .or_else(|_| m1.matches(actual.clone()))
            .or_else(|_| m2.matches(actual.clone()))
            .or_else(|_| m3.matches(actual.clone()))
            .or_else(|_| m4.matches(actual.clone()))
            .or_else(|_| m5.matches(actual.clone()))
    }
}
<|endoftext|>


<commit_before>pub mod segment;
pub mod agent;

use backend::obj;
use backend::obj::*;
use rand;
use rand::Rng;
use std::collections::HashMap;
use std::collections::HashSet;
use std::f32::consts;
use num;
use core::color;
use core::color::ToRgb;
use core::geometry::*;
use backend::world::segment::*;
use backend::world::agent::Agent;

pub struct Flock {
	seq: Id,
	rnd: Randomizer,
	agents: HashMap<Id, agent::Agent>,
	dead: HashSet<Id>,
}

struct Randomizer {
	rng: rand::ThreadRng,
}

#[allow(dead_code)]
impl Randomizer {
	fn new() -> Self {
		Randomizer { rng: rand::thread_rng() }
	}

	fn frand<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Float {
		self.rng.gen::<T>() * (max - min) + min
	}

	fn irand<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Integer + Copy {
		self.rng.gen::<T>() % (max - min + T::one()) + min
	}

	fn random_ball(&mut self) -> Shape {
		let radius: f32 = self.frand(1.0, 2.0);
		Shape::new_ball(radius)
	}

	fn random_box(&mut self) -> Shape {
		let radius: f32 = self.frand(1.0, 2.0);
		let ratio: f32 = self.frand(1.0, 2.0);
		Shape::new_box(radius, ratio)
	}

	fn random_vbar(&mut self) -> Shape {
		let radius: f32 = self.frand(1.0, 2.0);
		let ratio: f32 = self.frand(0.1, 0.2);
		Shape::new_box(radius, ratio)
	}

	fn random_triangle(&mut self) -> Shape {
		let radius = self.frand(0.5, 1.0);
		let alpha1 = self.frand(consts::PI * 0.5, consts::PI * 0.9);
		let alpha2 = consts::PI * 1.5 - self.frand(0., consts::PI);
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn random_iso_triangle(&mut self) -> Shape {
		let radius = self.frand(0.5, 1.0);
		let alpha1 = self.frand(consts::PI * 0.5, consts::PI * 0.9);
		let alpha2 = consts::PI * 2. - alpha1;
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn random_eq_triangle(&mut self) -> Shape {
		let radius = self.frand(0.5, 1.0);
		let alpha1 = consts::PI * 2. / 3.;
		let alpha2 = consts::PI * 2. - alpha1;
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn random_star(&mut self) -> Shape {
		let radius: f32 = self.frand(1.0, 2.0);
		let n = self.irand(3, 8);
		let ratio1 = self.frand(0.5, 1.0);
		let ratio2 = self.frand(0.7, 0.9) * (1. / ratio1);
		Shape::new_star(n, radius, ratio1, ratio2)
	}

	fn random_poly(&mut self, upside_down: bool) -> Shape {
		let n = self.irand(3, 8);
		self.random_npoly(n, upside_down)
	}

	fn random_npoly(&mut self, n: AttachmentIndex, upside_down: bool) -> Shape {
		let radius: f32 = self.frand(1.0, 2.0);
		let ratio1 = f32::cos(consts::PI / n as f32);
		let ratio2 = 1. / ratio1;
		if upside_down {
			Shape::new_star(n, radius * ratio1, ratio2, ratio1)
		} else {
			Shape::new_star(n, radius, ratio1, ratio2)
		}
	}
}

impl Flock {
	pub fn new() -> Flock {
		Flock {
			seq: 0,
			rnd: Randomizer::new(),
			agents: HashMap::new(),
			dead: HashSet::new(),
		}
	}

	pub fn get(&self, id: Id) -> Option<&Agent> {
		self.agents.get(&id)
	}

	pub fn get_mut(&mut self, id: Id) -> Option<&mut agent::Agent> {
		self.agents.get_mut(&id)
	}

	pub fn next_id(&mut self) -> Id {
		self.seq = self.seq + 1;
		self.seq
	}

	pub fn new_resource(&mut self, initial_pos: Position, charge: f32) -> Id {
		let albedo = color::YPbPr::new(0.5, self.rnd.frand(-0.5, 0.5), self.rnd.frand(-0.5, 0.5));
		let ball = self.rnd.random_ball();
		let mut builder = agent::AgentBuilder::new(self.next_id(),
		                                           Material { density: 1.0, ..Default::default() },
		                                           Livery { albedo: albedo.to_rgba(), ..Default::default() },
		                                           segment::State::with_charge(charge, 0., charge));
		self.insert(builder.start(initial_pos, 0., &ball).build())
	}

	pub fn free_resources(&mut self, freed: &mut Vec<Agent>) {
		self.dead.clear();
		for id in self.agents
			.iter()
			.filter(|&(_, agent)| !agent.state.is_alive())
			.map(|(&id, _)| id) {
			self.dead.insert(id);
		}
		for id in self.dead.iter() {
			if let Some(agent) = self.agents.remove(&id) {
				freed.push(agent);
			}
		}
	}

	pub fn new_minion(&mut self, initial_pos: Position, charge: f32) -> Id {
		let albedo = color::Hsl::new(self.rnd.frand(0., 1.), 0.5, 0.5);
		let mut builder = agent::AgentBuilder::new(self.next_id(),
		                                           Material { density: 0.2, ..Default::default() },
		                                           Livery { albedo: albedo.to_rgba(), ..Default::default() },
		                                           segment::State::with_charge(0., charge, charge));
		let arm_shape = self.rnd.random_star();
		let leg_shape = self.rnd.random_star();
		let torso_shape = self.rnd.random_npoly(5, true);
		let head_shape = self.rnd.random_iso_triangle();
		let tail_shape = self.rnd.random_vbar();
		let initial_angle = consts::PI / 2. + f32::atan2(initial_pos.y, initial_pos.x);

		let torso = builder.start(initial_pos, initial_angle, &torso_shape)
			.index();
		builder.addr(torso, 2, &arm_shape, ARM | JOINT | ACTUATOR | RUDDER)
			.addl(torso, -2, &arm_shape, ARM | JOINT | ACTUATOR | RUDDER);

		let head = builder.add(torso, 0, &head_shape, HEAD | SENSOR).index();
		builder.addr(head, 1, &head_shape, HEAD | ACTUATOR | RUDDER)
			.addl(head, 2, &head_shape, HEAD | ACTUATOR | RUDDER);

		let mut belly = torso;
		let mut belly_mid = torso_shape.mid();
		for _ in 0..self.rnd.irand(0, 4) {
			let belly_shape = self.rnd.random_poly(true);

			belly = builder.add(belly, belly_mid, &belly_shape, BELLY | JOINT).index();
			belly_mid = belly_shape.mid();
			if self.rnd.irand(0, 4) == 0 {
				builder.addr(belly, 2, &arm_shape, ARM | ACTUATOR | RUDDER)
					.addl(belly, -2, &arm_shape, ARM | ACTUATOR | RUDDER);
			}
		}

		builder.addr(belly, belly_mid - 1, &leg_shape, LEG | ACTUATOR | THRUSTER)
			.addl(belly,
			      -(belly_mid - 1),
			      &leg_shape,
			      LEG | ACTUATOR | THRUSTER)
			.add(belly, belly_mid, &tail_shape, TAIL | ACTUATOR | BRAKE);

		self.insert(builder.build())
	}

	fn insert(&mut self, agent: Agent) -> Id {
		let id = agent.id();
		self.agents.insert(id, agent);
		id
	}

	// 	pub fn kill(&mut self, id: &Id) {
	// 		self.agents.remove(id);
	// 	}

	pub fn agents(&self) -> &HashMap<Id, Agent> {
		&self.agents
	}

	pub fn agents_mut(&mut self) -> &mut HashMap<Id, Agent> {
		&mut self.agents
	}
}

#[repr(packed)]
#[derive(Eq, Hash, PartialEq, Clone, Copy, Debug)]
pub struct AgentRefs {
	pub agent_id: obj::Id,
	pub segment_index: obj::SegmentIndex,
	pub bone_index: obj::BoneIndex,
}

impl Default for AgentRefs {
	fn default() -> AgentRefs {
		AgentRefs {
			agent_id: 0xdeadbeef,
			segment_index: 0,
			bone_index: 0,
		}
	}
}

impl AgentRefs {
	pub fn with_id(id: obj::Id) -> AgentRefs {
		AgentRefs { agent_id: id, ..Default::default() }
	}

	pub fn with_segment(id: obj::Id, segment_index: obj::SegmentIndex) -> AgentRefs {
		AgentRefs {
			agent_id: id,
			segment_index: segment_index,
			..Default::default()
		}
	}

	pub fn with_bone(id: obj::Id, segment_index: obj::SegmentIndex, bone_index: obj::BoneIndex) -> AgentRefs {
		AgentRefs {
			agent_id: id,
			segment_index: segment_index,
			bone_index: bone_index,
		}
	}

	pub fn no_bone(&self) -> AgentRefs {
		AgentRefs { bone_index: 0, ..*self }
	}
}

pub struct World {
	pub extent: Rect,
	pub fence: obj::Mesh,
	pub players: Flock,
	pub minions: Flock,
	pub friendly_fire: Flock,
	pub enemies: Flock,
	pub enemy_fire: Flock,
	pub resources: Flock,
	pub props: Flock,
}

pub trait WorldState {
	fn minion(&self, id: obj::Id) -> Option<&Agent>;
}

impl WorldState for World {
	fn minion(&self, id: obj::Id) -> Option<&Agent> {
		self.minions.get(id)
	}
}

pub struct Cleanup {
	pub dead: Box<[Agent]>,
}

impl World {
	pub fn new() -> Self {
		World {
			extent: Rect::new(-50., -50., 50., 50.),
			fence: Mesh::from_shape(Shape::new_ball(50.), Winding::CW),
			players: Flock::new(),
			minions: Flock::new(),
			friendly_fire: Flock::new(),
			enemies: Flock::new(),
			enemy_fire: Flock::new(),
			resources: Flock::new(),
			props: Flock::new(),
		}
	}

	pub fn new_resource(&mut self, pos: Position) -> obj::Id {
		self.minions.new_resource(pos, 0.8)
	}

	pub fn new_minion(&mut self, pos: Position) -> obj::Id {
		self.minions.new_minion(pos, 0.3)
	}

	pub fn friend_mut(&mut self, id: obj::Id) -> Option<&mut Agent> {
		self.minions.get_mut(id)
	}

	pub fn cleanup(&mut self) -> Cleanup {
		let mut v = Vec::new();
		self.minions.free_resources(&mut v);
		Cleanup { dead: v.into_boxed_slice() }
	}
}
<commit_msg>Renamed Flock to Swarm<commit_after>pub mod segment;
pub mod agent;

use backend::obj;
use backend::obj::*;
use rand;
use rand::Rng;
use std::collections::HashMap;
use std::collections::HashSet;
use std::f32::consts;
use num;
use core::color;
use core::color::ToRgb;
use core::geometry::*;
use backend::world::segment::*;
use backend::world::agent::Agent;

pub struct Swarm {
	seq: Id,
	rnd: Randomizer,
	agents: HashMap<Id, agent::Agent>,
	dead: HashSet<Id>,
}

struct Randomizer {
	rng: rand::ThreadRng,
}

#[allow(dead_code)]
impl Randomizer {
	fn new() -> Self {
		Randomizer { rng: rand::thread_rng() }
	}

	fn frand<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Float {
		self.rng.gen::<T>() * (max - min) + min
	}

	fn irand<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Integer + Copy {
		self.rng.gen::<T>() % (max - min + T::one()) + min
	}

	fn random_ball(&mut self) -> Shape {
		let radius: f32 = self.frand(1.0, 2.0);
		Shape::new_ball(radius)
	}

	fn random_box(&mut self) -> Shape {
		let radius: f32 = self.frand(1.0, 2.0);
		let ratio: f32 = self.frand(1.0, 2.0);
		Shape::new_box(radius, ratio)
	}

	fn random_vbar(&mut self) -> Shape {
		let radius: f32 = self.frand(1.0, 2.0);
		let ratio: f32 = self.frand(0.1, 0.2);
		Shape::new_box(radius, ratio)
	}

	fn random_triangle(&mut self) -> Shape {
		let radius = self.frand(0.5, 1.0);
		let alpha1 = self.frand(consts::PI * 0.5, consts::PI * 0.9);
		let alpha2 = consts::PI * 1.5 - self.frand(0., consts::PI);
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn random_iso_triangle(&mut self) -> Shape {
		let radius = self.frand(0.5, 1.0);
		let alpha1 = self.frand(consts::PI * 0.5, consts::PI * 0.9);
		let alpha2 = consts::PI * 2. - alpha1;
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn random_eq_triangle(&mut self) -> Shape {
		let radius = self.frand(0.5, 1.0);
		let alpha1 = consts::PI * 2. / 3.;
		let alpha2 = consts::PI * 2. - alpha1;
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn random_star(&mut self) -> Shape {
		let radius: f32 = self.frand(1.0, 2.0);
		let n = self.irand(3, 8);
		let ratio1 = self.frand(0.5, 1.0);
		let ratio2 = self.frand(0.7, 0.9) * (1. / ratio1);
		Shape::new_star(n, radius, ratio1, ratio2)
	}

	fn random_poly(&mut self, upside_down: bool) -> Shape {
		let n = self.irand(3, 8);
		self.random_npoly(n, upside_down)
	}

	fn random_npoly(&mut self, n: AttachmentIndex, upside_down: bool) -> Shape {
		let radius: f32 = self.frand(1.0, 2.0);
		let ratio1 = f32::cos(consts::PI / n as f32);
		let ratio2 = 1. / ratio1;
		if upside_down {
			Shape::new_star(n, radius * ratio1, ratio2, ratio1)
		} else {
			Shape::new_star(n, radius, ratio1, ratio2)
		}
	}
}

impl Swarm {
	pub fn new() -> Swarm {
		Swarm {
			seq: 0,
			rnd: Randomizer::new(),
			agents: HashMap::new(),
			dead: HashSet::new(),
		}
	}

	pub fn get(&self, id: Id) -> Option<&Agent> {
		self.agents.get(&id)
	}

	pub fn get_mut(&mut self, id: Id) -> Option<&mut agent::Agent> {
		self.agents.get_mut(&id)
	}

	pub fn next_id(&mut self) -> Id {
		self.seq = self.seq + 1;
		self.seq
	}

	pub fn new_resource(&mut self, initial_pos: Position, charge: f32) -> Id {
		let albedo = color::YPbPr::new(0.5, self.rnd.frand(-0.5, 0.5), self.rnd.frand(-0.5, 0.5));
		let ball = self.rnd.random_ball();
		let mut builder = agent::AgentBuilder::new(self.next_id(),
		                                           Material { density: 1.0, ..Default::default() },
		                                           Livery { albedo: albedo.to_rgba(), ..Default::default() },
		                                           segment::State::with_charge(charge, 0., charge));
		self.insert(builder.start(initial_pos, 0., &ball).build())
	}

	pub fn free_resources(&mut self, freed: &mut Vec<Agent>) {
		self.dead.clear();
		for id in self.agents
			.iter()
			.filter(|&(_, agent)| !agent.state.is_alive())
			.map(|(&id, _)| id) {
			self.dead.insert(id);
		}
		for id in self.dead.iter() {
			if let Some(agent) = self.agents.remove(&id) {
				freed.push(agent);
			}
		}
	}

	pub fn new_minion(&mut self, initial_pos: Position, charge: f32) -> Id {
		let albedo = color::Hsl::new(self.rnd.frand(0., 1.), 0.5, 0.5);
		let mut builder = agent::AgentBuilder::new(self.next_id(),
		                                           Material { density: 0.2, ..Default::default() },
		                                           Livery { albedo: albedo.to_rgba(), ..Default::default() },
		                                           segment::State::with_charge(0., charge, charge));
		let arm_shape = self.rnd.random_star();
		let leg_shape = self.rnd.random_star();
		let torso_shape = self.rnd.random_npoly(5, true);
		let head_shape = self.rnd.random_iso_triangle();
		let tail_shape = self.rnd.random_vbar();
		let initial_angle = consts::PI / 2. + f32::atan2(initial_pos.y, initial_pos.x);

		let torso = builder.start(initial_pos, initial_angle, &torso_shape)
			.index();
		builder.addr(torso, 2, &arm_shape, ARM | JOINT | ACTUATOR | RUDDER)
			.addl(torso, -2, &arm_shape, ARM | JOINT | ACTUATOR | RUDDER);

		let head = builder.add(torso, 0, &head_shape, HEAD | SENSOR).index();
		builder.addr(head, 1, &head_shape, HEAD | ACTUATOR | RUDDER)
			.addl(head, 2, &head_shape, HEAD | ACTUATOR | RUDDER);

		let mut belly = torso;
		let mut belly_mid = torso_shape.mid();
		for _ in 0..self.rnd.irand(0, 4) {
			let belly_shape = self.rnd.random_poly(true);

			belly = builder.add(belly, belly_mid, &belly_shape, BELLY | JOINT).index();
			belly_mid = belly_shape.mid();
			if self.rnd.irand(0, 4) == 0 {
				builder.addr(belly, 2, &arm_shape, ARM | ACTUATOR | RUDDER)
					.addl(belly, -2, &arm_shape, ARM | ACTUATOR | RUDDER);
			}
		}

		builder.addr(belly, belly_mid - 1, &leg_shape, LEG | ACTUATOR | THRUSTER)
			.addl(belly,
			      -(belly_mid - 1),
			      &leg_shape,
			      LEG | ACTUATOR | THRUSTER)
			.add(belly, belly_mid, &tail_shape, TAIL | ACTUATOR | BRAKE);

		self.insert(builder.build())
	}

	fn insert(&mut self, agent: Agent) -> Id {
		let id = agent.id();
		self.agents.insert(id, agent);
		id
	}

	// 	pub fn kill(&mut self, id: &Id) {
	// 		self.agents.remove(id);
	// 	}

	pub fn agents(&self) -> &HashMap<Id, Agent> {
		&self.agents
	}

	pub fn agents_mut(&mut self) -> &mut HashMap<Id, Agent> {
		&mut self.agents
	}
}

#[repr(packed)]
#[derive(Eq, Hash, PartialEq, Clone, Copy, Debug)]
pub struct AgentRefs {
	pub agent_id: obj::Id,
	pub segment_index: obj::SegmentIndex,
	pub bone_index: obj::BoneIndex,
}

impl Default for AgentRefs {
	fn default() -> AgentRefs {
		AgentRefs {
			agent_id: 0xdeadbeef,
			segment_index: 0,
			bone_index: 0,
		}
	}
}

impl AgentRefs {
	pub fn with_id(id: obj::Id) -> AgentRefs {
		AgentRefs { agent_id: id, ..Default::default() }
	}

	pub fn with_segment(id: obj::Id, segment_index: obj::SegmentIndex) -> AgentRefs {
		AgentRefs {
			agent_id: id,
			segment_index: segment_index,
			..Default::default()
		}
	}

	pub fn with_bone(id: obj::Id, segment_index: obj::SegmentIndex, bone_index: obj::BoneIndex) -> AgentRefs {
		AgentRefs {
			agent_id: id,
			segment_index: segment_index,
			bone_index: bone_index,
		}
	}

	pub fn no_bone(&self) -> AgentRefs {
		AgentRefs { bone_index: 0, ..*self }
	}
}

pub struct World {
	pub extent: Rect,
	pub fence: obj::Mesh,
	pub players: Swarm,
	pub minions: Swarm,
	pub friendly_fire: Swarm,
	pub enemies: Swarm,
	pub enemy_fire: Swarm,
	pub resources: Swarm,
	pub props: Swarm,
}

pub trait WorldState {
	fn minion(&self, id: obj::Id) -> Option<&Agent>;
}

impl WorldState for World {
	fn minion(&self, id: obj::Id) -> Option<&Agent> {
		self.minions.get(id)
	}
}

pub struct Cleanup {
	pub dead: Box<[Agent]>,
}

impl World {
	pub fn new() -> Self {
		World {
			extent: Rect::new(-50., -50., 50., 50.),
			fence: Mesh::from_shape(Shape::new_ball(50.), Winding::CW),
			players: Swarm::new(),
			minions: Swarm::new(),
			friendly_fire: Swarm::new(),
			enemies: Swarm::new(),
			enemy_fire: Swarm::new(),
			resources: Swarm::new(),
			props: Swarm::new(),
		}
	}

	pub fn new_resource(&mut self, pos: Position) -> obj::Id {
		self.minions.new_resource(pos, 0.8)
	}

	pub fn new_minion(&mut self, pos: Position) -> obj::Id {
		self.minions.new_minion(pos, 0.3)
	}

	pub fn friend_mut(&mut self, id: obj::Id) -> Option<&mut Agent> {
		self.minions.get_mut(id)
	}

	pub fn cleanup(&mut self) -> Cleanup {
		let mut v = Vec::new();
		self.minions.free_resources(&mut v);
		Cleanup { dead: v.into_boxed_slice() }
	}
}
<|endoftext|>


<commit_before>//! A trivial example. Copied from ocl-core crate repository.
use af_opencl_interop as afcl;
use arrayfire as af;

use ocl_core::{ContextProperties, Event};

fn main() {
    // Choose platform & device(s) to use. Create a context, queue,
    let platform_id = ocl_core::default_platform().unwrap();
    let device_ids = ocl_core::get_device_ids(&platform_id, None, None).unwrap();
    let device_id = device_ids[0];
    let context_properties = ContextProperties::new().platform(platform_id);
    let context =
        ocl_core::create_context(Some(&context_properties), &[device_id], None, None).unwrap();
    let queue = ocl_core::create_command_queue(&context, &device_id, None).unwrap();
    let dims = [8, 1, 1];

    // Create a `Buffer`:
    let mut vec = vec![0.0f32; dims[0]];
    let buffer = unsafe {
        ocl_core::create_buffer(
            &context,
            ocl_core::MEM_READ_WRITE | ocl_core::MEM_COPY_HOST_PTR,
            dims[0],
            Some(&vec),
        )
        .unwrap()
    };
    ocl_core::finish(&queue).unwrap(); //sync up before switching to arrayfire

    // Add custom device, context and associated queue to ArrayFire
    afcl::add_device_context(device_id.as_raw(), context.as_ptr(), queue.as_ptr());
    afcl::set_device_context(device_id.as_raw(), context.as_ptr());
    af::info();

    let mut af_buffer = af::Array::new_from_device_ptr(
        buffer.as_ptr() as *mut f32,
        af::Dim4::new(&[dims[0] as u64, 1, 1, 1]),
    );

    af::af_print!("GPU Buffer before modification:", af_buffer);

    af_buffer = af_buffer + 10f32;

    af::sync(af::get_device());
    unsafe {
        let ptr = af_buffer.device_ptr();
        let obuf = ocl_core::Mem::from_raw_copied_ptr(ptr);

        // Read results from the device into a vector:
        ocl_core::enqueue_read_buffer(
            &queue,
            &obuf,
            true,
            0,
            &mut vec,
            None::<Event>,
            None::<&mut Event>,
        )
        .unwrap();
    }
    println!("GPU buffer on host after ArrayFire operation: {:?}", vec);

    // Remove device from ArrayFire management towards Application Exit
    af::set_device(0); // Cannot pop when in Use, hence switch to another device
    afcl::delete_device_context(device_id.as_raw(), context.as_ptr());
}
<commit_msg>Set OpenCL backend for opencl interop example<commit_after>//! A trivial example. Copied from ocl-core crate repository.
use af_opencl_interop as afcl;
use arrayfire as af;

use ocl_core::{ContextProperties, Event};

fn main() {
    // Set the arrayfire backend to use OopenCL first, because CUDA is the default
    af::set_backend(af::Backend::OPENCL);

    // Choose platform & device(s) to use. Create a context, queue,
    let platform_id = ocl_core::default_platform().unwrap();
    let device_ids = ocl_core::get_device_ids(&platform_id, None, None).unwrap();
    let device_id = device_ids[0];
    let context_properties = ContextProperties::new().platform(platform_id);
    let context =
        ocl_core::create_context(Some(&context_properties), &[device_id], None, None).unwrap();
    let queue = ocl_core::create_command_queue(&context, &device_id, None).unwrap();
    let dims = [8, 1, 1];

    // Create a `Buffer`:
    let mut vec = vec![0.0f32; dims[0]];
    let buffer = unsafe {
        ocl_core::create_buffer(
            &context,
            ocl_core::MEM_READ_WRITE | ocl_core::MEM_COPY_HOST_PTR,
            dims[0],
            Some(&vec),
        )
        .unwrap()
    };
    ocl_core::finish(&queue).unwrap(); //sync up before switching to arrayfire

    // Add custom device, context and associated queue to ArrayFire
    afcl::add_device_context(device_id.as_raw(), context.as_ptr(), queue.as_ptr());
    afcl::set_device_context(device_id.as_raw(), context.as_ptr());
    af::info();

    let mut af_buffer = af::Array::new_from_device_ptr(
        buffer.as_ptr() as *mut f32,
        af::Dim4::new(&[dims[0] as u64, 1, 1, 1]),
    );

    af::af_print!("GPU Buffer before modification:", af_buffer);

    af_buffer = af_buffer + 10f32;

    af::sync(af::get_device());
    unsafe {
        let ptr = af_buffer.device_ptr();
        let obuf = ocl_core::Mem::from_raw_copied_ptr(ptr);

        // Read results from the device into a vector:
        ocl_core::enqueue_read_buffer(
            &queue,
            &obuf,
            true,
            0,
            &mut vec,
            None::<Event>,
            None::<&mut Event>,
        )
        .unwrap();
    }
    println!("GPU buffer on host after ArrayFire operation: {:?}", vec);

    // Remove device from ArrayFire management towards Application Exit
    af::set_device(0); // Cannot pop when in Use, hence switch to another device
    afcl::delete_device_context(device_id.as_raw(), context.as_ptr());
}
<|endoftext|>


<commit_before>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate linuxdvb;

use std::fs;
use std::error::Error;
use std::path::Path;

use linuxdvb::{Frontend,ReadWriteMode,BlockMode};
use linuxdvb::properties::GetProperty as GP;
use linuxdvb::properties::GetPropertyValue as GPV;

type SimpleResult<T> = Result<T, Box<Error>>;

fn show_frontend_info(path: &Path, yet_another_one: bool) -> SimpleResult<()> {
    let frontend = Frontend::open("/dev/dvb/adapter0/frontend0", ReadWriteMode::ReadOnly, BlockMode::NonBlocking).unwrap();
    if yet_another_one {
        println!("--");
    }
    println!("Device: {}", path.to_string_lossy());
    let info = try!(frontend.get_info());
    println!("Name: {}", info.name);

    let properties = try!(frontend.get_properties(&[
        GP::DtvEnumDelsys
        ]));
    if let GPV::DtvEnumDelsys(delsys) = properties[0] {
        println!("Supported delivery systems: {:?}", delsys.delivery_systems());
    }

    println!("Minimal frequency: {}", info.frequency_min);
    println!("Maximal frequency: {}", info.frequency_max);
    println!("Frequency step: {}", info.frequency_stepsize);
    println!("Frequency tolerance: {}", info.frequency_tolerance);
    println!("Minimal symbol rate: {}", info.symbol_rate_min);
    println!("Maximal symbol rate: {}", info.symbol_rate_max);
    println!("Maximal symbol rate tolerance: {}", info.symbol_rate_tolerance);

    let caps: Vec<linuxdvb::caps::FrontendCapsEnum> = info.caps.into();
    println!("Frontend capabilities: {:?}", caps);

    Ok(())
}

fn iterate_devices(adapter_dir: &Path, yet_another_one: bool) -> SimpleResult<bool> {
    let mut has_frontend = false;
    for device in try!(fs::read_dir(adapter_dir)) {
        let device = try!(device);
        let is_frontend = device.path().file_name()
            .map(|f| f.to_str())
            .unwrap_or(None)
            .map_or(false, |f| f.starts_with("frontend"));
        if is_frontend {
            try!(show_frontend_info(&device.path(), yet_another_one));
            has_frontend = true;
        }
    }
    Ok(has_frontend)
}

fn iterate_adapters() -> SimpleResult<bool> {
    let mut has_frontend = false;
    for adapter_dir in try!(fs::read_dir("/dev/dvb")) {
        let adapter_dir = try!(adapter_dir);
        let is_frontend = try!(iterate_devices(&adapter_dir.path(), has_frontend));
        has_frontend = is_frontend || has_frontend;
    }
    Ok(has_frontend)
}

fn main() {
    let has_frontend = match iterate_adapters() {
        Ok(has_frontend) => has_frontend,
        Err(error) => {
            println!("Error: {}", error.description());
            return;
        }
    };
    if !has_frontend {
        println!("No DVB frontend devices were found");
    }
}<commit_msg>Change parameter type and fix embarrassing bug.<commit_after>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate linuxdvb;

use std::fs;
use std::error::Error;
use std::path::Path;

use linuxdvb::{Frontend,ReadWriteMode,BlockMode};
use linuxdvb::properties::GetProperty as GP;
use linuxdvb::properties::GetPropertyValue as GPV;

type SimpleResult<T> = Result<T, Box<Error>>;

fn show_frontend_info(path: &Path, yet_another_one: bool) -> SimpleResult<()> {
    let frontend = Frontend::open(path, ReadWriteMode::ReadOnly, BlockMode::NonBlocking).unwrap();
    if yet_another_one {
        println!("--");
    }
    println!("Device: {}", path.to_string_lossy());
    let info = try!(frontend.get_info());
    println!("Name: {}", info.name);

    let properties = try!(frontend.get_properties(&[
        GP::DtvEnumDelsys
        ]));
    if let GPV::DtvEnumDelsys(delsys) = properties[0] {
        println!("Supported delivery systems: {:?}", delsys.delivery_systems());
    }

    println!("Minimal frequency: {}", info.frequency_min);
    println!("Maximal frequency: {}", info.frequency_max);
    println!("Frequency step: {}", info.frequency_stepsize);
    println!("Frequency tolerance: {}", info.frequency_tolerance);
    println!("Minimal symbol rate: {}", info.symbol_rate_min);
    println!("Maximal symbol rate: {}", info.symbol_rate_max);
    println!("Maximal symbol rate tolerance: {}", info.symbol_rate_tolerance);

    let caps: Vec<linuxdvb::caps::FrontendCapsEnum> = info.caps.into();
    println!("Frontend capabilities: {:?}", caps);

    Ok(())
}

fn iterate_devices(adapter_dir: &Path, yet_another_one: bool) -> SimpleResult<bool> {
    let mut has_frontend = false;
    for device in try!(fs::read_dir(adapter_dir)) {
        let device = try!(device);
        let is_frontend = device.path().file_name()
            .map(|f| f.to_str())
            .unwrap_or(None)
            .map_or(false, |f| f.starts_with("frontend"));
        if is_frontend {
            try!(show_frontend_info(&device.path(), yet_another_one));
            has_frontend = true;
        }
    }
    Ok(has_frontend)
}

fn iterate_adapters() -> SimpleResult<bool> {
    let mut has_frontend = false;
    for adapter_dir in try!(fs::read_dir("/dev/dvb")) {
        let adapter_dir = try!(adapter_dir);
        let is_frontend = try!(iterate_devices(&adapter_dir.path(), has_frontend));
        has_frontend = is_frontend || has_frontend;
    }
    Ok(has_frontend)
}

fn main() {
    let has_frontend = match iterate_adapters() {
        Ok(has_frontend) => has_frontend,
        Err(error) => {
            println!("Error: {}", error.description());
            return;
        }
    };
    if !has_frontend {
        println!("No DVB frontend devices were found");
    }
}<|endoftext|>


<commit_before>#![feature(integer_atomics)]

extern crate abra;
extern crate rocksdb;
extern crate rustc_serialize;
#[macro_use]
extern crate maplit;
extern crate byteorder;

use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicU32, Ordering};
use std::collections::BTreeMap;

use rocksdb::{DB, WriteBatch, Writable, Options, MergeOperands};
use abra::{Term, Document};
use abra::schema::{Schema, FieldType, FieldRef, AddFieldError};
use rustc_serialize::{json, Encodable};
use byteorder::{ByteOrder, BigEndian};

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
struct TermRef(u32);

impl TermRef {
    pub fn ord(&self) -> u32 {
        self.0
    }
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
struct DocRef(u32, u16);

impl DocRef {
    pub fn chunk(&self) -> u32 {
        self.0
    }

    pub fn ord(&self) -> u16 {
        self.1
    }
}

fn merge_keys(key: &[u8], existing_val: Option<&[u8]>, operands: &mut MergeOperands) -> Vec<u8> {
    match key[0] {
        b'd' => {
            // Directory (sequence of two byte document ids)

            // Allocate vec for new Value
            let new_size = match existing_val {
                Some(existing_val) => existing_val.len(),
                None => 0,
            } + operands.size_hint().0 * 2;

            let mut new_val = Vec::with_capacity(new_size);

            // Push existing value
            existing_val.map(|v| {
                for b in v {
                    new_val.push(*b);
                }
            });

            // Append new entries
            for op in operands {
                for b in op {
                    new_val.push(*b);
                }
            }

            new_val
        }
        _ => {
            // Unrecognised key, fallback to emulating a put operation (by taking the last value)
            operands.last().unwrap().iter().cloned().collect()
        }
    }
}

pub struct RocksDBIndexStore {
    schema: Arc<Schema>,
    db: DB,
    next_term_ref: AtomicU32,
    term_dictionary: RwLock<BTreeMap<Vec<u8>, TermRef>>,
    next_chunk: AtomicU32,
}

impl RocksDBIndexStore {
    pub fn create(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        opts.add_merge_operator("merge operator", merge_keys);
        opts.create_if_missing(true);
        let db = try!(DB::open(&opts, path));

        // Schema
        let schema = Schema::new();
        db.put(b".schema", json::encode(&schema).unwrap().as_bytes());

        // Next term ref
        db.put(b".next_term_ref", b"1");

        // Next chunk
        db.put(b".next_chunk", b"1");

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
            next_term_ref: AtomicU32::new(1),
            term_dictionary: RwLock::new(BTreeMap::new()),
            next_chunk: AtomicU32::new(1),
        })
    }

    pub fn open(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        opts.add_merge_operator("merge operator", merge_keys);
        let db = try!(DB::open(&opts, path));

        let schema = match db.get(b".schema") {
            Ok(Some(schema)) => {
                let schema = schema.to_utf8().unwrap().to_string();
                json::decode(&schema).unwrap()
            }
            Ok(None) => Schema::new(),  // TODO: error
            Err(_) => Schema::new(),  // TODO: error
        };

        let next_term_ref = match db.get(b".next_term_ref") {
            Ok(Some(next_term_ref)) => {
                next_term_ref.to_utf8().unwrap().parse::<u32>().unwrap()
            }
            Ok(None) => 1,  // TODO: error
            Err(_) => 1,  // TODO: error
        };

        let next_chunk = match db.get(b".next_chunk") {
            Ok(Some(next_chunk)) => {
                next_chunk.to_utf8().unwrap().parse::<u32>().unwrap()
            }
            Ok(None) => 1,  // TODO: error
            Err(_) => 1,  // TODO: error
        };

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
            next_term_ref: AtomicU32::new(next_term_ref),
            term_dictionary: RwLock::new(BTreeMap::new()),
            next_chunk: AtomicU32::new(next_chunk),
        })
    }

    pub fn add_field(&mut self, name: String, field_type: FieldType) -> Result<FieldRef, AddFieldError> {
        let mut schema_copy = (*self.schema).clone();
        let field_ref = try!(schema_copy.add_field(name, field_type));
        self.schema = Arc::new(schema_copy);

        self.db.put(b".schema", json::encode(&self.schema).unwrap().as_bytes());

        Ok(field_ref)
    }

    pub fn remove_field(&mut self, field_ref: &FieldRef) -> bool {
        let mut schema_copy = (*self.schema).clone();
        let field_removed = schema_copy.remove_field(field_ref);

        if field_removed {
            self.schema = Arc::new(schema_copy);
            self.db.put(b".schema", json::encode(&self.schema).unwrap().as_bytes());
        }

        field_removed
    }

    fn get_or_create_term(&mut self, term: &Term) -> TermRef {
        let term_bytes = term.to_bytes();

        if let Some(term_ref) = self.term_dictionary.read().unwrap().get(&term_bytes) {
            return *term_ref;
        }

        // Term doesn't exist in the term dictionary

        // Increment next_term_ref
        let next_term_ref = self.next_term_ref.fetch_add(1, Ordering::SeqCst);
        self.db.put(b".next_term_ref", (next_term_ref + 1).to_string().as_bytes());

        // Create term ref
        let term_ref = TermRef(next_term_ref);

        // Get exclusive lock to term dictionary
        let mut term_dictionary = self.term_dictionary.write().unwrap();

        // It's possible that another thread has written the term to the dictionary
        // since we checked earlier. If this is the case, We should forget about
        // writing our TermRef and use the one that has been inserted already.
        if let Some(term_ref) = term_dictionary.get(&term_bytes) {
            return *term_ref;
        }

        // Write it to the on-disk term dictionary
        let mut key = Vec::with_capacity(1 + term_bytes.len());
        key.push(b't');
        for byte in term_bytes.iter() {
            key.push(*byte);
        }
        self.db.put(&key, next_term_ref.to_string().as_bytes());

        // Write it to the term dictionary
        term_dictionary.insert(term_bytes, term_ref);

        term_ref
    }

    pub fn insert_or_update_document(&mut self, doc: Document) {
        // Allocate a new chunk for the document

        // Chunk merges are very slow so we should avoid doing them at runtime
        // which is why each new document is created in a fresh chunk.
        // Later on, a background process will come and merge any small chunks
        // together.

        // For best performance, documents should be inserted in batches.

        // Increment next_chunk
        let next_chunk = self.next_chunk.fetch_add(1, Ordering::SeqCst);
        self.db.put(b".next_chunk", (next_chunk + 1).to_string().as_bytes());

        // Create doc ref
        let doc_ref = DocRef(next_chunk, 0);

        // Start write batch
        let mut write_batch = WriteBatch::default();

        // Insert contents
        for (field_ref, tokens) in doc.fields.iter() {
            for token in tokens.iter() {
                let term_ref = self.get_or_create_term(&token.term);

                let mut key = Vec::with_capacity(20);
                key.push(b'd');
                for byte in field_ref.ord().to_string().as_bytes() {
                    key.push(*byte);
                }
                key.push(b'/');
                for byte in term_ref.ord().to_string().as_bytes() {
                    key.push(*byte);
                }
                key.push(b'/');
                for byte in doc_ref.chunk().to_string().as_bytes() {
                    key.push(*byte);
                }

                let mut doc_id_bytes = [0; 2];
                BigEndian::write_u16(&mut doc_id_bytes, doc_ref.ord());
                write_batch.merge(&key, &doc_id_bytes);
            }
        }

        // Write
        self.db.write(write_batch);
    }
}

#[cfg(test)]
mod tests {
    use rocksdb::{DB, Options, IteratorMode};
    use abra::{Term, Token, Document};
    use abra::schema::{Schema, FieldType, FieldRef};

    use super::RocksDBIndexStore;

    fn clean_test_indices() {
        use std::fs::remove_dir_all;

        remove_dir_all("test_indices");
    }

    #[test]
    fn test_create() {
        clean_test_indices();

        let store = RocksDBIndexStore::create("test_indices/test_create");
        assert!(store.is_ok());
    }

    #[test]
    fn test_open() {
        clean_test_indices();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_err());

        // Create DB
        let mut opts = Options::default();
        opts.create_if_missing(true);
        DB::open(&opts, "test_indices/test_open").unwrap();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_ok());
    }

    fn make_test_store(path: &str) -> RocksDBIndexStore {
        let mut store = RocksDBIndexStore::create(path).unwrap();
        let mut title_field = store.add_field("title".to_string(), FieldType::Text).unwrap();
        let mut body_field = store.add_field("body".to_string(), FieldType::Text).unwrap();

        store.insert_or_update_document(Document {
            key: "test_doc".to_string(),
            fields: hashmap! {
                title_field => vec![
                    Token { term: Term::String("hello".to_string()), position: 1 },
                    Token { term: Term::String("world".to_string()), position: 2 },
                ],
                body_field => vec![
                    Token { term: Term::String("lorem".to_string()), position: 1 },
                    Token { term: Term::String("ipsum".to_string()), position: 2 },
                    Token { term: Term::String("dolar".to_string()), position: 3 },
                ],
            }
        });

        store.insert_or_update_document(Document {
            key: "test_doc".to_string(),
            fields: hashmap! {
                title_field => vec![
                    Token { term: Term::String("howdy".to_string()), position: 1 },
                    Token { term: Term::String("partner".to_string()), position: 2 },
                ],
                body_field => vec![
                    Token { term: Term::String("lorem".to_string()), position: 1 },
                    Token { term: Term::String("ipsum".to_string()), position: 2 },
                    Token { term: Term::String("dolar".to_string()), position: 3 },
                ],
            }
        });

        store
    }

    pub fn print_keys(db: &DB) {
        fn bytes_to_string(bytes: &Box<[u8]>) -> String {
            use std::char;

            let mut string = String::new();

            for byte in bytes.iter() {
                if *byte < 128 {
                    // ASCII character
                    string.push(char::from_u32(*byte as u32).unwrap());
                } else {
                    string.push('?');
                }
            }

            string
        }

        for (key, value) in db.iterator(IteratorMode::Start) {
            println!("{} = {:?}", bytes_to_string(&key), value);
        }
    }

    #[test]
    fn test() {
        clean_test_indices();

        let store = make_test_store("test_indices/test");

        print_keys(&store.db);

    }
}
<commit_msg>Document key index and deletion list<commit_after>#![feature(integer_atomics)]

extern crate abra;
extern crate rocksdb;
extern crate rustc_serialize;
#[macro_use]
extern crate maplit;
extern crate byteorder;

use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicU32, Ordering};
use std::collections::BTreeMap;

use rocksdb::{DB, WriteBatch, Writable, Options, MergeOperands};
use abra::{Term, Document};
use abra::schema::{Schema, FieldType, FieldRef, AddFieldError};
use rustc_serialize::{json, Encodable};
use byteorder::{ByteOrder, BigEndian};

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
struct TermRef(u32);

impl TermRef {
    pub fn ord(&self) -> u32 {
        self.0
    }
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
struct DocRef(u32, u16);

impl DocRef {
    pub fn chunk(&self) -> u32 {
        self.0
    }

    pub fn ord(&self) -> u16 {
        self.1
    }
}

fn merge_keys(key: &[u8], existing_val: Option<&[u8]>, operands: &mut MergeOperands) -> Vec<u8> {
    match key[0] {
        b'd' | b'x' => {
            // Sequence of two byte document ids
            // d = directory
            // x = deletion list

            // Allocate vec for new Value
            let new_size = match existing_val {
                Some(existing_val) => existing_val.len(),
                None => 0,
            } + operands.size_hint().0 * 2;

            let mut new_val = Vec::with_capacity(new_size);

            // Push existing value
            existing_val.map(|v| {
                for b in v {
                    new_val.push(*b);
                }
            });

            // Append new entries
            for op in operands {
                for b in op {
                    new_val.push(*b);
                }
            }

            new_val
        }
        _ => {
            // Unrecognised key, fallback to emulating a put operation (by taking the last value)
            operands.last().unwrap().iter().cloned().collect()
        }
    }
}

pub struct RocksDBIndexStore {
    schema: Arc<Schema>,
    db: DB,
    next_term_ref: AtomicU32,
    term_dictionary: RwLock<BTreeMap<Vec<u8>, TermRef>>,
    next_chunk: AtomicU32,
    doc_key_mapping: RwLock<BTreeMap<Vec<u8>, DocRef>>,
    deleted_docs: RwLock<Vec<DocRef>>,
}

impl RocksDBIndexStore {
    pub fn create(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        opts.add_merge_operator("merge operator", merge_keys);
        opts.create_if_missing(true);
        let db = try!(DB::open(&opts, path));

        // Schema
        let schema = Schema::new();
        db.put(b".schema", json::encode(&schema).unwrap().as_bytes());

        // Next term ref
        db.put(b".next_term_ref", b"1");

        // Next chunk
        db.put(b".next_chunk", b"1");

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
            next_term_ref: AtomicU32::new(1),
            term_dictionary: RwLock::new(BTreeMap::new()),
            next_chunk: AtomicU32::new(1),
            doc_key_mapping: RwLock::new(BTreeMap::new()),
            deleted_docs: RwLock::new(Vec::new()),
        })
    }

    pub fn open(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        opts.add_merge_operator("merge operator", merge_keys);
        let db = try!(DB::open(&opts, path));

        let schema = match db.get(b".schema") {
            Ok(Some(schema)) => {
                let schema = schema.to_utf8().unwrap().to_string();
                json::decode(&schema).unwrap()
            }
            Ok(None) => Schema::new(),  // TODO: error
            Err(_) => Schema::new(),  // TODO: error
        };

        let next_term_ref = match db.get(b".next_term_ref") {
            Ok(Some(next_term_ref)) => {
                next_term_ref.to_utf8().unwrap().parse::<u32>().unwrap()
            }
            Ok(None) => 1,  // TODO: error
            Err(_) => 1,  // TODO: error
        };

        let next_chunk = match db.get(b".next_chunk") {
            Ok(Some(next_chunk)) => {
                next_chunk.to_utf8().unwrap().parse::<u32>().unwrap()
            }
            Ok(None) => 1,  // TODO: error
            Err(_) => 1,  // TODO: error
        };

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
            next_term_ref: AtomicU32::new(next_term_ref),
            term_dictionary: RwLock::new(BTreeMap::new()),
            next_chunk: AtomicU32::new(next_chunk),
            doc_key_mapping: RwLock::new(BTreeMap::new()),
            deleted_docs: RwLock::new(Vec::new()),
        })
    }

    pub fn add_field(&mut self, name: String, field_type: FieldType) -> Result<FieldRef, AddFieldError> {
        let mut schema_copy = (*self.schema).clone();
        let field_ref = try!(schema_copy.add_field(name, field_type));
        self.schema = Arc::new(schema_copy);

        self.db.put(b".schema", json::encode(&self.schema).unwrap().as_bytes());

        Ok(field_ref)
    }

    pub fn remove_field(&mut self, field_ref: &FieldRef) -> bool {
        let mut schema_copy = (*self.schema).clone();
        let field_removed = schema_copy.remove_field(field_ref);

        if field_removed {
            self.schema = Arc::new(schema_copy);
            self.db.put(b".schema", json::encode(&self.schema).unwrap().as_bytes());
        }

        field_removed
    }

    fn get_or_create_term(&mut self, term: &Term) -> TermRef {
        let term_bytes = term.to_bytes();

        if let Some(term_ref) = self.term_dictionary.read().unwrap().get(&term_bytes) {
            return *term_ref;
        }

        // Term doesn't exist in the term dictionary

        // Increment next_term_ref
        let next_term_ref = self.next_term_ref.fetch_add(1, Ordering::SeqCst);
        self.db.put(b".next_term_ref", (next_term_ref + 1).to_string().as_bytes());

        // Create term ref
        let term_ref = TermRef(next_term_ref);

        // Get exclusive lock to term dictionary
        let mut term_dictionary = self.term_dictionary.write().unwrap();

        // It's possible that another thread has written the term to the dictionary
        // since we checked earlier. If this is the case, We should forget about
        // writing our TermRef and use the one that has been inserted already.
        if let Some(term_ref) = term_dictionary.get(&term_bytes) {
            return *term_ref;
        }

        // Write it to the on-disk term dictionary
        let mut key = Vec::with_capacity(1 + term_bytes.len());
        key.push(b't');
        for byte in term_bytes.iter() {
            key.push(*byte);
        }
        self.db.put(&key, next_term_ref.to_string().as_bytes());

        // Write it to the term dictionary
        term_dictionary.insert(term_bytes, term_ref);

        term_ref
    }

    pub fn insert_or_update_document(&mut self, doc: Document) {
        // Allocate a new chunk for the document

        // Chunk merges are very slow so we should avoid doing them at runtime
        // which is why each new document is created in a fresh chunk.
        // Later on, a background process will come and merge any small chunks
        // together.

        // For best performance, documents should be inserted in batches.

        // Increment next_chunk
        let next_chunk = self.next_chunk.fetch_add(1, Ordering::SeqCst);
        self.db.put(b".next_chunk", (next_chunk + 1).to_string().as_bytes());

        // Create doc ref
        let doc_ref = DocRef(next_chunk, 0);

        // Start write batch
        let mut write_batch = WriteBatch::default();

        // Insert contents
        for (field_ref, tokens) in doc.fields.iter() {
            for token in tokens.iter() {
                let term_ref = self.get_or_create_term(&token.term);

                let mut key = Vec::with_capacity(20);
                key.push(b'd');
                for byte in field_ref.ord().to_string().as_bytes() {
                    key.push(*byte);
                }
                key.push(b'/');
                for byte in term_ref.ord().to_string().as_bytes() {
                    key.push(*byte);
                }
                key.push(b'/');
                for byte in doc_ref.chunk().to_string().as_bytes() {
                    key.push(*byte);
                }

                let mut doc_id_bytes = [0; 2];
                BigEndian::write_u16(&mut doc_id_bytes, doc_ref.ord());
                write_batch.merge(&key, &doc_id_bytes);
            }
        }

        // Write document data
        self.db.write(write_batch);

        // Update doc_key_mapping
        let mut write_batch = WriteBatch::default();
        let previous_doc_ref = self.doc_key_mapping.write().unwrap().insert(doc.key.as_bytes().iter().cloned().collect(), doc_ref);

        let mut key = Vec::with_capacity(1 + doc.key.len());
        key.push(b'k');
        for byte in doc.key.as_bytes() {
            key.push(*byte);
        }
        let mut doc_ref_bytes = [0; 6];
        BigEndian::write_u32(&mut doc_ref_bytes, doc_ref.chunk());
        BigEndian::write_u16(&mut doc_ref_bytes[4..], doc_ref.ord());
        write_batch.put(&key, &doc_ref_bytes);

        // If there was a document there previously, mark it as deleted
        if let Some(previous_doc_ref) = previous_doc_ref {
            self.deleted_docs.write().unwrap().push(previous_doc_ref);

            let mut key = Vec::with_capacity(5);
            key.push(b'x');
            for byte in previous_doc_ref.chunk().to_string().as_bytes() {
                key.push(*byte);
            }

            let mut previous_doc_id_bytes = [0; 2];
            BigEndian::write_u16(&mut previous_doc_id_bytes, previous_doc_ref.ord());
            write_batch.merge(&key, &previous_doc_id_bytes);
        }

        // Write document data
        self.db.write(write_batch);
    }
}

#[cfg(test)]
mod tests {
    use rocksdb::{DB, Options, IteratorMode};
    use abra::{Term, Token, Document};
    use abra::schema::{Schema, FieldType, FieldRef};

    use super::RocksDBIndexStore;

    fn clean_test_indices() {
        use std::fs::remove_dir_all;

        remove_dir_all("test_indices");
    }

    #[test]
    fn test_create() {
        clean_test_indices();

        let store = RocksDBIndexStore::create("test_indices/test_create");
        assert!(store.is_ok());
    }

    #[test]
    fn test_open() {
        clean_test_indices();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_err());

        // Create DB
        let mut opts = Options::default();
        opts.create_if_missing(true);
        DB::open(&opts, "test_indices/test_open").unwrap();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_ok());
    }

    fn make_test_store(path: &str) -> RocksDBIndexStore {
        let mut store = RocksDBIndexStore::create(path).unwrap();
        let mut title_field = store.add_field("title".to_string(), FieldType::Text).unwrap();
        let mut body_field = store.add_field("body".to_string(), FieldType::Text).unwrap();

        store.insert_or_update_document(Document {
            key: "test_doc".to_string(),
            fields: hashmap! {
                title_field => vec![
                    Token { term: Term::String("hello".to_string()), position: 1 },
                    Token { term: Term::String("world".to_string()), position: 2 },
                ],
                body_field => vec![
                    Token { term: Term::String("lorem".to_string()), position: 1 },
                    Token { term: Term::String("ipsum".to_string()), position: 2 },
                    Token { term: Term::String("dolar".to_string()), position: 3 },
                ],
            }
        });

        store.insert_or_update_document(Document {
            key: "another_test_doc".to_string(),
            fields: hashmap! {
                title_field => vec![
                    Token { term: Term::String("howdy".to_string()), position: 1 },
                    Token { term: Term::String("partner".to_string()), position: 2 },
                ],
                body_field => vec![
                    Token { term: Term::String("lorem".to_string()), position: 1 },
                    Token { term: Term::String("ipsum".to_string()), position: 2 },
                    Token { term: Term::String("dolar".to_string()), position: 3 },
                ],
            }
        });

        store
    }

    pub fn print_keys(db: &DB) {
        fn bytes_to_string(bytes: &Box<[u8]>) -> String {
            use std::char;

            let mut string = String::new();

            for byte in bytes.iter() {
                if *byte < 128 {
                    // ASCII character
                    string.push(char::from_u32(*byte as u32).unwrap());
                } else {
                    string.push('?');
                }
            }

            string
        }

        for (key, value) in db.iterator(IteratorMode::Start) {
            println!("{} = {:?}", bytes_to_string(&key), value);
        }
    }

    #[test]
    fn test() {
        clean_test_indices();

        let store = make_test_store("test_indices/test");

        print_keys(&store.db);

    }
}
<|endoftext|>


<commit_before>//! Light filters and nodes.
use rulinalg::{norm::Euclidean, vector::Vector};

use filters::context::IRect;
use surface_utils::{iterators::PixelRectangle, shared_surface::SharedImageSurface, EdgeMode};

pub mod diffuse_lighting;
pub mod light_source;
pub mod specular_lighting;

/// Normalizes a `Vector`. Returns `Err(())` if the vector has a length of zero.
fn normalize(v: &mut Vector<f64>) -> Result<(), ()> {
    let norm = v.norm(Euclidean);
    if norm == 0.0 {
        return Err(());
    }

    *v /= norm;
    Ok(())
}

/// Computes and returns the normal vector for the light filters.
fn normal(
    surface: &SharedImageSurface,
    bounds: IRect,
    x: u32,
    y: u32,
    surface_scale: f64,
) -> Vector<f64> {
    assert!(x as i32 >= bounds.x0);
    assert!(y as i32 >= bounds.y0);
    assert!((x as i32) < bounds.x1);
    assert!((y as i32) < bounds.y1);

    // Get the correct sobel kernel and factor for the pixel position.
    // Performance note: it's possible to replace the matrices with normal arrays.
    let (factor_x, kx, factor_y, ky) = match (x as i32, y as i32) {
        (x, y) if (x, y) == (bounds.x0, bounds.y0) => (
            2. / 3.,
            matrix![
                0.,  0., 0.;
                0., -2., 2.;
                0., -1., 1.
            ],
            2. / 3.,
            matrix![
                0.,  0.,  0.;
                0., -2., -1.;
                0.,  2.,  1.
            ],
        ),
        (x, y) if (x + 1, y) == (bounds.x1, bounds.y0) => (
            2. / 3.,
            matrix![
                 0.,  0.,  0.;
                -2.,  2.,  0.;
                -1.,  1.,  0.
            ],
            2. / 3.,
            matrix![
                 0.,  0.,  0.;
                -1., -2.,  0.;
                 1.,  2.,  0.
            ],
        ),
        (x, y) if (x, y + 1) == (bounds.x0, bounds.y1) => (
            2. / 3.,
            matrix![
                0., -1.,  1.;
                0., -2.,  2.;
                0.,  0.,  0.
            ],
            2. / 3.,
            matrix![
                 0., -2., -1.;
                 0.,  2.,  1.;
                 0.,  0.,  0.
            ],
        ),
        (x, y) if (x + 1, y + 1) == (bounds.x1, bounds.y1) => (
            2. / 3.,
            matrix![
                -1.,  1.,  0.;
                -2.,  2.,  0.;
                 0.,  0.,  0.
            ],
            2. / 3.,
            matrix![
                -1., -2.,  0.;
                 1.,  2.,  0.;
                 0.,  0.,  0.
            ],
        ),
        (_, y) if y == bounds.y0 => (
            1. / 3.,
            matrix![
                 0.,  0.,  0.;
                -2.,  0.,  2.;
                -1.,  0.,  1.
            ],
            1. / 2.,
            matrix![
                 0.,  0.,  0.;
                -1., -2., -1.;
                 1.,  2.,  1.
            ],
        ),
        (x, _) if x == bounds.x0 => (
            1. / 2.,
            matrix![
                0., -1.,  1.;
                0., -2.,  2.;
                0., -1.,  1.
            ],
            1. / 3.,
            matrix![
                 0., -2., -1.;
                 0.,  0.,  0.;
                 0.,  2.,  1.
            ],
        ),
        (x, _) if x + 1 == bounds.x1 => (
            1. / 2.,
            matrix![
                -1.,  1., 0.;
                -2.,  2., 0.;
                -1.,  1., 0.
            ],
            1. / 3.,
            matrix![
                -1., -2.,  0.;
                 0.,  0.,  0.;
                 1.,  2.,  0.
            ],
        ),
        (_, y) if y + 1 == bounds.y1 => (
            1. / 3.,
            matrix![
                -1.,  0.,  1.;
                -2.,  0.,  2.;
                 0.,  0.,  0.
            ],
            1. / 2.,
            matrix![
                -1., -2., -1.;
                 1.,  2.,  1.;
                 0.,  0.,  0.
            ],
        ),
        _ => (
            1. / 4.,
            matrix![
                -1.,  0.,  1.;
                -2.,  0.,  2.;
                -1.,  0.,  1.
            ],
            1. / 4.,
            matrix![
                -1., -2., -1.;
                 0.,  0.,  0.;
                 1.,  2.,  1.
            ],
        ),
    };

    let kernel_bounds = IRect {
        x0: x as i32 - 1,
        y0: y as i32 - 1,
        x1: x as i32 + 2,
        y1: y as i32 + 2,
    };

    let mut nx = 0.0;
    let mut ny = 0.0;
    for (x, y, pixel) in PixelRectangle::new(surface, bounds, kernel_bounds, EdgeMode::None) {
        let kernel_x = (x - kernel_bounds.x0) as usize;
        let kernel_y = (y - kernel_bounds.y0) as usize;
        let alpha = f64::from(pixel.a) / 255.0;

        nx += alpha * kx[[kernel_y, kernel_x]];
        ny += alpha * ky[[kernel_y, kernel_x]];
    }

    nx *= factor_x * surface_scale;
    ny *= factor_y * surface_scale;

    // Negative nx and ny to account for the different coordinate system.
    let mut n = vector![-nx, -ny, 1.0];
    normalize(&mut n).unwrap();
    n
}
<commit_msg>Use stack arrays in filters::light::normal()<commit_after>//! Light filters and nodes.
use rulinalg::{norm::Euclidean, vector::Vector};

use filters::context::IRect;
use surface_utils::{iterators::PixelRectangle, shared_surface::SharedImageSurface, EdgeMode};

pub mod diffuse_lighting;
pub mod light_source;
pub mod specular_lighting;

/// Normalizes a `Vector`. Returns `Err(())` if the vector has a length of zero.
fn normalize(v: &mut Vector<f64>) -> Result<(), ()> {
    let norm = v.norm(Euclidean);
    if norm == 0.0 {
        return Err(());
    }

    *v /= norm;
    Ok(())
}

/// Computes and returns the normal vector for the light filters.
fn normal(
    surface: &SharedImageSurface,
    bounds: IRect,
    x: u32,
    y: u32,
    surface_scale: f64,
) -> Vector<f64> {
    assert!(x as i32 >= bounds.x0);
    assert!(y as i32 >= bounds.y0);
    assert!((x as i32) < bounds.x1);
    assert!((y as i32) < bounds.y1);

    // Get the correct sobel kernel and factor for the pixel position.
    // Performance note: it's possible to replace the matrices with normal arrays.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    let (factor_x, kx, factor_y, ky) = match (x as i32, y as i32) {
        (x, y) if (x, y) == (bounds.x0, bounds.y0) => (
            2. / 3.,
            [
                [0.,  0., 0.],
                [0., -2., 2.],
                [0., -1., 1.],
            ],
            2. / 3.,
            [
                [0.,  0.,  0.],
                [0., -2., -1.],
                [0.,  2.,  1.],
            ],
        ),
        (x, y) if (x + 1, y) == (bounds.x1, bounds.y0) => (
            2. / 3.,
            [
                [0.,  0., 0.],
                [-2., 2., 0.],
                [-1., 1., 0.],
            ],
            2. / 3.,
            [
                [ 0.,  0., 0.],
                [-1., -2., 0.],
                [ 1.,  2., 0.],
            ],
        ),
        (x, y) if (x, y + 1) == (bounds.x0, bounds.y1) => (
            2. / 3.,
            [
                [0., -1., 1.],
                [0., -2., 2.],
                [0.,  0., 0.],
            ],
            2. / 3.,
            [
                [0., -2., -1.],
                [0.,  2.,  1.],
                [0.,  0.,  0.],
            ],
        ),
        (x, y) if (x + 1, y + 1) == (bounds.x1, bounds.y1) => (
            2. / 3.,
            [
                [-1., 1., 0.],
                [-2., 2., 0.],
                [ 0., 0., 0.],
            ],
            2. / 3.,
            [
                [-1., -2., 0.],
                [ 1.,  2., 0.],
                [ 0.,  0., 0.],
            ],
        ),
        (_, y) if y == bounds.y0 => (
            1. / 3.,
            [
                [ 0., 0., 0.],
                [-2., 0., 2.],
                [-1., 0., 1.],
            ],
            1. / 2.,
            [
                [ 0.,  0.,  0.],
                [-1., -2., -1.],
                [ 1.,  2.,  1.],
            ],
        ),
        (x, _) if x == bounds.x0 => (
            1. / 2.,
            [
                [0., -1., 1.],
                [0., -2., 2.],
                [0., -1., 1.],
            ],
            1. / 3.,
            [
                [0., -2., -1.],
                [0.,  0.,  0.],
                [0.,  2.,  1.],
            ],
        ),
        (x, _) if x + 1 == bounds.x1 => (
            1. / 2.,
            [
                [-1., 1., 0.],
                [-2., 2., 0.],
                [-1., 1., 0.],
            ],
            1. / 3.,
            [
                [-1., -2., 0.],
                [ 0.,  0., 0.],
                [ 1.,  2., 0.],
            ],
        ),
        (_, y) if y + 1 == bounds.y1 => (
            1. / 3.,
            [
                [-1., 0., 1.],
                [-2., 0., 2.],
                [ 0., 0., 0.],
            ],
            1. / 2.,
            [
                [-1., -2., -1.],
                [ 1.,  2.,  1.],
                [ 0.,  0.,  0.],
            ],
        ),
        _ => (
            1. / 4.,
            [
                [-1., 0., 1.],
                [-2., 0., 2.],
                [-1., 0., 1.],
            ],
            1. / 4.,
            [
                [-1., -2., -1.],
                [ 0.,  0.,  0.],
                [ 1.,  2.,  1.],
            ],
        ),
    };

    let kernel_bounds = IRect {
        x0: x as i32 - 1,
        y0: y as i32 - 1,
        x1: x as i32 + 2,
        y1: y as i32 + 2,
    };

    let mut nx = 0.0;
    let mut ny = 0.0;
    for (x, y, pixel) in PixelRectangle::new(surface, bounds, kernel_bounds, EdgeMode::None) {
        let kernel_x = (x - kernel_bounds.x0) as usize;
        let kernel_y = (y - kernel_bounds.y0) as usize;
        let alpha = f64::from(pixel.a) / 255.0;

        nx += alpha * kx[kernel_y][kernel_x];
        ny += alpha * ky[kernel_y][kernel_x];
    }

    nx *= factor_x * surface_scale;
    ny *= factor_y * surface_scale;

    // Negative nx and ny to account for the different coordinate system.
    let mut n = vector![-nx, -ny, 1.0];
    normalize(&mut n).unwrap();
    n
}
<|endoftext|>


<commit_before><commit_msg>Don't parse non-template attributes<commit_after><|endoftext|>


<commit_before>use std::ffi::OsStr;
use std::ffi::OsString;

#[derive(Debug)]
pub(crate) struct Input {
    items: Vec<OsString>,
    cursor: usize,
}

impl<I, T> From<I> for Input
where
    I: Iterator<Item = T>,
    T: Into<OsString> + Clone,
{
    fn from(val: I) -> Self {
        Self {
            items: val.map(|x| x.into()).collect(),
            cursor: 0,
        }
    }
}

impl Input {
    pub(crate) fn next(&mut self) -> Option<(&OsStr, &[OsString])> {
        if self.cursor >= self.items.len() {
            None
        } else {
            let current = &self.items[self.cursor];
            self.cursor += 1;
            let remaining = &self.items[self.cursor..];
            Some((current, remaining))
        }
    }

    pub(crate) fn previous(&mut self) {
        self.cursor -= 1;
    }

    /// Insert some items to the Input items just after current parsing cursor.
    /// Usually used by replaced items recovering.
    pub(crate) fn insert(&mut self, insert_items: &[&str]) {
        self.items = insert_items
            .iter()
            .map(OsString::from)
            .chain(self.items.drain(self.cursor..))
            .collect();
        self.cursor = 0;
    }
}
<commit_msg>refactor(lex): Remove unused bound<commit_after>use std::ffi::OsStr;
use std::ffi::OsString;

#[derive(Debug)]
pub(crate) struct Input {
    items: Vec<OsString>,
    cursor: usize,
}

impl<I, T> From<I> for Input
where
    I: Iterator<Item = T>,
    T: Into<OsString>,
{
    fn from(val: I) -> Self {
        Self {
            items: val.map(|x| x.into()).collect(),
            cursor: 0,
        }
    }
}

impl Input {
    pub(crate) fn next(&mut self) -> Option<(&OsStr, &[OsString])> {
        if self.cursor >= self.items.len() {
            None
        } else {
            let current = &self.items[self.cursor];
            self.cursor += 1;
            let remaining = &self.items[self.cursor..];
            Some((current, remaining))
        }
    }

    pub(crate) fn previous(&mut self) {
        self.cursor -= 1;
    }

    /// Insert some items to the Input items just after current parsing cursor.
    /// Usually used by replaced items recovering.
    pub(crate) fn insert(&mut self, insert_items: &[&str]) {
        self.items = insert_items
            .iter()
            .map(OsString::from)
            .chain(self.items.drain(self.cursor..))
            .collect();
        self.cursor = 0;
    }
}
<|endoftext|>


<commit_before>use std::fmt::{ Display, Formatter };
use std::fmt::Error as FormatError;
use std::num::ParseFloatError;
use read_token::ParseStringError;
use std::rc::Rc;

use {
    Type,
    DebugId
};

/// Errors reporting expected values.
#[derive(Debug, PartialEq)]
pub enum ParseError {
    /// Not supported.
    NotSupported,
    /// Whitespace is required.
    ExpectedWhitespace(DebugId),
    /// Something is required.
    ExpectedSomething(DebugId),
    /// Expected number.
    ExpectedNumber(DebugId),
    /// Error when parsing float.
    ParseFloatError(ParseFloatError, DebugId),
    /// Expected text.
    ExpectedText(DebugId),
    /// Empty text not allowed.
    EmptyTextNotAllowed(DebugId),
    /// Invalid string format.
    ParseStringError(ParseStringError, DebugId),
    /// Expected token.
    ExpectedToken(Rc<String>, DebugId),
    /// An invalid rule.
    InvalidRule(&'static str, DebugId),
    /// Expected nodes with other names.
    ExpectedNode(Vec<String>),
    /// Expected another propert type.
    ExpectedPropertyType(Type),
    /// Reaching end of node, but expected more properties.
    ExpectedMoreProperties(Vec<String>),
}

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatError> {
        match self {
            &ParseError::NotSupported =>
                try!(fmt.write_str("This feature is not supported")),
            &ParseError::ExpectedWhitespace(debug_id) =>
                try!(write!(fmt, "#{}, Expected whitespace",
                    debug_id)),
            &ParseError::ExpectedSomething(debug_id) =>
                try!(write!(fmt, "#{}, Expected something",
                    debug_id)),
            &ParseError::ExpectedNumber(debug_id) =>
                try!(write!(fmt, "#{}, Expected number", debug_id)),
            &ParseError::ParseFloatError(ref err, debug_id) =>
                try!(fmt.write_fmt(format_args!(
                    "#{}, Invalid number format: {}", debug_id, err
                ))),
            &ParseError::ExpectedToken(ref token, debug_id) =>
                try!(write!(fmt, "#{}, Expected: `{}`", debug_id,
                    token)),
            &ParseError::ExpectedText(debug_id) =>
                try!(write!(fmt, "#{}, Expected text", debug_id)),
            &ParseError::EmptyTextNotAllowed(debug_id) =>
                try!(write!(fmt, "#{}, Empty text not allowed",
                    debug_id)),
            &ParseError::ParseStringError(err, debug_id) =>
                try!(write!(fmt, "#{}, Invalid string format: {}",
                    debug_id, err)),
            &ParseError::ExpectedNode(ref nodes) => {
                try!(fmt.write_str("Expected nodes: "));
                let mut tail = false;
                for node in nodes {
                    if tail {
                        try!(fmt.write_str(", "));
                    } else {
                        tail = true;
                    }
                    try!(fmt.write_str(&node));
                }
            }
            &ParseError::ExpectedPropertyType(ref ty) =>
                try!(fmt.write_fmt(format_args!(
                    "Expected property type: {}", ty
                ))),
            &ParseError::ExpectedMoreProperties(ref props) => {
                try!(fmt.write_str("Expected more properties: "));
                let mut tail = false;
                for prop in props {
                    if tail {
                        try!(fmt.write_str(", "));
                    } else {
                        tail = true;
                    }
                    try!(fmt.write_str(prop));
                }
            }
            &ParseError::InvalidRule(msg, debug_id) =>
                try!(fmt.write_fmt(format_args!(
                    "#{}, Invalid rule: {}", debug_id, msg
                ))),
        }
        Ok(())
    }
}
<commit_msg>Use `write!` macro instead of `fmt.write_fmt`<commit_after>use std::fmt::{ Display, Formatter };
use std::fmt::Error as FormatError;
use std::num::ParseFloatError;
use read_token::ParseStringError;
use std::rc::Rc;

use {
    Type,
    DebugId
};

/// Errors reporting expected values.
#[derive(Debug, PartialEq)]
pub enum ParseError {
    /// Not supported.
    NotSupported,
    /// Whitespace is required.
    ExpectedWhitespace(DebugId),
    /// Something is required.
    ExpectedSomething(DebugId),
    /// Expected number.
    ExpectedNumber(DebugId),
    /// Error when parsing float.
    ParseFloatError(ParseFloatError, DebugId),
    /// Expected text.
    ExpectedText(DebugId),
    /// Empty text not allowed.
    EmptyTextNotAllowed(DebugId),
    /// Invalid string format.
    ParseStringError(ParseStringError, DebugId),
    /// Expected token.
    ExpectedToken(Rc<String>, DebugId),
    /// An invalid rule.
    InvalidRule(&'static str, DebugId),
    /// Expected nodes with other names.
    ExpectedNode(Vec<String>),
    /// Expected another propert type.
    ExpectedPropertyType(Type),
    /// Reaching end of node, but expected more properties.
    ExpectedMoreProperties(Vec<String>),
}

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatError> {
        match self {
            &ParseError::NotSupported =>
                try!(fmt.write_str("This feature is not supported")),
            &ParseError::ExpectedWhitespace(debug_id) =>
                try!(write!(fmt, "#{}, Expected whitespace",
                    debug_id)),
            &ParseError::ExpectedSomething(debug_id) =>
                try!(write!(fmt, "#{}, Expected something",
                    debug_id)),
            &ParseError::ExpectedNumber(debug_id) =>
                try!(write!(fmt, "#{}, Expected number", debug_id)),
            &ParseError::ParseFloatError(ref err, debug_id) =>
                try!(write!(fmt, "#{}, Invalid number format: {}",
                    debug_id, err)),
            &ParseError::ExpectedToken(ref token, debug_id) =>
                try!(write!(fmt, "#{}, Expected: `{}`", debug_id, token)),
            &ParseError::ExpectedText(debug_id) =>
                try!(write!(fmt, "#{}, Expected text", debug_id)),
            &ParseError::EmptyTextNotAllowed(debug_id) =>
                try!(write!(fmt, "#{}, Empty text not allowed", debug_id)),
            &ParseError::ParseStringError(err, debug_id) =>
                try!(write!(fmt, "#{}, Invalid string format: {}",
                    debug_id, err)),
            &ParseError::ExpectedNode(ref nodes) => {
                try!(fmt.write_str("Expected nodes: "));
                let mut tail = false;
                for node in nodes {
                    if tail {
                        try!(fmt.write_str(", "));
                    } else {
                        tail = true;
                    }
                    try!(fmt.write_str(&node));
                }
            }
            &ParseError::ExpectedPropertyType(ref ty) =>
                try!(write!(fmt, "Expected property type: {}", ty)),
            &ParseError::ExpectedMoreProperties(ref props) => {
                try!(fmt.write_str("Expected more properties: "));
                let mut tail = false;
                for prop in props {
                    if tail {
                        try!(fmt.write_str(", "));
                    } else {
                        tail = true;
                    }
                    try!(fmt.write_str(prop));
                }
            }
            &ParseError::InvalidRule(msg, debug_id) =>
                try!(write!(fmt, "#{}, Invalid rule: {}", debug_id, msg)),
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before><commit_msg>Filter test for method call arguments.<commit_after><|endoftext|>


<commit_before><commit_msg>Test that destructors are called.<commit_after><|endoftext|>