<commit_before>use wrapped2d::b2;
use wrapped2d::user_data::*;
use app::obj;
use app::obj::Updateable;
use super::*;
use app::obj::{Solid, Geometry, Transformable};
use app::world;
use std::collections::HashMap;
use std::f64::consts;

struct CreatureData;

impl UserDataTypes for CreatureData {
	type BodyData = world::CreatureRefs;
    type JointData = ();
    type FixtureData = world::CreatureRefs;
}

pub struct PhysicsSystem {
	edge: f32,
	world: b2::World<CreatureData>,
	handles: HashMap<world::CreatureRefs, b2::BodyHandle>,
	dropped: Vec<world::CreatureRefs>,
}

impl Updateable for PhysicsSystem {
	fn update(&mut self, dt: f32) {
		let world = &mut self.world;
		world.step(dt, 8, 3);
		const MAX_RADIUS: f32 = 5.0;
		let mut v = Vec::new();
		self.dropped.clear();
		// TODO: is this the best way to iterate?
		for (h, b) in world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			let key = (*body).user_data().clone();
			if position.y < (self.edge - MAX_RADIUS) {
				v.push(h);
				self.dropped.push(key);
			}
		}
		for h in v {
			world.destroy_body(h);
		}
		for key in &self.dropped {
			self.handles.remove(&key);
		}
	}
}

impl System for PhysicsSystem {
	fn register(&mut self, creature: &world::Creature) {
		let world = &mut self.world;
		let object_id = creature.id();

		let mut joint_body: Option<b2::BodyHandle> = None;
		let mut joint_limb: Option<b2::BodyHandle> = None;

		for (limb_index, limb) in creature.limbs().enumerate() {
			let material = limb.material();
			let mut f_def = b2::FixtureDef::new();
			f_def.density = material.density;
			f_def.restitution = material.restitution;
			f_def.friction = material.friction;

			let transform = limb.transform();
			let mut b_def = b2::BodyDef::new();
			b_def.body_type = b2::BodyType::Dynamic;
			b_def.position = b2::Vec2 {
				x: transform.position.x,
				y: transform.position.y,
			};
			let refs = world::CreatureRefs::with_limb(object_id, limb_index as u8);
			let handle = world.create_body_with(&b_def, refs);

			let mesh = limb.mesh();

			match mesh.shape {
				obj::Shape::Ball { radius } => {
					let mut circle_shape = b2::CircleShape::new();
					circle_shape.set_radius(radius);
					world.body_mut(handle).create_fixture_with(&circle_shape, &mut f_def, refs);
				}
				obj::Shape::Box { width, height } => {
					let mut rect_shape = b2::PolygonShape::new();
					rect_shape.set_as_box(width, height);
					world.body_mut(handle).create_fixture_with(&rect_shape, &mut f_def, refs);
				}
				obj::Shape::Star { radius, n, .. } => {
					let p = &mesh.vertices;
					for i in 0..n {
						let mut quad = b2::PolygonShape::new();
						let p1 = p[(i * 2 + 1) as usize];
						let p2 = p[(i * 2) as usize];
						let p3 = p[((i * 2 + (n * 2) - 1) % (n * 2)) as usize];
						quad.set(&[b2::Vec2 { x: 0., y: 0. },
						           b2::Vec2 {
							           x: p1.x * radius,
							           y: p1.y * radius,
						           },
						           b2::Vec2 {
							           x: p2.x * radius,
							           y: p2.y * radius,
						           },
						           b2::Vec2 {
							           x: p3.x * radius,
							           y: p3.y * radius,
						           }]);
						let refs = world::CreatureRefs::with_bone(object_id, limb_index as u8, i as u8);
						world.body_mut(handle).create_fixture_with(&quad, &mut f_def, refs);
					}
				}
				obj::Shape::Triangle { radius, .. } => {
					let p = &mesh.vertices;
					let mut quad = b2::PolygonShape::new();
					let p1 = p[0];
					let p2 = p[2]; // not a typo, we want cw, physics wants ccw
					let p3 = p[1];
					quad.set(&[b2::Vec2 {
						           x: p1.x * radius,
						           y: p1.y * radius,
					           },
					           b2::Vec2 {
						           x: p2.x * radius,
						           y: p2.y * radius,
					           },
					           b2::Vec2 {
						           x: p3.x * radius,
						           y: p3.y * radius,
					           }]);
					world.body_mut(handle).create_fixture_with(&quad, &mut f_def, refs);
				}
			};
			if joint_body == None {
				joint_body = Some(handle);
			} else {
				joint_limb = Some(handle);
			}
			if let (Some(b), Some(l)) = (joint_body, joint_limb) {
				let mut joint = b2::RevoluteJointDef::new(b, l);
				joint.local_anchor_b = b2::Vec2 { x: 0., y: 1. };
				world.create_joint_with(&joint, ());
			}
			self.handles.insert(refs, handle);
		}
	}

	fn to_world(&self, world: &mut world::World) {
		for key in &self.dropped {
			world.friends.kill(&key.creature_id);
			// println!("Killed object: {}", key.creature_id);
		}
		for (_, b) in self.world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			let angle = (*body).angle();
			let key = (*body).user_data();

			if let Some(creature) = world.friends.get_mut(key.creature_id) {
				if let Some(object) = creature.limb_mut(key.limb_index) {
					let scale = object.transform().scale;
					object.transform_to(obj::Transform {
						position: obj::Position {
							x: position.x,
							y: position.y,
						},
						angle: angle,
						scale: scale,
					});
				}
			}
		}
	}
}

impl PhysicsSystem {
	pub fn new() -> Self {
		PhysicsSystem {
			world: Self::new_world(),
			edge: 0.,
			handles: HashMap::new(),
			dropped: Vec::new(),
		}
	}

	pub fn drop_below(&mut self, edge: f32) {
		self.edge = edge;
	}

	fn new_world() -> b2::World<CreatureData> {
		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.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
	}
}
<commit_msg>Tweaked joints<commit_after>use wrapped2d::b2;
use wrapped2d::user_data::*;
use app::obj;
use app::obj::Updateable;
use super::*;
use app::obj::{Solid, Geometry, Transformable};
use app::world;
use std::collections::HashMap;
use std::f64::consts;

struct CreatureData;

impl UserDataTypes for CreatureData {
	type BodyData = world::CreatureRefs;
    type JointData = ();
    type FixtureData = world::CreatureRefs;
}

pub struct PhysicsSystem {
	edge: f32,
	world: b2::World<CreatureData>,
	handles: HashMap<world::CreatureRefs, b2::BodyHandle>,
	dropped: Vec<world::CreatureRefs>,
}

impl Updateable for PhysicsSystem {
	fn update(&mut self, dt: f32) {
		let world = &mut self.world;
		world.step(dt, 8, 3);
		const MAX_RADIUS: f32 = 5.0;
		let mut v = Vec::new();
		self.dropped.clear();
		// TODO: is this the best way to iterate?
		for (h, b) in world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			let key = (*body).user_data().clone();
			if position.y < (self.edge - MAX_RADIUS) {
				v.push(h);
				self.dropped.push(key);
			}
		}
		for h in v {
			world.destroy_body(h);
		}
		for key in &self.dropped {
			self.handles.remove(&key);
		}
	}
}

impl System for PhysicsSystem {
	fn register(&mut self, creature: &world::Creature) {
		let world = &mut self.world;
		let object_id = creature.id();

		let mut joint_body: Option<b2::BodyHandle> = None;
		let mut joint_limb: Option<b2::BodyHandle> = None;

		for (limb_index, limb) in creature.limbs().enumerate() {
			let material = limb.material();
			let mut f_def = b2::FixtureDef::new();
			f_def.density = material.density;
			f_def.restitution = material.restitution;
			f_def.friction = material.friction;

			let transform = limb.transform();
			let mut b_def = b2::BodyDef::new();
			b_def.body_type = b2::BodyType::Dynamic;
			b_def.position = b2::Vec2 {
				x: transform.position.x,
				y: transform.position.y,
			};
			let refs = world::CreatureRefs::with_limb(object_id, limb_index as u8);
			let handle = world.create_body_with(&b_def, refs);

			let mesh = limb.mesh();

			match mesh.shape {
				obj::Shape::Ball { radius } => {
					let mut circle_shape = b2::CircleShape::new();
					circle_shape.set_radius(radius);
					world.body_mut(handle).create_fixture_with(&circle_shape, &mut f_def, refs);
				}
				obj::Shape::Box { width, height } => {
					let mut rect_shape = b2::PolygonShape::new();
					rect_shape.set_as_box(width, height);
					world.body_mut(handle).create_fixture_with(&rect_shape, &mut f_def, refs);
				}
				obj::Shape::Star { radius, n, .. } => {
					let p = &mesh.vertices;
					for i in 0..n {
						let mut quad = b2::PolygonShape::new();
						let p1 = p[(i * 2 + 1) as usize];
						let p2 = p[(i * 2) as usize];
						let p3 = p[((i * 2 + (n * 2) - 1) % (n * 2)) as usize];
						quad.set(&[b2::Vec2 { x: 0., y: 0. },
						           b2::Vec2 {
							           x: p1.x * radius,
							           y: p1.y * radius,
						           },
						           b2::Vec2 {
							           x: p2.x * radius,
							           y: p2.y * radius,
						           },
						           b2::Vec2 {
							           x: p3.x * radius,
							           y: p3.y * radius,
						           }]);
						let refs = world::CreatureRefs::with_bone(object_id, limb_index as u8, i as u8);
						world.body_mut(handle).create_fixture_with(&quad, &mut f_def, refs);
					}
				}
				obj::Shape::Triangle { radius, .. } => {
					let p = &mesh.vertices;
					let mut quad = b2::PolygonShape::new();
					let p1 = p[0];
					let p2 = p[2]; // not a typo, we want cw, physics wants ccw
					let p3 = p[1];
					quad.set(&[b2::Vec2 {
						           x: p1.x * radius,
						           y: p1.y * radius,
					           },
					           b2::Vec2 {
						           x: p2.x * radius,
						           y: p2.y * radius,
					           },
					           b2::Vec2 {
						           x: p3.x * radius,
						           y: p3.y * radius,
					           }]);
					world.body_mut(handle).create_fixture_with(&quad, &mut f_def, refs);
				}
			};
			if joint_body == None {
				joint_body = Some(handle);
			} else {
				joint_limb = Some(handle);
			}
			if let (Some(b), Some(l)) = (joint_body, joint_limb) {
				let mut joint = b2::RevoluteJointDef::new(b, l);
				joint.reference_angle = 1.0;
				joint.local_anchor_b = b2::Vec2 { x: 0., y: 2. };
				world.create_joint_with(&joint, ());
			}
			self.handles.insert(refs, handle);
		}
	}

	fn to_world(&self, world: &mut world::World) {
		for key in &self.dropped {
			world.friends.kill(&key.creature_id);
			// println!("Killed object: {}", key.creature_id);
		}
		for (_, b) in self.world.bodies() {
			let body = b.borrow();
			let position = (*body).position();
			let angle = (*body).angle();
			let key = (*body).user_data();

			if let Some(creature) = world.friends.get_mut(key.creature_id) {
				if let Some(object) = creature.limb_mut(key.limb_index) {
					let scale = object.transform().scale;
					object.transform_to(obj::Transform {
						position: obj::Position {
							x: position.x,
							y: position.y,
						},
						angle: angle,
						scale: scale,
					});
				}
			}
		}
	}
}

impl PhysicsSystem {
	pub fn new() -> Self {
		PhysicsSystem {
			world: Self::new_world(),
			edge: 0.,
			handles: HashMap::new(),
			dropped: Vec::new(),
		}
	}

	pub fn drop_below(&mut self, edge: f32) {
		self.edge = edge;
	}

	fn new_world() -> b2::World<CreatureData> {
		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.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
	}
}
<|endoftext|>


<commit_before>use crate::error::{Error,
                   Result};
use blake2b_simd::{Params,
                   State};
use hex::FromHex;
use serde::Serialize;
use std::{convert::TryInto,
          fmt,
          fs::File,
          io::{BufReader,
               Read},
          path::Path,
          str::FromStr};

/// When hashing byte streams, we'll read 1KB at a time, adding this to the
/// internal hashing state as we compute the final digest.
const BUF_SIZE: usize = 1024;

/// The size of our Blake2b hash digests (32 bytes)
const HASH_DIGEST_SIZE: usize = 32;

/// Convenience wrapper type for a 32-byte Blake2b hash digest.
///
/// Implements secure equality comparison, as well as hex-encoding via
/// `std::fmt::Display`.
///
/// There are intentionally no explicit constructors; to get a
/// instance, you'll need to either convert it directly from a `&[u8]`
/// or parse it from a hex string.
#[derive(Clone, Debug)]
pub struct Blake2bHash {
    digest: [u8; HASH_DIGEST_SIZE],
}

impl Blake2bHash {
    /// Calculate the BLAKE2b hash of the contents of a file.
    pub fn from_file<P>(filename: P) -> Result<Self>
        where P: AsRef<Path>
    {
        let file = File::open(filename.as_ref())?;
        let mut reader = BufReader::new(file);
        Self::from_reader(&mut reader)
    }

    /// Calculate the BLAKE2b hash of a sequence of bytes.
    pub fn from_bytes<B>(data: B) -> Self
        where B: AsRef<[u8]>
    {
        let mut state = hash_state();
        state.update(data.as_ref());
        state.finalize().into()
    }

    /// Calculate the BLAKE2b hash of a Read implentation.
    pub fn from_reader(reader: &mut dyn Read) -> Result<Self> {
        let mut state = hash_state();

        let mut buf = [0u8; BUF_SIZE];
        loop {
            let bytes_read = reader.read(&mut buf)?;
            if bytes_read == 0 {
                break;
            }
            let chunk = &buf[0..bytes_read];
            state.update(chunk);
        }

        Ok(state.finalize().into())
    }
}

// We *could* just wrap the `blake2b_simd::Hash` directly in our
// `Blake2bHash` type, but then we wouldn't be able to parse a
// `Blake2bHash` from a string, because `blake2b_simd::Hash does not
// have that ability. So, we'll just grab the bytes and call it a
// day.
impl From<blake2b_simd::Hash> for Blake2bHash {
    fn from(src: blake2b_simd::Hash) -> Self {
        let digest = src.as_bytes()
                        .try_into()
                        .expect("We know we can safely convert to a byte array");
        Blake2bHash { digest }
    }
}

impl AsRef<[u8]> for Blake2bHash {
    fn as_ref(&self) -> &[u8] { &self.digest }
}

impl PartialEq for Blake2bHash {
    /// Implement secure equality comparison for our hashes here so we
    /// don't have to think about it elsewhere.
    // Strictly speaking, secure equality comparison shouldn't be
    // necessary; however, having a type encapsulate this gives us a
    // convenient way to modify this in the future.
    fn eq(&self, other: &Blake2bHash) -> bool { crate::crypto::secure_eq(self, other) }
}

impl Eq for Blake2bHash {}

impl fmt::Display for Blake2bHash {
    /// Displays a Blake2bHash as a lowercase hex-encoded string.
    ///
    /// Due to historical precedent, the lowercasing *is* significant,
    /// as we sign the lowercase hex-encoded version of a Blake2b
    /// hash, and not simply the Blake2b hash itself, when we sign a
    /// HART file.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // hex::encode currently outputs lowercase strings, but we
        // want to strictly enforce this and guard against any future
        // changes to that crate.
        hex::encode(self).to_lowercase().fmt(f)
    }
}

impl FromStr for Blake2bHash {
    type Err = Error;

    /// Convert a hex-encoded byte string into a Blake2bHash. Ensures
    /// the string represents a byte array of proper length.
    ///
    /// Case of the incoming string is not significant (e.g.,
    /// "DEADBEEF" and "deadbeef" are equivalent).
    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        // FromHex has an implementation for [u8; 32], so this ensures
        // the proper length of bytes... well, that and the compiler,
        // of course :)
        let bytes = FromHex::from_hex(s).map_err(|e| {
                                            Error::CryptoError(format!("Could not parse \
                                                                        Blake2bHash from string: \
                                                                        {}",
                                                                       e))
                                        })?;
        Ok(Self { digest: bytes })
    }
}

impl Serialize for Blake2bHash {
    /// Serializes a `Blake2bHash` according to its `Display`
    /// implementation (i.e., a lowercase hex-encoded string).
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
        where S: serde::Serializer
    {
        serializer.serialize_str(&self.to_string())
    }
}

////////////////////////////////////////////////////////////////////////

/// Initialize the hasher state. In particular, set the digest length
/// to 32 bytes. All hashing functions must use this to ensure
/// consistency!
fn hash_state() -> State {
    let mut params = Params::new();
    params.hash_length(HASH_DIGEST_SIZE);
    params.to_state()
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::crypto::test_support::fixture;

    /// Helper function to create a Blake2bHash directly from a
    /// hex-encoded string.
    fn hash_from_hex(hex: &str) -> Blake2bHash { hex.parse().unwrap() }

    #[test]
    fn strings_can_be_hashed() {
        let message = "supercalifragilisticexpialadocious";
        let expected =
            hash_from_hex("2ca8ebafca7e189de2a36125b92a1db20f393d1e2708f5daa55e51cf05114437");
        let actual = Blake2bHash::from_bytes(message);

        assert_eq!(expected, actual);
    }

    #[test]
    fn bytes_can_be_hashed() {
        let message = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
        let expected =
            hash_from_hex("8b57a796a5d07cb04cc1614dfc2acb3f73edc712d7f433619ca3bbe66bb15f49");
        let actual = Blake2bHash::from_bytes(&message);

        assert_eq!(expected, actual);
    }

    #[test]
    fn hash_file_working() {
        // The expected values were computed using the `b2sum` program from
        // https://github.com/dchest/b2sum using the the `-s=32` option. For example:
        //      b2sum -s=32 signme.dat

        let computed = Blake2bHash::from_file(&fixture("signme.dat")).unwrap();
        let expected =
            hash_from_hex("20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233");
        assert_eq!(computed, expected);

        let computed =
            Blake2bHash::from_file(&fixture("happyhumans-20160424223347.sig.key")).unwrap();
        let expected =
            hash_from_hex("e966844bbc50b7a3a6d81e94dd38e27b92814b944095a8e55f1780921bfcfbe1");
        assert_eq!(computed, expected);

        let computed = Blake2bHash::from_file(&fixture("happyhumans-20160424223347.pub")).unwrap();
        let expected =
            hash_from_hex("b80c4f412f9a0a7727b6e6f115e1b5fa3bae79ad2fcf47f769ed4e42cfb12265");
        assert_eq!(computed, expected);
    }

    #[test]
    #[cfg(feature = "functional")]
    fn hash_file_large_binary() {
        let dir = tempfile::Builder::new().prefix("large_file")
                                          .tempdir()
                                          .unwrap();

        let url = "http://www.kernel.org/pub/linux/kernel/v4.x/linux-4.3.tar.gz";
        let file = dir.path().join(url.rsplit('/').next().unwrap());

        // Download the doc to the temp directory
        let mut f = File::create(&file).unwrap();
        let mut res = reqwest::blocking::get(url).unwrap();
        res.copy_to(&mut f).unwrap();

        let computed = Blake2bHash::from_file(&file).unwrap();
        let expected =
            hash_from_hex("ba640dc063f0ed27e60b38dbb7cf19778cf7805d9fc91eb129fb68b409d46414");
        assert_eq!(computed, expected);
    }

    #[test]
    fn eq() {
        let zeroes = Blake2bHash { digest: [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
                                            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
                                            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], };

        let ones = Blake2bHash { digest: [1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                          1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                          1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8], };

        assert_ne!(zeroes, ones);
        assert_eq!(zeroes, zeroes);
        assert_eq!(ones, ones);
    }

    #[test]
    fn display() {
        let ones = Blake2bHash { digest: [1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                          1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                          1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8], };
        assert_eq!(ones.to_string(),
                   "0101010101010101010101010101010101010101010101010101010101010101");
    }

    #[test]
    fn from_str_good() {
        // Exactly 32 bytes long
        let h = "0101010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
        assert!(h.is_ok());
    }

    #[test]
    fn from_str_short() {
        // This is one byte too short
        let h =
            "01010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
        assert!(h.is_err());
    }
    #[test]
    fn from_str_long() {
        // This is one byte too long
        let h = "010101010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
        assert!(h.is_err());
    }

    #[test]
    fn from_str_case_is_insignificant() {
        let lower_case = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
        let upper_case = "20590A52C4F00588C500328B16D466C982A26FABAA5FA4DCC83052DD0A84F233";

        let l = lower_case.parse::<Blake2bHash>().unwrap();
        let u = upper_case.parse::<Blake2bHash>().unwrap();

        assert_eq!(l, u);
    }

    #[test]
    fn from_str_display_round_trip() {
        let input = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
        let output = input.parse::<Blake2bHash>().unwrap().to_string();
        assert_eq!(output, input);
    }

    #[test]
    fn serialize_as_hex_encoding() {
        let input = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
        let hash: Blake2bHash = input.parse().unwrap();
        serde_test::assert_ser_tokens(&hash, &[serde_test::Token::Str(input)]);
    }
}
<commit_msg>[PR FEEDBACK] Just derive Eq for Blake2bHash<commit_after>use crate::error::{Error,
                   Result};
use blake2b_simd::{Params,
                   State};
use hex::FromHex;
use serde::Serialize;
use std::{convert::TryInto,
          fmt,
          fs::File,
          io::{BufReader,
               Read},
          path::Path,
          str::FromStr};

/// When hashing byte streams, we'll read 1KB at a time, adding this to the
/// internal hashing state as we compute the final digest.
const BUF_SIZE: usize = 1024;

/// The size of our Blake2b hash digests (32 bytes)
const HASH_DIGEST_SIZE: usize = 32;

/// Convenience wrapper type for a 32-byte Blake2b hash digest.
///
/// Implements secure equality comparison, as well as hex-encoding via
/// `std::fmt::Display`.
///
/// There are intentionally no explicit constructors; to get a
/// instance, you'll need to either convert it directly from a `&[u8]`
/// or parse it from a hex string.
#[derive(Clone, Debug, Eq)]
pub struct Blake2bHash {
    digest: [u8; HASH_DIGEST_SIZE],
}

impl Blake2bHash {
    /// Calculate the BLAKE2b hash of the contents of a file.
    pub fn from_file<P>(filename: P) -> Result<Self>
        where P: AsRef<Path>
    {
        let file = File::open(filename.as_ref())?;
        let mut reader = BufReader::new(file);
        Self::from_reader(&mut reader)
    }

    /// Calculate the BLAKE2b hash of a sequence of bytes.
    pub fn from_bytes<B>(data: B) -> Self
        where B: AsRef<[u8]>
    {
        let mut state = hash_state();
        state.update(data.as_ref());
        state.finalize().into()
    }

    /// Calculate the BLAKE2b hash of a Read implentation.
    pub fn from_reader(reader: &mut dyn Read) -> Result<Self> {
        let mut state = hash_state();

        let mut buf = [0u8; BUF_SIZE];
        loop {
            let bytes_read = reader.read(&mut buf)?;
            if bytes_read == 0 {
                break;
            }
            let chunk = &buf[0..bytes_read];
            state.update(chunk);
        }

        Ok(state.finalize().into())
    }
}

// We *could* just wrap the `blake2b_simd::Hash` directly in our
// `Blake2bHash` type, but then we wouldn't be able to parse a
// `Blake2bHash` from a string, because `blake2b_simd::Hash does not
// have that ability. So, we'll just grab the bytes and call it a
// day.
impl From<blake2b_simd::Hash> for Blake2bHash {
    fn from(src: blake2b_simd::Hash) -> Self {
        let digest = src.as_bytes()
                        .try_into()
                        .expect("We know we can safely convert to a byte array");
        Blake2bHash { digest }
    }
}

impl AsRef<[u8]> for Blake2bHash {
    fn as_ref(&self) -> &[u8] { &self.digest }
}

impl PartialEq for Blake2bHash {
    /// Implement secure equality comparison for our hashes here so we
    /// don't have to think about it elsewhere.
    // Strictly speaking, secure equality comparison shouldn't be
    // necessary; however, having a type encapsulate this gives us a
    // convenient way to modify this in the future.
    fn eq(&self, other: &Blake2bHash) -> bool { crate::crypto::secure_eq(self, other) }
}

impl fmt::Display for Blake2bHash {
    /// Displays a Blake2bHash as a lowercase hex-encoded string.
    ///
    /// Due to historical precedent, the lowercasing *is* significant,
    /// as we sign the lowercase hex-encoded version of a Blake2b
    /// hash, and not simply the Blake2b hash itself, when we sign a
    /// HART file.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // hex::encode currently outputs lowercase strings, but we
        // want to strictly enforce this and guard against any future
        // changes to that crate.
        hex::encode(self).to_lowercase().fmt(f)
    }
}

impl FromStr for Blake2bHash {
    type Err = Error;

    /// Convert a hex-encoded byte string into a Blake2bHash. Ensures
    /// the string represents a byte array of proper length.
    ///
    /// Case of the incoming string is not significant (e.g.,
    /// "DEADBEEF" and "deadbeef" are equivalent).
    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        // FromHex has an implementation for [u8; 32], so this ensures
        // the proper length of bytes... well, that and the compiler,
        // of course :)
        let bytes = FromHex::from_hex(s).map_err(|e| {
                                            Error::CryptoError(format!("Could not parse \
                                                                        Blake2bHash from string: \
                                                                        {}",
                                                                       e))
                                        })?;
        Ok(Self { digest: bytes })
    }
}

impl Serialize for Blake2bHash {
    /// Serializes a `Blake2bHash` according to its `Display`
    /// implementation (i.e., a lowercase hex-encoded string).
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
        where S: serde::Serializer
    {
        serializer.serialize_str(&self.to_string())
    }
}

////////////////////////////////////////////////////////////////////////

/// Initialize the hasher state. In particular, set the digest length
/// to 32 bytes. All hashing functions must use this to ensure
/// consistency!
fn hash_state() -> State {
    let mut params = Params::new();
    params.hash_length(HASH_DIGEST_SIZE);
    params.to_state()
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::crypto::test_support::fixture;

    /// Helper function to create a Blake2bHash directly from a
    /// hex-encoded string.
    fn hash_from_hex(hex: &str) -> Blake2bHash { hex.parse().unwrap() }

    #[test]
    fn strings_can_be_hashed() {
        let message = "supercalifragilisticexpialadocious";
        let expected =
            hash_from_hex("2ca8ebafca7e189de2a36125b92a1db20f393d1e2708f5daa55e51cf05114437");
        let actual = Blake2bHash::from_bytes(message);

        assert_eq!(expected, actual);
    }

    #[test]
    fn bytes_can_be_hashed() {
        let message = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
        let expected =
            hash_from_hex("8b57a796a5d07cb04cc1614dfc2acb3f73edc712d7f433619ca3bbe66bb15f49");
        let actual = Blake2bHash::from_bytes(&message);

        assert_eq!(expected, actual);
    }

    #[test]
    fn hash_file_working() {
        // The expected values were computed using the `b2sum` program from
        // https://github.com/dchest/b2sum using the the `-s=32` option. For example:
        //      b2sum -s=32 signme.dat

        let computed = Blake2bHash::from_file(&fixture("signme.dat")).unwrap();
        let expected =
            hash_from_hex("20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233");
        assert_eq!(computed, expected);

        let computed =
            Blake2bHash::from_file(&fixture("happyhumans-20160424223347.sig.key")).unwrap();
        let expected =
            hash_from_hex("e966844bbc50b7a3a6d81e94dd38e27b92814b944095a8e55f1780921bfcfbe1");
        assert_eq!(computed, expected);

        let computed = Blake2bHash::from_file(&fixture("happyhumans-20160424223347.pub")).unwrap();
        let expected =
            hash_from_hex("b80c4f412f9a0a7727b6e6f115e1b5fa3bae79ad2fcf47f769ed4e42cfb12265");
        assert_eq!(computed, expected);
    }

    #[test]
    #[cfg(feature = "functional")]
    fn hash_file_large_binary() {
        let dir = tempfile::Builder::new().prefix("large_file")
                                          .tempdir()
                                          .unwrap();

        let url = "http://www.kernel.org/pub/linux/kernel/v4.x/linux-4.3.tar.gz";
        let file = dir.path().join(url.rsplit('/').next().unwrap());

        // Download the doc to the temp directory
        let mut f = File::create(&file).unwrap();
        let mut res = reqwest::blocking::get(url).unwrap();
        res.copy_to(&mut f).unwrap();

        let computed = Blake2bHash::from_file(&file).unwrap();
        let expected =
            hash_from_hex("ba640dc063f0ed27e60b38dbb7cf19778cf7805d9fc91eb129fb68b409d46414");
        assert_eq!(computed, expected);
    }

    #[test]
    fn eq() {
        let zeroes = Blake2bHash { digest: [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
                                            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
                                            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], };

        let ones = Blake2bHash { digest: [1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                          1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                          1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8], };

        assert_ne!(zeroes, ones);
        assert_eq!(zeroes, zeroes);
        assert_eq!(ones, ones);
    }

    #[test]
    fn display() {
        let ones = Blake2bHash { digest: [1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                          1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                          1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8], };
        assert_eq!(ones.to_string(),
                   "0101010101010101010101010101010101010101010101010101010101010101");
    }

    #[test]
    fn from_str_good() {
        // Exactly 32 bytes long
        let h = "0101010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
        assert!(h.is_ok());
    }

    #[test]
    fn from_str_short() {
        // This is one byte too short
        let h =
            "01010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
        assert!(h.is_err());
    }
    #[test]
    fn from_str_long() {
        // This is one byte too long
        let h = "010101010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
        assert!(h.is_err());
    }

    #[test]
    fn from_str_case_is_insignificant() {
        let lower_case = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
        let upper_case = "20590A52C4F00588C500328B16D466C982A26FABAA5FA4DCC83052DD0A84F233";

        let l = lower_case.parse::<Blake2bHash>().unwrap();
        let u = upper_case.parse::<Blake2bHash>().unwrap();

        assert_eq!(l, u);
    }

    #[test]
    fn from_str_display_round_trip() {
        let input = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
        let output = input.parse::<Blake2bHash>().unwrap().to_string();
        assert_eq!(output, input);
    }

    #[test]
    fn serialize_as_hex_encoding() {
        let input = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
        let hash: Blake2bHash = input.parse().unwrap();
        serde_test::assert_ser_tokens(&hash, &[serde_test::Token::Str(input)]);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::WebSocketBinding;
use dom::bindings::codegen::Bindings::WebSocketBinding::WebSocketMethods;
use dom::bindings::codegen::Bindings::WebSocketBinding::WebSocketConstants;
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{Temporary, JSRef};
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::eventtarget::{EventTarget, EventTargetHelpers, WebSocketTypeId};
use servo_net::resource_task::{Load, LoadData, LoadResponse};
use servo_util::str::DOMString;
use std::ascii::IntoBytes;
use std::comm::channel;
use url::Url;

#[dom_struct]
pub struct WebSocket {
    eventtarget: EventTarget,
    url: DOMString,
    response: LoadResponse,
    state: u16
}

impl WebSocket {
    pub fn new_inherited(url: DOMString, resp: LoadResponse, state_value: u16) -> WebSocket {
        WebSocket {
            eventtarget: EventTarget::new_inherited(WebSocketTypeId),
            url: url,
            response: resp,
            state: state_value
        }
    }

    pub fn new(global: &GlobalRef, url: DOMString) -> Temporary<WebSocket> {
        let resource_task = global.resource_task();
        let ws_url = Url::parse(url.as_slice()).unwrap();
        let(start_chan, start_port) = channel();
        resource_task.send(Load(LoadData::new(ws_url), start_chan));
        let resp = start_port.recv();
        reflect_dom_object(box WebSocket::new_inherited(url, resp, WebSocketConstants::OPEN),
                           global,
                           WebSocketBinding::Wrap)
    }

    pub fn Constructor(global: &GlobalRef, url: DOMString) -> Fallible<Temporary<WebSocket>> {
        Ok(WebSocket::new(global, url))
    }

}

impl Reflectable for WebSocket {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.eventtarget.reflector()
    }
}

impl<'a> WebSocketMethods for JSRef<'a, WebSocket> {
    event_handler!(open, GetOnopen, SetOnopen)
    event_handler!(error, GetOnerror, SetOnerror)
    event_handler!(close, GetOnclose, SetOnclose)
    event_handler!(message, GetOnmessage, SetOnmessage)

    fn Send(self, message: DOMString) -> ()
    {
        let message1: Vec<u8>;
        message1=message.to_string().into_bytes();
        let payload_len = message.len() as u8;
        let entry1=129 as u8;
        let mut payload: Vec<u8> = Vec::with_capacity(2+message1.len());
        payload.push(entry1);
        payload.push(payload_len);
        for x in message1.iter() {
            payload.push(*x);
        }
    }

    fn Url(self) -> DOMString {
        self.url.clone()
    }
}
<commit_msg>addressing comments for changes in the send method in websocket.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::WebSocketBinding;
use dom::bindings::codegen::Bindings::WebSocketBinding::WebSocketMethods;
use dom::bindings::codegen::Bindings::WebSocketBinding::WebSocketConstants;
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{Temporary, JSRef};
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::eventtarget::{EventTarget, EventTargetHelpers, WebSocketTypeId};
use servo_net::resource_task::{Load, LoadData, LoadResponse};
use servo_util::str::DOMString;
use std::ascii::IntoBytes;
use std::comm::channel;
use url::Url;

#[dom_struct]
pub struct WebSocket {
    eventtarget: EventTarget,
    url: DOMString,
    response: LoadResponse,
    state: u16
}

impl WebSocket {
    pub fn new_inherited(url: DOMString, resp: LoadResponse, state_value: u16) -> WebSocket {
        WebSocket {
            eventtarget: EventTarget::new_inherited(WebSocketTypeId),
            url: url,
            response: resp,
            state: state_value
        }
    }

    pub fn new(global: &GlobalRef, url: DOMString) -> Temporary<WebSocket> {
        let resource_task = global.resource_task();
        let ws_url = Url::parse(url.as_slice()).unwrap();
        let(start_chan, start_port) = channel();
        resource_task.send(Load(LoadData::new(ws_url), start_chan));
        let resp = start_port.recv();
        reflect_dom_object(box WebSocket::new_inherited(url, resp, WebSocketConstants::OPEN),
                           global,
                           WebSocketBinding::Wrap)
    }

    pub fn Constructor(global: &GlobalRef, url: DOMString) -> Fallible<Temporary<WebSocket>> {
        Ok(WebSocket::new(global, url))
    }

}

impl Reflectable for WebSocket {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.eventtarget.reflector()
    }
}

impl<'a> WebSocketMethods for JSRef<'a, WebSocket> {
    event_handler!(open, GetOnopen, SetOnopen)
    event_handler!(error, GetOnerror, SetOnerror)
    event_handler!(close, GetOnclose, SetOnclose)
    event_handler!(message, GetOnmessage, SetOnmessage)

    fn Send(self, message: DOMString)
    {
        let message_u8: Vec<u8>=message.to_string().into_bytes();
//        assert_gt!((message.len() as u8),  125);
        let mut payload: Vec<u8> = Vec::with_capacity(2 + message_u8.len());
        payload.push(129u8);
        payload.push(message.len() as u8);
        payload.push_all(message_u8.as_slice());
    }

    fn Url(self) -> DOMString {
        self.url.clone()
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.

use crate::callback::must_call;
use futures::channel::mpsc;
use futures::channel::oneshot as futures_oneshot;
use futures::future::{self, BoxFuture, Future, FutureExt, TryFutureExt};
use futures::stream::{Stream, StreamExt};
use futures::task::{self, ArcWake, Context, Poll};

use std::sync::{Arc, Mutex};

/// Generates a paired future and callback so that when callback is being called, its result
/// is automatically passed as a future result.
pub fn paired_future_callback<T>() -> (Box<dyn FnOnce(T) + Send>, futures_oneshot::Receiver<T>)
where
    T: Send + 'static,
{
    let (tx, future) = futures_oneshot::channel::<T>();
    let callback = Box::new(move |result| {
        let r = tx.send(result);
        if r.is_err() {
            warn!("paired_future_callback: Failed to send result to the future rx, discarded.");
        }
    });
    (callback, future)
}

pub fn paired_must_called_future_callback<T>(
    arg_on_drop: impl FnOnce() -> T + Send + 'static,
) -> (Box<dyn FnOnce(T) + Send>, futures_oneshot::Receiver<T>)
where
    T: Send + 'static,
{
    let (tx, future) = futures_oneshot::channel::<T>();
    let callback = must_call(
        move |result| {
            let r = tx.send(result);
            if r.is_err() {
                warn!("paired_future_callback: Failed to send result to the future rx, discarded.");
            }
        },
        arg_on_drop,
    );
    (callback, future)
}

/// Create a stream proxy with buffer representing the remote stream. The returned task
/// will receive messages from the remote stream as much as possible.
pub fn create_stream_with_buffer<T, S>(
    s: S,
    size: usize,
) -> (
    impl Stream<Item = T> + Send + 'static,
    impl Future<Output = ()> + Send + 'static,
)
where
    S: Stream<Item = T> + Send + 'static,
    T: Send + 'static,
{
    let (tx, rx) = mpsc::channel::<T>(size);
    let driver = s
        .then(future::ok::<T, mpsc::SendError>)
        .forward(tx)
        .map_err(|e| warn!("stream with buffer send error"; "error" => %e))
        .map(|_| ());
    (rx, driver)
}

/// Polls the provided future immediately. If the future is not ready,
/// it will register the waker. When the event is ready, the waker will
/// be notified, then the internal future is immediately polled in the
/// thread calling `wake()`.
pub fn poll_future_notify<F: Future<Output = ()> + Send + 'static>(f: F) {
    let f: BoxFuture<'static, ()> = Box::pin(f);
    let waker = Arc::new(BatchCommandsWaker(Mutex::new(Some(f))));
    waker.wake();
}

// BatchCommandsWaker is used to make business pool notifiy completion queues directly.
struct BatchCommandsWaker(Mutex<Option<BoxFuture<'static, ()>>>);

impl ArcWake for BatchCommandsWaker {
    fn wake_by_ref(arc_self: &Arc<Self>) {
        let mut future_slot = arc_self.0.lock().unwrap();
        if let Some(mut future) = future_slot.take() {
            let waker = task::waker_ref(arc_self);
            let cx = &mut Context::from_waker(&*waker);
            match future.as_mut().poll(cx) {
                Poll::Pending => {
                    *future_slot = Some(future);
                }
                Poll::Ready(()) => {}
            }
        }
    }
}
<commit_msg>tikv_util: reimplement poll_future_notify (#11550)<commit_after>// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.

use crate::callback::must_call;
use futures::channel::mpsc;
use futures::channel::oneshot as futures_oneshot;
use futures::future::{self, BoxFuture, Future, FutureExt, TryFutureExt};
use futures::stream::{Stream, StreamExt};
use futures::task::{self, ArcWake, Context, Poll};

use std::cell::UnsafeCell;
use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc;

/// Generates a paired future and callback so that when callback is being called, its result
/// is automatically passed as a future result.
pub fn paired_future_callback<T>() -> (Box<dyn FnOnce(T) + Send>, futures_oneshot::Receiver<T>)
where
    T: Send + 'static,
{
    let (tx, future) = futures_oneshot::channel::<T>();
    let callback = Box::new(move |result| {
        let r = tx.send(result);
        if r.is_err() {
            warn!("paired_future_callback: Failed to send result to the future rx, discarded.");
        }
    });
    (callback, future)
}

pub fn paired_must_called_future_callback<T>(
    arg_on_drop: impl FnOnce() -> T + Send + 'static,
) -> (Box<dyn FnOnce(T) + Send>, futures_oneshot::Receiver<T>)
where
    T: Send + 'static,
{
    let (tx, future) = futures_oneshot::channel::<T>();
    let callback = must_call(
        move |result| {
            let r = tx.send(result);
            if r.is_err() {
                warn!("paired_future_callback: Failed to send result to the future rx, discarded.");
            }
        },
        arg_on_drop,
    );
    (callback, future)
}

/// Create a stream proxy with buffer representing the remote stream. The returned task
/// will receive messages from the remote stream as much as possible.
pub fn create_stream_with_buffer<T, S>(
    s: S,
    size: usize,
) -> (
    impl Stream<Item = T> + Send + 'static,
    impl Future<Output = ()> + Send + 'static,
)
where
    S: Stream<Item = T> + Send + 'static,
    T: Send + 'static,
{
    let (tx, rx) = mpsc::channel::<T>(size);
    let driver = s
        .then(future::ok::<T, mpsc::SendError>)
        .forward(tx)
        .map_err(|e| warn!("stream with buffer send error"; "error" => %e))
        .map(|_| ());
    (rx, driver)
}

/// Polls the provided future immediately. If the future is not ready,
/// it will register the waker. When the event is ready, the waker will
/// be notified, then the internal future is immediately polled in the
/// thread calling `wake()`.
pub fn poll_future_notify<F: Future<Output = ()> + Send + 'static>(f: F) {
    let f: BoxFuture<'static, ()> = Box::pin(f);
    let poller = Arc::new(PollAtWake {
        f: UnsafeCell::new(Some(f)),
        state: AtomicU8::new(IDLE),
    });
    PollAtWake::poll(&poller)
}

/// The future is not processed by any one.
const IDLE: u8 = 0;
/// The future is being polled by some thread.
const POLLING: u8 = 1;
/// The future is woken when being polled.
const NOTIFIED: u8 = 2;

/// A waker that will poll the future immediately when waking up.
struct PollAtWake {
    f: UnsafeCell<Option<BoxFuture<'static, ()>>>,
    state: AtomicU8,
}

impl PollAtWake {
    fn poll(arc_self: &Arc<PollAtWake>) {
        let mut state = arc_self.state.load(Ordering::Relaxed);
        loop {
            match state {
                IDLE => {
                    match arc_self.state.compare_exchange_weak(
                        IDLE,
                        POLLING,
                        Ordering::SeqCst,
                        Ordering::SeqCst,
                    ) {
                        Ok(_) => break,
                        Err(s) => state = s,
                    }
                }
                POLLING => {
                    match arc_self.state.compare_exchange_weak(
                        POLLING,
                        NOTIFIED,
                        Ordering::SeqCst,
                        Ordering::SeqCst,
                    ) {
                        // The polling thread should poll the future again.
                        Ok(_) => return,
                        Err(s) => state = s,
                    }
                }
                NOTIFIED => {
                    // It will be polled again, so we don't need to do anything here.
                    return;
                }
                _ => panic!("unexpected state {}", state),
            }
        }

        let f = unsafe { &mut *arc_self.f.get() };
        let fut = match f {
            Some(f) => f,
            None => {
                // It can't be `None` for the moment. But it's not a big mistake, just ignore.
                return;
            }
        };

        let waker = task::waker_ref(arc_self);
        let cx = &mut Context::from_waker(&*waker);
        loop {
            match fut.as_mut().poll(cx) {
                // Likely pending
                Poll::Pending => (),
                Poll::Ready(()) => {
                    // We skip updating states here as all future wake should be ignored once
                    // a future is resolved.
                    f.take();
                    return;
                }
            }
            match arc_self
                .state
                .compare_exchange(POLLING, IDLE, Ordering::SeqCst, Ordering::SeqCst)
            {
                Ok(_) => return,
                Err(s) => {
                    if s == NOTIFIED {
                        // Only this thread can change the state from NOTIFIED, so it has to succeed.
                        match arc_self.state.compare_exchange(
                            NOTIFIED,
                            POLLING,
                            Ordering::SeqCst,
                            Ordering::SeqCst,
                        ) {
                            Ok(_) => continue,
                            Err(s) => panic!("unexpected state {}", s),
                        }
                    } else {
                        panic!("unexpcted state {}", s);
                    }
                }
            }
        }
    }
}

// `BoxFuture` is Send, so `PollAtWake` is Send and Sync.
unsafe impl Send for PollAtWake {}
unsafe impl Sync for PollAtWake {}

impl ArcWake for PollAtWake {
    #[inline]
    fn wake_by_ref(arc_self: &Arc<Self>) {
        PollAtWake::poll(arc_self)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use futures::task::Poll;
    use std::sync::atomic::AtomicUsize;

    #[test]
    fn test_in_place_wake() {
        let poll_times = Arc::new(AtomicUsize::new(0));
        let times = poll_times.clone();
        let f = futures::future::poll_fn(move |cx| {
            cx.waker().wake_by_ref();
            let last_time = times.fetch_add(1, Ordering::SeqCst);
            if last_time == 0 {
                Poll::Pending
            } else {
                Poll::Ready(())
            }
        });
        poll_future_notify(f);
        // The future will be woken twice, but only polled twice.
        // The sequence should be:
        // 1. future gets polled
        //   1.1 future gets woken
        //      1.1.1 future marks NOTIFIED
        //   1.2 future returns Poll::Pending
        // 2. future finishes polling, then re-poll
        //   2.1 future gets woken
        //     2.1.1 future marks NOTIFIED
        //   2.2 future returns Poll::Ready
        // 3. future gets ready, ignore NOTIFIED
        assert_eq!(poll_times.load(Ordering::SeqCst), 2);
    }
}
<|endoftext|>


<commit_before>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use engine::EngineData;
use text_renderer::TextRenderer;
use sdl2::pixels::Color;
use std::io::Result;
use std::path::Path;

use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

pub struct AnimScene {
    page: Option<Texture>,
}

impl AnimScene {
    pub fn new<'a>(renderer: &mut Renderer, engine_data: &mut EngineData<'a>) -> BoxedScene<SceneName, EngineData<'a>> {
        Box::new(AnimScene {
            page: None,
        })
    }
}

impl<SceneName, EngineData> Scene<SceneName, EngineData> for AnimScene {
    fn render(&self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        renderer.clear();
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, renderer: &mut Renderer, engine_data: &mut EngineData) -> Option<SceneChangeEvent<SceneName>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
             _ => None
        }
    }
}
<commit_msg>Framework for anim page<commit_after>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use engine::EngineData;
use text_renderer::TextRenderer;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::surface::Surface;
use std::io::Result;
use std::path::Path;
use std::fs::File;

use uorustlibs::anim::{AnimReader};

use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

pub struct AnimScene {
    reader: Result<AnimReader<File>>,
    index: u32,
    page: Option<Texture>,
}

impl AnimScene {
    pub fn new<'a>(renderer: &mut Renderer, engine_data: &mut EngineData<'a>) -> BoxedScene<SceneName, EngineData<'a>> {
        let reader = AnimReader::new(&Path::new("./assets/anim.idx"), &Path::new("./assets/Anim.mul"));  //FIXME: Multiple anim muls!
        let mut scene = Box::new(AnimScene {
            reader: reader,
            index: 0,
            page: None,
        });
        scene.create_slice(renderer, engine_data);

        scene
    }

    fn create_slice(&mut self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        let mut dest = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
        match self.reader {
            Ok(ref mut reader) => {
                match reader.read(self.index) {
                    Ok(anim) => {
                        dest.fill_rect(None, Color::RGB(0, 0, 0)).unwrap();
                        //let surface = gump.to_surface();
                        //surface.blit(None, &mut dest, Some(Rect::new(0, 0, surface.width(), surface.height())));
                        let label = engine_data.text_renderer.create_text(&format!("{}", self.index), Color::RGBA(255, 255, 255, 255));
                        label.blit(None, &mut dest, Some(Rect::new(9, 16, label.width(), label.height())));
                    },
                    _ => {
                        let error = engine_data.text_renderer.create_text("Invalid anim", Color::RGBA(255, 255, 255, 255));
                        error.blit(None, &mut dest, Some(Rect::new(0, 0, error.width(), error.height())));
                        let label = engine_data.text_renderer.create_text(&format!("{}", self.index), Color::RGBA(255, 255, 255, 255));
                        label.blit(None, &mut dest, Some(Rect::new(0, 16, label.width(), label.height())));
                    }
                }
            },
            _ => {
                let error = engine_data.text_renderer.create_text("Could not create slice", Color::RGBA(255, 255, 255, 255));
            }
        }
        self.page = Some(renderer.create_texture_from_surface(&dest).unwrap());
    }
}

impl<'a> Scene<SceneName, EngineData<'a>> for AnimScene {
    fn render(&self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        renderer.clear();
        match self.page {
            Some(ref texture) => {
                renderer.copy(texture, None, None).unwrap();
            },
            None => ()
        };
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, renderer: &mut Renderer, engine_data: &mut EngineData) -> Option<SceneChangeEvent<SceneName>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.index > 0 {
                    self.index -= 1;
                    self.create_slice(renderer, engine_data);
                }
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.index += 1;
                self.create_slice(renderer, engine_data);
                None
            },
             _ => None
        }
    }
}
<|endoftext|>


<commit_before>use serde_json;
use serde_yaml;
use std::{io, net, time};
use std::collections::HashMap;

use lb::WithAddr;

pub fn from_str(mut txt: &str) -> io::Result<AppConfig> {
    txt = txt.trim_left();
    if txt.starts_with('{') {
        serde_json::from_str(txt).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
    } else {
        serde_yaml::from_str(txt).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
    }
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct AppConfig {
    pub proxies: Vec<ProxyConfig>,
    pub buffer_size: Option<usize>,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ProxyConfig {
    pub servers: Vec<ServerConfig>,
    pub namerd: NamerdConfig,
    pub client: Option<ClientConfig>,
    pub max_waiters: Option<usize>,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "kind")]
pub enum ServerConfig {
    #[serde(rename = "io.l5d.tcp")]
    Tcp { addr: net::SocketAddr },

    // TODO support cypher suites
    // TODO support client auth
    // TODO supoprt persistence?
    #[serde(rename = "io.l5d.tls")]
    Tls {
        addr: net::SocketAddr,
        alpn_protocols: Option<Vec<String>>,
        default_identity: Option<TlsServerIdentity>,
        identities: Option<HashMap<String, TlsServerIdentity>>,
    },
}

impl WithAddr for ServerConfig {
    fn addr(&self) -> net::SocketAddr {
        match *self {
            ServerConfig::Tcp { ref addr } |
            ServerConfig::Tls { ref addr, .. } => *addr,
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TlsServerIdentity {
    pub cert_paths: Vec<String>,
    pub private_key_path: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct NamerdConfig {
    pub addr: net::SocketAddr,
    pub path: String,
    pub namespace: Option<String>,
    pub interval: Option<time::Duration>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ClientConfig {
    pub tls: Option<TlsClientConfig>,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TlsClientConfig {
    pub name: String,
    pub trust_cert_paths: Option<Vec<String>>,
}

#[test]
fn parse_simple_yaml() {
    let yaml = "
bufferSize: 1234
proxies:
  - servers:
      - addr: 0.0.0.0:4321
      - addr: 0.0.0.0:4322
    namerd:
      addr: 127.0.0.1:4180
      path: /svc/default
    unknownField: false
";
    let app = from_str(yaml).unwrap();
    assert!(app.buffer_size == Some(1234));
    assert!(app.proxies.len() == 1);
}

#[test]
fn parse_simple_json() {
    let json = "{\"bufferSize\": 1234, \"proxies\": [{\"servers\": [\
                  {\"addr\": \"0.0.0.0:4321\"},{\"addr\": \"0.0.0.0:4322\"}],\
                  \"namerd\": {\"addr\": \"127.0.0.1:4180\", \"path\": \"/svc/default\"}}]}";
    let app = from_str(json).unwrap();
    assert!(app.buffer_size == Some(1234));
    assert!(app.proxies.len() == 1);
}
<commit_msg>update tests<commit_after>use serde_json;
use serde_yaml;
use std::{io, net, time};
use std::collections::HashMap;

use lb::WithAddr;

pub fn from_str(mut txt: &str) -> io::Result<AppConfig> {
    txt = txt.trim_left();
    if txt.starts_with('{') {
        serde_json::from_str(txt).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
    } else {
        serde_yaml::from_str(txt).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
    }
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct AppConfig {
    pub proxies: Vec<ProxyConfig>,
    pub buffer_size: Option<usize>,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ProxyConfig {
    pub servers: Vec<ServerConfig>,
    pub namerd: NamerdConfig,
    pub client: Option<ClientConfig>,
    pub max_waiters: Option<usize>,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "kind")]
pub enum ServerConfig {
    #[serde(rename = "io.l5d.tcp")]
    Tcp { addr: net::SocketAddr },

    // TODO support cypher suites
    // TODO support client auth
    // TODO supoprt persistence?
    #[serde(rename = "io.l5d.tls")]
    Tls {
        addr: net::SocketAddr,
        alpn_protocols: Option<Vec<String>>,
        default_identity: Option<TlsServerIdentity>,
        identities: Option<HashMap<String, TlsServerIdentity>>,
    },
}

impl WithAddr for ServerConfig {
    fn addr(&self) -> net::SocketAddr {
        match *self {
            ServerConfig::Tcp { ref addr } |
            ServerConfig::Tls { ref addr, .. } => *addr,
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TlsServerIdentity {
    pub cert_paths: Vec<String>,
    pub private_key_path: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct NamerdConfig {
    pub addr: net::SocketAddr,
    pub path: String,
    pub namespace: Option<String>,
    pub interval: Option<time::Duration>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ClientConfig {
    pub tls: Option<TlsClientConfig>,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TlsClientConfig {
    pub name: String,
    pub trust_cert_paths: Option<Vec<String>>,
}

#[test]
fn parse_simple_yaml() {
    let yaml = "
bufferSize: 1234
proxies:
  - servers:
      - kind: io.l5d.tcp
        addr: 0.0.0.0:4321
      - kind: io.l5d.tcp
        addr: 0.0.0.0:4322
    namerd:
      addr: 127.0.0.1:4180
      path: /svc/default
    unknownField: false
";
    let app = from_str(yaml).unwrap();
    assert!(app.buffer_size == Some(1234));
    assert!(app.proxies.len() == 1);
}

#[test]
fn parse_simple_json() {
    let json = "{\"bufferSize\":1234, \"proxies\": [{\"servers\": [\
               {\"kind\":\"io.l5d.tcp\", \"addr\":\"0.0.0.0:4321\"},\
               {\"kind\":\"io.l5d.tcp\", \"addr\":\"0.0.0.0:4322\"}],\
               \"namerd\": {\"addr\":\"127.0.0.1:4180\", \"path\":\"/svc/default\"}}]}";
    let app = from_str(json).unwrap();
    assert!(app.buffer_size == Some(1234));
    assert!(app.proxies.len() == 1);
}
<|endoftext|>


<commit_before>#[test]
fn num_cards() {
    let deck = super::Deck::new();
    assert_eq!(deck.cards.len(), 52);
}

#[test]
fn draw_one_card() {
    let mut deck = super::Deck::new();
    let top_card_value = deck.cards.get(51).unwrap().value.clone();
    let top_card_suit = deck.cards.get(51).unwrap().suit.clone();
    let card = deck.draw().unwrap();
    assert_eq!(deck.cards.len(), 51);

    assert!(card.value != ::card::Value::None);
    assert!(card.suit != ::card::Suit::None);

    assert_eq!(card.value, top_card_value);
    assert_eq!(card.suit, top_card_suit);
}

#[test]
fn draw_too_many_cards() {
    let mut deck = super::Deck::new();
    for i in 0..53 {
        let exists = match deck.draw() {
            None    => false,
            Some(_) => true
        };
        if i < 52 {
            assert!(exists);
        } else {
            assert!(!exists);
        }
    }
}
<commit_msg>Updated scoping to use absolute path instead of super<commit_after>#[test]
fn num_cards() {
    let deck = deck::Deck::new();
    assert_eq!(deck.cards.len(), 52);
}

#[test]
fn draw_one_card() {
    let mut deck = deck::Deck::new();
    let top_card_value = deck.cards.get(51).unwrap().value.clone();
    let top_card_suit = deck.cards.get(51).unwrap().suit.clone();
    let card = deck.draw().unwrap();
    assert_eq!(deck.cards.len(), 51);

    assert!(card.value != ::card::Value::None);
    assert!(card.suit != ::card::Suit::None);

    assert_eq!(card.value, top_card_value);
    assert_eq!(card.suit, top_card_suit);
}

#[test]
fn draw_too_many_cards() {
    let mut deck = deck::Deck::new();
    for i in 0..53 {
        let exists = match deck.draw() {
            None    => false,
            Some(_) => true
        };
        if i < 52 {
            assert!(exists);
        } else {
            assert!(!exists);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Till Höppner
//
// 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.

//! Traits and structs for conversion between various formats.
//! As the source format may not provide the same information as the
//! target format, all formats must allow for omittable information.

use std::io::{ BufRead, Write };
use std::borrow::Cow;

use event::Event;
use context::Context;

pub mod weechat3;
pub mod energymech;
pub mod binary;

pub trait Encode<'a, W> where W: Write {
    fn encode(&'a self, context: &'a Context, output: W, event: &'a Event) -> ::Result<()>;
}

pub trait Decode<'a, Input> where Input: BufRead,
                                  Self::Output: Iterator<Item = ::Result<Event<'a>>> + 'a {
    type Output;
    fn decode(&'a mut self, context: &'a Context, input: Input) -> Self::Output;
}

pub trait DecodeBox<'a, I> {
    fn decode_box(&'a mut self, context: &'a Context, input: I)
    -> Box<Iterator<Item = ::Result<Event>> + 'a>;
}

impl<'a, T, I: BufRead> DecodeBox<'a, I> for T where T: Decode<'a, I> {
    fn decode_box(&'a mut self, context: &'a Context, input: I)
    -> Box<Iterator<Item = ::Result<Event>> + 'a> {
        Box::new(self.decode(context, input))
    }
}

fn rejoin(s: &[&str], splits: &[char]) -> Cow<'static, str> {
    let len = s.iter().map(|s| s.len()).sum();
    let mut out = s.iter().zip(splits.iter()).fold(String::with_capacity(len),
        |mut s, (b, &split)| { s.push_str(b); s.push(split); s });
    out.pop(); Cow::Owned(out)
}

fn strip_one(s: &str) -> String {
    if s.len() >= 2 { s[1..(s.len() - 1)].to_owned() } else { String::new() }
}
<commit_msg>Functions to select a decoder/encoder based on a name<commit_after>// Copyright 2015 Till Höppner
//
// 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.

//! Traits and structs for conversion between various formats.
//! As the source format may not provide the same information as the
//! target format, all formats must allow for omittable information.

use std::io::{ BufRead, Write };
use std::borrow::Cow;

use event::Event;
use context::Context;

pub mod weechat3;
pub mod energymech;
pub mod binary;

pub trait Encode<'a, W> where W: Write {
    fn encode(&'a self, context: &'a Context, output: W, event: &'a Event) -> ::Result<()>;
}

pub trait Decode<'a, Input> where Input: BufRead,
                                  Self::Output: Iterator<Item = ::Result<Event<'a>>> + 'a {
    type Output;
    fn decode(&'a mut self, context: &'a Context, input: Input) -> Self::Output;
}

pub trait DecodeBox<'a, I> {
    fn decode_box(&'a mut self, context: &'a Context, input: I)
    -> Box<Iterator<Item = ::Result<Event>> + 'a>;
}

impl<'a, T, I: BufRead> DecodeBox<'a, I> for T where T: Decode<'a, I> {
    fn decode_box(&'a mut self, context: &'a Context, input: I)
    -> Box<Iterator<Item = ::Result<Event>> + 'a> {
        Box::new(self.decode(context, input))
    }
}

pub fn decoder(format: &str) -> Option<Box<DecodeBox<&mut BufRead>>> {
    match format {
        "energymech" => Some(Box::new(energymech::Energymech)),
        "weechat3" => Some(Box::new(weechat3::Weechat3)),
        "binary" => Some(Box::new(binary::Binary)),
        _ => None
    }
}

pub fn encoder(format: &str) -> Option<Box<Encode<&mut Write>>> {
    match format {
        "energymech" => Some(Box::new(energymech::Energymech)),
        "weechat3" => Some(Box::new(weechat3::Weechat3)),
        "binary" => Some(Box::new(binary::Binary)),
        _ => None
    }
}

fn rejoin(s: &[&str], splits: &[char]) -> Cow<'static, str> {
    let len = s.iter().map(|s| s.len()).sum();
    let mut out = s.iter().zip(splits.iter()).fold(String::with_capacity(len),
        |mut s, (b, &split)| { s.push_str(b); s.push(split); s });
    out.pop(); Cow::Owned(out)
}

fn strip_one(s: &str) -> String {
    if s.len() >= 2 { s[1..(s.len() - 1)].to_owned() } else { String::new() }
}
<|endoftext|>


<commit_before>use std::mem::swap;
use std::vec;
use gl;
use color::rgb;
use color::rgb::{ToRGB};
use cgVector = cgmath::vector::Vector;
use cgmath::vector::{Vec2, Vec4};
use cgmath::point::{Point, Point2};
use cgmath::aabb::{Aabb, Aabb2};
use hgl::{Program};
use hgl;
use glfw;
use calx::rectutil::RectUtil;
use stb::image::Image;
use atlas::{Sprite, Atlas};
use recter::Recter;
use recter;
use texture::Texture;
use key;

static COLORED_V: &'static str =
    "#version 130
    in vec3 in_pos;
    in vec2 in_texcoord;
    in vec4 in_color;

    out vec2 texcoord;
    out vec4 color;

    void main(void) {
        texcoord = in_texcoord;
        color = in_color;
        gl_Position = vec4(in_pos, 1.0);
    }
    ";

// Allow opaque shading: All nonzero alpha values are treated as opaque, but
// they also modulate RGB luminance so low alpha means a darker shade.
static ALPHA_SPRITE_F: &'static str =
    "#version 130
    uniform sampler2D textureUnit;
    in vec2 texcoord;
    in vec4 color;

    void main(void) {
        float a = texture(textureUnit, texcoord).w;

        // Color key is gray value 128. This lets us
        // use both blacks and whites in the actual sprites,
        // and keeps the sprite bitmaps easy to read visually.
        // XXX: Looks like I can't do exact compare
        // with colors converted to float.
        // XXX: Also hardcoding this right into the
        // shader is a bit gross.
        if (abs(a * 255 - 128.0) <= 0.1) discard;

        gl_FragColor = vec4(color.x * a, color.y * a, color.z * a, 1.0);
    }
    ";

static BLIT_V: &'static str =
    "#version 130
    in vec2 in_pos;
    in vec2 in_texcoord;

    out vec2 texcoord;

    void main(void) {
        texcoord = in_texcoord;
        gl_Position = vec4(in_pos, 0.0, 1.0);
    }
    ";

static BLIT_F: &'static str =
    "#version 130
    uniform sampler2D textureUnit;
    in vec2 texcoord;

    void main(void) {
        gl_FragColor = texture(textureUnit, texcoord);
    }
    ";

static FONT_DATA: &'static [u8] = include!("../../gen/font_data.rs");
static FONT_SIZE: f32 = 13.0;
static FONT_START_CHAR: uint = 33;
static FONT_NUM_CHARS: uint = 94;
pub static FONT_HEIGHT: f32 = 10.0;
pub static FONT_SPACE: f32 = 5.0;

pub static SPRITE_INDEX_START: uint = FONT_NUM_CHARS + 1;

// TODO: Make a proper type.
pub type Color = Vec4<f32>;

#[deriving(Clone, Eq)]
pub struct KeyEvent {
    // Scancode (ignores local layout)
    code: uint,
    // Printable character (if any)
    ch: Option<char>,
}

#[deriving(Eq, Clone)]
pub struct MouseState {
    pos: Point2<f32>,
    left: bool,
    middle: bool,
    right: bool,
}

pub struct App {
    resolution: Vec2<f32>,
    window: ~glfw::Window,
    alive: bool,
    atlas: ~Atlas,
    sprite_shader: ~Program,
    blit_shader: ~Program,
    recter: Recter,
    key_buffer: ~[KeyEvent],
    // Key input hack flag.
    unknown_key: bool,
}

impl App {
    pub fn new(width: uint, height: uint, title: &str) -> App {
        if !glfw::init().is_ok() {
            fail!("Failed to initialize GLFW");
        }

        let window = glfw::Window::create(width as u32, height as u32, title, glfw::Windowed)
            .expect("Failed to create GLFW window.");
        window.make_context_current();
        window.set_key_polling(true);
        window.set_char_polling(true);

        gl::load_with(glfw::get_proc_address);
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);

        gl::Enable(gl::DEPTH_TEST);
        gl::DepthFunc(gl::LEQUAL);

        gl::Viewport(0, 0, width as i32, height as i32);
        gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

        let mut ret = App {
            resolution: Vec2::new(width as f32, height as f32),
            window: ~window,
            alive: true,
            atlas: ~Atlas::new(),
            sprite_shader:
                ~Program::link(
                    [hgl::Shader::compile(COLORED_V, hgl::VertexShader).unwrap(),
                     hgl::Shader::compile(ALPHA_SPRITE_F, hgl::FragmentShader).unwrap()]
                 ).unwrap(),
            blit_shader:
                ~Program::link(
                    [hgl::Shader::compile(BLIT_V, hgl::VertexShader).unwrap(),
                     hgl::Shader::compile(BLIT_F, hgl::FragmentShader).unwrap()]
                 ).unwrap(),
            recter: Recter::new(),
            key_buffer: ~[],
            unknown_key: false,
        };

        // Hack for solid rectangles, push a solid single-pixel sprite in.
        // Assume this'll end up as position 0.
        ret.atlas.push(~Sprite::new_alpha(
                RectUtil::new(0, 0, 1, 1),
                ~[255u8]));
        ret.atlas.push_ttf(FONT_DATA.to_owned(),
            FONT_SIZE, FONT_START_CHAR, FONT_NUM_CHARS);

        ret
    }

    pub fn add_sprite(&mut self, sprite: ~Sprite) -> uint {
        self.atlas.push(sprite)
    }

    pub fn draw_string<C: ToRGB>(&mut self, offset: &Vec2<f32>, color: &C, text: &str) {
        let first_font_idx = 1;

        let mut offset = *offset;
        for c in text.chars() {
            let i = c as u32;
            if i == 32 {
                // XXX: Space hack.
                offset.add_self_v(&Vec2::new(FONT_SPACE, 0.0));
            } else if i >= FONT_START_CHAR as u32
                && i < (FONT_START_CHAR + FONT_NUM_CHARS) as u32 {
                let spr = self.atlas.get(
                    (first_font_idx + i) as uint - FONT_START_CHAR);
                self.recter.add(
                    &transform_pixel_rect(&self.resolution, &spr.bounds.add_v(&offset)), 0f32,
                    &spr.texcoords, color, 1f32);
                offset.add_self_v(&Vec2::new(spr.bounds.dim().x + 1.0, 0.0));
            }
        }
    }

    pub fn string_bounds(&mut self, text: &str) -> Aabb2<f32> {
        let first_font_idx = 1;

        let mut w = 0f32;
        for c in text.chars() {
            let i = c as u32;
            if i == 32 {
                // XXX: Space hack.
                w = w + FONT_SPACE;
            } else if i >= FONT_START_CHAR as u32
                && i < (FONT_START_CHAR + FONT_NUM_CHARS) as u32 {
                let spr = self.atlas.get(
                    (first_font_idx + i) as uint - FONT_START_CHAR);
                w = w + spr.bounds.dim().x + 1.0;
            }
        }
        RectUtil::new(0f32, 0f32, w, -FONT_HEIGHT)
    }

    pub fn fill_rect<C: ToRGB>(&mut self, rect: &Aabb2<f32>, color: &C) {
        let magic_solid_texture_index = 0;
        self.recter.add(
            &transform_pixel_rect(&self.resolution, rect), 0f32,
            &self.atlas.get(magic_solid_texture_index).texcoords,
            color, 1f32);
    }

    pub fn draw_sprite<C: ToRGB>(&mut self, idx: uint, pos: &Point2<f32>, z: f32, color: &C) {
        let spr = self.atlas.get(idx);
        self.recter.add(
            &transform_pixel_rect(&self.resolution, &spr.bounds.add_v(&pos.to_vec())), z,
            &spr.texcoords, color, 1f32);
    }

    fn render_screen_tex(&mut self) -> Texture {
        let screen_tex = Texture::new_rgba(
            self.resolution.x as uint, self.resolution.y as uint,
            Some(vec::from_elem(
                    (self.resolution.x * self.resolution.y) as uint * 4, 128u8)
                .as_slice()));
        screen_tex.render_to(|| {
            gl::Viewport(0, 0, self.resolution.x as i32, self.resolution.y as i32);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            self.atlas.bind();
            self.recter.render(self.sprite_shader);
        });
        screen_tex
    }

    pub fn flush(&mut self) {
        gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

        // Render-to-texture.
        let screen_tex = ~self.render_screen_tex();
        self.recter.clear();

        let (width, height) = self.window.get_size();
        // XXX Odd dimensions are bad mojo for pixel perfection.
        let (width, height) = (width & !1, height & !1);
        gl::Viewport(0, 0, width, height);

        screen_tex.bind();

        let mut screen_draw = Recter::new();
        let mut bound = recter::screen_bound(&self.resolution, &Vec2::new(width as f32, height as f32));
        // XXX: Degenerate the rectangle to flip y-axis.
        swap(&mut bound.min.y, &mut bound.max.y);
        screen_draw.add(
            &bound, 0f32, &RectUtil::new(0f32, 0f32, 1f32, 1f32), &rgb::consts::WHITE, 1f32);
        screen_draw.render(self.blit_shader);

        self.window.swap_buffers();

        glfw::poll_events();

        // XXX: Dance around the borrow checker...
        let mut queue = ~[];
        for event in self.window.flush_events() {
            queue.push(event);
        }
        for &event in queue.iter() {
            self.handle_event(event);
        }

        if self.window.should_close() {
            self.alive = false
        }
    }

    pub fn screenshot(&mut self, path: &str) {
        let screen_tex = ~self.render_screen_tex();
        let bytes = screen_tex.get_bytes();
        let mut img = Image::new(self.resolution.x as uint, self.resolution.y as uint, 4);
        img.pixels = bytes;
        img.save_png(path);
    }

    fn handle_event(&mut self, (_time, event): (f64, glfw::WindowEvent)) {
        match event {
            glfw::CharEvent(ch) => {
                if !self.unknown_key {
                    if self.key_buffer.len() > 0 {
                        self.key_buffer[self.key_buffer.len() - 1].ch = Some(ch);
                    } else {
                        println!("WARNING: Received char event with no preceding key down event");
                    }
                } else {
                    // Char emitted from a key which App did not recognize.
                    // Emit the print event with code UNKNOWN.
                    self.key_buffer.push(
                        KeyEvent{ code: key::UNKNOWN, ch: Some(ch) });
                }
            },
            glfw::KeyEvent(key, _scan, action, _mods) => {
                if action == glfw::Press || action == glfw::Repeat {
                    match key::translate_glfw_key(key) {
                        Some(key) => {
                            self.key_buffer.push(KeyEvent{ code: key, ch: None });
                            self.unknown_key = false;
                        },
                        None => {
                            self.unknown_key = true;
                        }
                    };
                }
            },
            _ => ()
        };
    }

    pub fn key_buffer(&mut self) -> ~[KeyEvent] {
        let mut ret : ~[KeyEvent] = ~[];
        swap(&mut ret, &mut self.key_buffer);
        ret
    }

    pub fn get_mouse(&self) -> MouseState {
        let (cx, cy) = self.window.get_cursor_pos();
        // XXX: overly complex juggling back and forth the coordinate systems.
        let (width, height) = self.window.get_size();
        let area = Vec2::new(width as f32, height as f32);
        let bounds =
            recter::screen_bound(&self.resolution, &area)
            .add_v(&Vec2::new(1f32, 1f32))
            .mul_s(0.5f32)
            .mul_v(&area);

        MouseState {
            pos: Point2::new(
                     (cx as f32 - bounds.min.x) * (self.resolution.x / bounds.dim().x),
                     (cy as f32 - bounds.min.y) * (self.resolution.y / bounds.dim().y)),
            left: self.window.get_mouse_button(glfw::MouseButtonLeft) != glfw::Release,
            middle: self.window.get_mouse_button(glfw::MouseButtonMiddle) != glfw::Release,
            right: self.window.get_mouse_button(glfw::MouseButtonRight) != glfw::Release,
        }
    }

    pub fn screen_area(&self) -> Aabb2<f32> {
        RectUtil::new(0f32, 0f32, self.resolution.x as f32, self.resolution.y as f32)
    }

    pub fn quit(&mut self) {
        self.alive = false;
    }
}

fn transform_pixel_rect(dim: &Vec2<f32>, rect: &Aabb2<f32>) -> Aabb2<f32> {
    Aabb2::new(
        Point2::new(
            rect.min.x / dim.x * 2.0f32 - 1.0f32,
            rect.min.y / dim.y * 2.0f32 - 1.0f32),
        Point2::new(
            rect.max.x / dim.x * 2.0f32 - 1.0f32,
            rect.max.y / dim.y * 2.0f32 - 1.0f32))
}
<commit_msg>Fix comment on the shader<commit_after>use std::mem::swap;
use std::vec;
use gl;
use color::rgb;
use color::rgb::{ToRGB};
use cgVector = cgmath::vector::Vector;
use cgmath::vector::{Vec2, Vec4};
use cgmath::point::{Point, Point2};
use cgmath::aabb::{Aabb, Aabb2};
use hgl::{Program};
use hgl;
use glfw;
use calx::rectutil::RectUtil;
use stb::image::Image;
use atlas::{Sprite, Atlas};
use recter::Recter;
use recter;
use texture::Texture;
use key;

static COLORED_V: &'static str =
    "#version 130
    in vec3 in_pos;
    in vec2 in_texcoord;
    in vec4 in_color;

    out vec2 texcoord;
    out vec4 color;

    void main(void) {
        texcoord = in_texcoord;
        color = in_color;
        gl_Position = vec4(in_pos, 1.0);
    }
    ";

// Allow opaque shading: All alpha values except the color key are treated as
// opaque, but they also modulate RGB luminance so low alpha means a darker
// shade.
static ALPHA_SPRITE_F: &'static str =
    "#version 130
    uniform sampler2D textureUnit;
    in vec2 texcoord;
    in vec4 color;

    void main(void) {
        float a = texture(textureUnit, texcoord).w;

        // Color key is gray value 128. This lets us
        // use both blacks and whites in the actual sprites,
        // and keeps the sprite bitmaps easy to read visually.
        // XXX: Looks like I can't do exact compare
        // with colors converted to float.
        // XXX: Also hardcoding this right into the
        // shader is a bit gross.
        if (abs(a * 255 - 128.0) <= 0.1) discard;

        gl_FragColor = vec4(color.x * a, color.y * a, color.z * a, 1.0);
    }
    ";

static BLIT_V: &'static str =
    "#version 130
    in vec2 in_pos;
    in vec2 in_texcoord;

    out vec2 texcoord;

    void main(void) {
        texcoord = in_texcoord;
        gl_Position = vec4(in_pos, 0.0, 1.0);
    }
    ";

static BLIT_F: &'static str =
    "#version 130
    uniform sampler2D textureUnit;
    in vec2 texcoord;

    void main(void) {
        gl_FragColor = texture(textureUnit, texcoord);
    }
    ";

static FONT_DATA: &'static [u8] = include!("../../gen/font_data.rs");
static FONT_SIZE: f32 = 13.0;
static FONT_START_CHAR: uint = 33;
static FONT_NUM_CHARS: uint = 94;
pub static FONT_HEIGHT: f32 = 10.0;
pub static FONT_SPACE: f32 = 5.0;

pub static SPRITE_INDEX_START: uint = FONT_NUM_CHARS + 1;

// TODO: Make a proper type.
pub type Color = Vec4<f32>;

#[deriving(Clone, Eq)]
pub struct KeyEvent {
    // Scancode (ignores local layout)
    code: uint,
    // Printable character (if any)
    ch: Option<char>,
}

#[deriving(Eq, Clone)]
pub struct MouseState {
    pos: Point2<f32>,
    left: bool,
    middle: bool,
    right: bool,
}

pub struct App {
    resolution: Vec2<f32>,
    window: ~glfw::Window,
    alive: bool,
    atlas: ~Atlas,
    sprite_shader: ~Program,
    blit_shader: ~Program,
    recter: Recter,
    key_buffer: ~[KeyEvent],
    // Key input hack flag.
    unknown_key: bool,
}

impl App {
    pub fn new(width: uint, height: uint, title: &str) -> App {
        if !glfw::init().is_ok() {
            fail!("Failed to initialize GLFW");
        }

        let window = glfw::Window::create(width as u32, height as u32, title, glfw::Windowed)
            .expect("Failed to create GLFW window.");
        window.make_context_current();
        window.set_key_polling(true);
        window.set_char_polling(true);

        gl::load_with(glfw::get_proc_address);
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);

        gl::Enable(gl::DEPTH_TEST);
        gl::DepthFunc(gl::LEQUAL);

        gl::Viewport(0, 0, width as i32, height as i32);
        gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

        let mut ret = App {
            resolution: Vec2::new(width as f32, height as f32),
            window: ~window,
            alive: true,
            atlas: ~Atlas::new(),
            sprite_shader:
                ~Program::link(
                    [hgl::Shader::compile(COLORED_V, hgl::VertexShader).unwrap(),
                     hgl::Shader::compile(ALPHA_SPRITE_F, hgl::FragmentShader).unwrap()]
                 ).unwrap(),
            blit_shader:
                ~Program::link(
                    [hgl::Shader::compile(BLIT_V, hgl::VertexShader).unwrap(),
                     hgl::Shader::compile(BLIT_F, hgl::FragmentShader).unwrap()]
                 ).unwrap(),
            recter: Recter::new(),
            key_buffer: ~[],
            unknown_key: false,
        };

        // Hack for solid rectangles, push a solid single-pixel sprite in.
        // Assume this'll end up as position 0.
        ret.atlas.push(~Sprite::new_alpha(
                RectUtil::new(0, 0, 1, 1),
                ~[255u8]));
        ret.atlas.push_ttf(FONT_DATA.to_owned(),
            FONT_SIZE, FONT_START_CHAR, FONT_NUM_CHARS);

        ret
    }

    pub fn add_sprite(&mut self, sprite: ~Sprite) -> uint {
        self.atlas.push(sprite)
    }

    pub fn draw_string<C: ToRGB>(&mut self, offset: &Vec2<f32>, color: &C, text: &str) {
        let first_font_idx = 1;

        let mut offset = *offset;
        for c in text.chars() {
            let i = c as u32;
            if i == 32 {
                // XXX: Space hack.
                offset.add_self_v(&Vec2::new(FONT_SPACE, 0.0));
            } else if i >= FONT_START_CHAR as u32
                && i < (FONT_START_CHAR + FONT_NUM_CHARS) as u32 {
                let spr = self.atlas.get(
                    (first_font_idx + i) as uint - FONT_START_CHAR);
                self.recter.add(
                    &transform_pixel_rect(&self.resolution, &spr.bounds.add_v(&offset)), 0f32,
                    &spr.texcoords, color, 1f32);
                offset.add_self_v(&Vec2::new(spr.bounds.dim().x + 1.0, 0.0));
            }
        }
    }

    pub fn string_bounds(&mut self, text: &str) -> Aabb2<f32> {
        let first_font_idx = 1;

        let mut w = 0f32;
        for c in text.chars() {
            let i = c as u32;
            if i == 32 {
                // XXX: Space hack.
                w = w + FONT_SPACE;
            } else if i >= FONT_START_CHAR as u32
                && i < (FONT_START_CHAR + FONT_NUM_CHARS) as u32 {
                let spr = self.atlas.get(
                    (first_font_idx + i) as uint - FONT_START_CHAR);
                w = w + spr.bounds.dim().x + 1.0;
            }
        }
        RectUtil::new(0f32, 0f32, w, -FONT_HEIGHT)
    }

    pub fn fill_rect<C: ToRGB>(&mut self, rect: &Aabb2<f32>, color: &C) {
        let magic_solid_texture_index = 0;
        self.recter.add(
            &transform_pixel_rect(&self.resolution, rect), 0f32,
            &self.atlas.get(magic_solid_texture_index).texcoords,
            color, 1f32);
    }

    pub fn draw_sprite<C: ToRGB>(&mut self, idx: uint, pos: &Point2<f32>, z: f32, color: &C) {
        let spr = self.atlas.get(idx);
        self.recter.add(
            &transform_pixel_rect(&self.resolution, &spr.bounds.add_v(&pos.to_vec())), z,
            &spr.texcoords, color, 1f32);
    }

    fn render_screen_tex(&mut self) -> Texture {
        let screen_tex = Texture::new_rgba(
            self.resolution.x as uint, self.resolution.y as uint,
            Some(vec::from_elem(
                    (self.resolution.x * self.resolution.y) as uint * 4, 128u8)
                .as_slice()));
        screen_tex.render_to(|| {
            gl::Viewport(0, 0, self.resolution.x as i32, self.resolution.y as i32);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            self.atlas.bind();
            self.recter.render(self.sprite_shader);
        });
        screen_tex
    }

    pub fn flush(&mut self) {
        gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

        // Render-to-texture.
        let screen_tex = ~self.render_screen_tex();
        self.recter.clear();

        let (width, height) = self.window.get_size();
        // XXX Odd dimensions are bad mojo for pixel perfection.
        let (width, height) = (width & !1, height & !1);
        gl::Viewport(0, 0, width, height);

        screen_tex.bind();

        let mut screen_draw = Recter::new();
        let mut bound = recter::screen_bound(&self.resolution, &Vec2::new(width as f32, height as f32));
        // XXX: Degenerate the rectangle to flip y-axis.
        swap(&mut bound.min.y, &mut bound.max.y);
        screen_draw.add(
            &bound, 0f32, &RectUtil::new(0f32, 0f32, 1f32, 1f32), &rgb::consts::WHITE, 1f32);
        screen_draw.render(self.blit_shader);

        self.window.swap_buffers();

        glfw::poll_events();

        // XXX: Dance around the borrow checker...
        let mut queue = ~[];
        for event in self.window.flush_events() {
            queue.push(event);
        }
        for &event in queue.iter() {
            self.handle_event(event);
        }

        if self.window.should_close() {
            self.alive = false
        }
    }

    pub fn screenshot(&mut self, path: &str) {
        let screen_tex = ~self.render_screen_tex();
        let bytes = screen_tex.get_bytes();
        let mut img = Image::new(self.resolution.x as uint, self.resolution.y as uint, 4);
        img.pixels = bytes;
        img.save_png(path);
    }

    fn handle_event(&mut self, (_time, event): (f64, glfw::WindowEvent)) {
        match event {
            glfw::CharEvent(ch) => {
                if !self.unknown_key {
                    if self.key_buffer.len() > 0 {
                        self.key_buffer[self.key_buffer.len() - 1].ch = Some(ch);
                    } else {
                        println!("WARNING: Received char event with no preceding key down event");
                    }
                } else {
                    // Char emitted from a key which App did not recognize.
                    // Emit the print event with code UNKNOWN.
                    self.key_buffer.push(
                        KeyEvent{ code: key::UNKNOWN, ch: Some(ch) });
                }
            },
            glfw::KeyEvent(key, _scan, action, _mods) => {
                if action == glfw::Press || action == glfw::Repeat {
                    match key::translate_glfw_key(key) {
                        Some(key) => {
                            self.key_buffer.push(KeyEvent{ code: key, ch: None });
                            self.unknown_key = false;
                        },
                        None => {
                            self.unknown_key = true;
                        }
                    };
                }
            },
            _ => ()
        };
    }

    pub fn key_buffer(&mut self) -> ~[KeyEvent] {
        let mut ret : ~[KeyEvent] = ~[];
        swap(&mut ret, &mut self.key_buffer);
        ret
    }

    pub fn get_mouse(&self) -> MouseState {
        let (cx, cy) = self.window.get_cursor_pos();
        // XXX: overly complex juggling back and forth the coordinate systems.
        let (width, height) = self.window.get_size();
        let area = Vec2::new(width as f32, height as f32);
        let bounds =
            recter::screen_bound(&self.resolution, &area)
            .add_v(&Vec2::new(1f32, 1f32))
            .mul_s(0.5f32)
            .mul_v(&area);

        MouseState {
            pos: Point2::new(
                     (cx as f32 - bounds.min.x) * (self.resolution.x / bounds.dim().x),
                     (cy as f32 - bounds.min.y) * (self.resolution.y / bounds.dim().y)),
            left: self.window.get_mouse_button(glfw::MouseButtonLeft) != glfw::Release,
            middle: self.window.get_mouse_button(glfw::MouseButtonMiddle) != glfw::Release,
            right: self.window.get_mouse_button(glfw::MouseButtonRight) != glfw::Release,
        }
    }

    pub fn screen_area(&self) -> Aabb2<f32> {
        RectUtil::new(0f32, 0f32, self.resolution.x as f32, self.resolution.y as f32)
    }

    pub fn quit(&mut self) {
        self.alive = false;
    }
}

fn transform_pixel_rect(dim: &Vec2<f32>, rect: &Aabb2<f32>) -> Aabb2<f32> {
    Aabb2::new(
        Point2::new(
            rect.min.x / dim.x * 2.0f32 - 1.0f32,
            rect.min.y / dim.y * 2.0f32 - 1.0f32),
        Point2::new(
            rect.max.x / dim.x * 2.0f32 - 1.0f32,
            rect.max.y / dim.y * 2.0f32 - 1.0f32))
}
<|endoftext|>