<commit_before>// Copyright 2018 The Grin Developers
//
// 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.

//! Sane serialization & deserialization of cryptographic structs into hex

use crate::keychain::BlindingFactor;
use crate::serde::{Deserialize, Deserializer, Serializer};
use crate::util::secp::pedersen::{Commitment, RangeProof};
use crate::util::{from_hex, to_hex};

/// Serializes a secp PublicKey to and from hex
pub mod pubkey_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::secp::key::PublicKey;
	use crate::util::{from_hex, static_secp_instance, to_hex};

	///
	pub fn serialize<S>(key: &PublicKey, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		serializer.serialize_str(&to_hex(key.serialize_vec(&static_secp, true).to_vec()))
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<PublicKey, D::Error>
	where
		D: Deserializer<'de>,
	{
		use serde::de::Error;
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		String::deserialize(deserializer)
			.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
			.and_then(|bytes: Vec<u8>| {
				PublicKey::from_slice(&static_secp, &bytes)
					.map_err(|err| Error::custom(err.to_string()))
			})
	}
}

/// Serializes an Option<secp::Signature> to and from hex
pub mod option_sig_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::secp;
	use crate::util::{from_hex, to_hex};
	use serde::de::Error;

	///
	pub fn serialize<S>(sig: &Option<secp::Signature>, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		match sig {
			Some(sig) => serializer.serialize_str(&to_hex(sig.to_raw_data().to_vec())),
			None => serializer.serialize_none(),
		}
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<secp::Signature>, D::Error>
	where
		D: Deserializer<'de>,
	{
		Option::<String>::deserialize(deserializer).and_then(|res| match res {
			Some(string) => from_hex(string.to_string())
				.map_err(|err| Error::custom(err.to_string()))
				.and_then(|bytes: Vec<u8>| {
					let mut b = [0u8; 64];
					b.copy_from_slice(&bytes[0..64]);
					secp::Signature::from_raw_data(&b)
						.map(|val| Some(val))
						.map_err(|err| Error::custom(err.to_string()))
				}),
			None => Ok(None),
		})
	}

}

/// Serializes a secp::Signature to and from hex
pub mod sig_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::secp;
	use crate::util::{from_hex, to_hex};
	use serde::de::Error;

	///
	pub fn serialize<S>(sig: &secp::Signature, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		serializer.serialize_str(&to_hex(sig.to_raw_data().to_vec()))
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<secp::Signature, D::Error>
	where
		D: Deserializer<'de>,
	{
		String::deserialize(deserializer)
			.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
			.and_then(|bytes: Vec<u8>| {
				let mut b = [0u8; 64];
				b.copy_from_slice(&bytes[0..64]);
				secp::Signature::from_raw_data(&b).map_err(|err| Error::custom(err.to_string()))
			})
	}
}

/// Creates a BlindingFactor from a hex string
pub fn blind_from_hex<'de, D>(deserializer: D) -> Result<BlindingFactor, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::Error;
	String::deserialize(deserializer).and_then(|string| {
		BlindingFactor::from_hex(&string).map_err(|err| Error::custom(err.to_string()))
	})
}

/// Creates a RangeProof from a hex string
pub fn rangeproof_from_hex<'de, D>(deserializer: D) -> Result<RangeProof, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::{Error, IntoDeserializer};

	let val = String::deserialize(deserializer)
		.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))?;
	RangeProof::deserialize(val.into_deserializer())
}

/// Creates a Pedersen Commitment from a hex string
pub fn commitment_from_hex<'de, D>(deserializer: D) -> Result<Commitment, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::Error;
	String::deserialize(deserializer)
		.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
		.and_then(|bytes: Vec<u8>| Ok(Commitment::from_vec(bytes.to_vec())))
}

/// Seralizes a byte string into hex
pub fn as_hex<T, S>(bytes: T, serializer: S) -> Result<S::Ok, S::Error>
where
	T: AsRef<[u8]>,
	S: Serializer,
{
	serializer.serialize_str(&to_hex(bytes.as_ref().to_vec()))
}

/// Used to ensure u64s are serialised in json
/// as strings by default, since it can't be guaranteed that consumers
/// will know what to do with u64 literals (e.g. Javascript). However,
/// fields using this tag can be deserialized from literals or strings.
/// From solutions on:
/// https://github.com/serde-rs/json/issues/329
pub mod string_or_u64 {
	use std::fmt;

	use serde::{de, Deserializer, Serializer};

	/// serialize into a string
	pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
	where
		T: fmt::Display,
		S: Serializer,
	{
		serializer.collect_str(value)
	}

	/// deserialize from either literal or string
	pub fn deserialize<'de, D>(deserializer: D) -> Result<u64, D::Error>
	where
		D: Deserializer<'de>,
	{
		struct Visitor;
		impl<'a> de::Visitor<'a> for Visitor {
			type Value = u64;
			fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
				write!(
					formatter,
					"a string containing digits or an int fitting into u64"
				)
			}
			fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
				Ok(v)
			}
			fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				s.parse().map_err(de::Error::custom)
			}
		}
		deserializer.deserialize_any(Visitor)
	}
}

/// As above, for Options
pub mod opt_string_or_u64 {
	use std::fmt;

	use serde::{de, Deserializer, Serializer};

	/// serialize into string or none
	pub fn serialize<T, S>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
	where
		T: fmt::Display,
		S: Serializer,
	{
		match value {
			Some(v) => serializer.collect_str(v),
			None => serializer.serialize_none(),
		}
	}

	/// deser from 'null', literal or string
	pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
	where
		D: Deserializer<'de>,
	{
		struct Visitor;
		impl<'a> de::Visitor<'a> for Visitor {
			type Value = Option<u64>;
			fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
				write!(
					formatter,
					"null, a string containing digits or an int fitting into u64"
				)
			}
			fn visit_unit<E>(self) -> Result<Self::Value, E> {
				Ok(None)
			}
			fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
				Ok(Some(v))
			}
			fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				let val: u64 = s.parse().map_err(de::Error::custom)?;
				Ok(Some(val))
			}
		}
		deserializer.deserialize_any(Visitor)
	}
}

// Test serialization methods of components that are being used
#[cfg(test)]
mod test {
	use super::*;
	use crate::libtx::aggsig;
	use crate::util::secp::key::{PublicKey, SecretKey};
	use crate::util::secp::{Message, Signature};
	use crate::util::static_secp_instance;

	use serde_json;

	use rand::{thread_rng, Rng};

	#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
	struct SerTest {
		#[serde(with = "pubkey_serde")]
		pub pub_key: PublicKey,
		#[serde(with = "option_sig_serde")]
		pub opt_sig: Option<Signature>,
		#[serde(with = "sig_serde")]
		pub sig: Signature,
		#[serde(with = "string_or_u64")]
		pub num: u64,
		#[serde(with = "opt_string_or_u64")]
		pub opt_num: Option<u64>,
	}

	impl SerTest {
		pub fn random() -> SerTest {
			let static_secp = static_secp_instance();
			let secp = static_secp.lock();
			let sk = SecretKey::new(&secp, &mut thread_rng());
			let mut msg = [0u8; 32];
			thread_rng().fill(&mut msg);
			let msg = Message::from_slice(&msg).unwrap();
			let sig = aggsig::sign_single(&secp, &msg, &sk, None, None).unwrap();
			SerTest {
				pub_key: PublicKey::from_secret_key(&secp, &sk).unwrap(),
				opt_sig: Some(sig.clone()),
				sig: sig.clone(),
				num: 30,
				opt_num: Some(33),
			}
		}
	}

	#[test]
	fn ser_secp_primitives() {
		for _ in 0..10 {
			let s = SerTest::random();
			println!("Before Serialization: {:?}", s);
			let serialized = serde_json::to_string_pretty(&s).unwrap();
			println!("JSON: {}", serialized);
			let deserialized: SerTest = serde_json::from_str(&serialized).unwrap();
			println!("After Serialization: {:?}", deserialized);
			println!();
			assert_eq!(s, deserialized);
		}
	}
}
<commit_msg>De/Serialize signatures (for slate consumption) to compressed format rather than raw (#2852)<commit_after>// Copyright 2018 The Grin Developers
//
// 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.

//! Sane serialization & deserialization of cryptographic structs into hex

use crate::keychain::BlindingFactor;
use crate::serde::{Deserialize, Deserializer, Serializer};
use crate::util::secp::pedersen::{Commitment, RangeProof};
use crate::util::{from_hex, to_hex};

/// Serializes a secp PublicKey to and from hex
pub mod pubkey_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::secp::key::PublicKey;
	use crate::util::{from_hex, static_secp_instance, to_hex};

	///
	pub fn serialize<S>(key: &PublicKey, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		serializer.serialize_str(&to_hex(key.serialize_vec(&static_secp, true).to_vec()))
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<PublicKey, D::Error>
	where
		D: Deserializer<'de>,
	{
		use serde::de::Error;
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		String::deserialize(deserializer)
			.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
			.and_then(|bytes: Vec<u8>| {
				PublicKey::from_slice(&static_secp, &bytes)
					.map_err(|err| Error::custom(err.to_string()))
			})
	}
}

/// Serializes an Option<secp::Signature> to and from hex
pub mod option_sig_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::{from_hex, secp, static_secp_instance, to_hex};
	use serde::de::Error;

	///
	pub fn serialize<S>(sig: &Option<secp::Signature>, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		match sig {
			Some(sig) => {
				serializer.serialize_str(&to_hex(sig.serialize_compact(&static_secp).to_vec()))
			}
			None => serializer.serialize_none(),
		}
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<secp::Signature>, D::Error>
	where
		D: Deserializer<'de>,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		Option::<String>::deserialize(deserializer).and_then(|res| match res {
			Some(string) => from_hex(string.to_string())
				.map_err(|err| Error::custom(err.to_string()))
				.and_then(|bytes: Vec<u8>| {
					let mut b = [0u8; 64];
					b.copy_from_slice(&bytes[0..64]);
					secp::Signature::from_compact(&static_secp, &b)
						.map(|val| Some(val))
						.map_err(|err| Error::custom(err.to_string()))
				}),
			None => Ok(None),
		})
	}

}

/// Serializes a secp::Signature to and from hex
pub mod sig_serde {
	use crate::serde::{Deserialize, Deserializer, Serializer};
	use crate::util::{from_hex, secp, static_secp_instance, to_hex};
	use serde::de::Error;

	///
	pub fn serialize<S>(sig: &secp::Signature, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: Serializer,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		serializer.serialize_str(&to_hex(sig.serialize_compact(&static_secp).to_vec()))
	}

	///
	pub fn deserialize<'de, D>(deserializer: D) -> Result<secp::Signature, D::Error>
	where
		D: Deserializer<'de>,
	{
		let static_secp = static_secp_instance();
		let static_secp = static_secp.lock();
		String::deserialize(deserializer)
			.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
			.and_then(|bytes: Vec<u8>| {
				let mut b = [0u8; 64];
				b.copy_from_slice(&bytes[0..64]);
				secp::Signature::from_compact(&static_secp, &b)
					.map_err(|err| Error::custom(err.to_string()))
			})
	}
}

/// Creates a BlindingFactor from a hex string
pub fn blind_from_hex<'de, D>(deserializer: D) -> Result<BlindingFactor, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::Error;
	String::deserialize(deserializer).and_then(|string| {
		BlindingFactor::from_hex(&string).map_err(|err| Error::custom(err.to_string()))
	})
}

/// Creates a RangeProof from a hex string
pub fn rangeproof_from_hex<'de, D>(deserializer: D) -> Result<RangeProof, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::{Error, IntoDeserializer};

	let val = String::deserialize(deserializer)
		.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))?;
	RangeProof::deserialize(val.into_deserializer())
}

/// Creates a Pedersen Commitment from a hex string
pub fn commitment_from_hex<'de, D>(deserializer: D) -> Result<Commitment, D::Error>
where
	D: Deserializer<'de>,
{
	use serde::de::Error;
	String::deserialize(deserializer)
		.and_then(|string| from_hex(string).map_err(|err| Error::custom(err.to_string())))
		.and_then(|bytes: Vec<u8>| Ok(Commitment::from_vec(bytes.to_vec())))
}

/// Seralizes a byte string into hex
pub fn as_hex<T, S>(bytes: T, serializer: S) -> Result<S::Ok, S::Error>
where
	T: AsRef<[u8]>,
	S: Serializer,
{
	serializer.serialize_str(&to_hex(bytes.as_ref().to_vec()))
}

/// Used to ensure u64s are serialised in json
/// as strings by default, since it can't be guaranteed that consumers
/// will know what to do with u64 literals (e.g. Javascript). However,
/// fields using this tag can be deserialized from literals or strings.
/// From solutions on:
/// https://github.com/serde-rs/json/issues/329
pub mod string_or_u64 {
	use std::fmt;

	use serde::{de, Deserializer, Serializer};

	/// serialize into a string
	pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
	where
		T: fmt::Display,
		S: Serializer,
	{
		serializer.collect_str(value)
	}

	/// deserialize from either literal or string
	pub fn deserialize<'de, D>(deserializer: D) -> Result<u64, D::Error>
	where
		D: Deserializer<'de>,
	{
		struct Visitor;
		impl<'a> de::Visitor<'a> for Visitor {
			type Value = u64;
			fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
				write!(
					formatter,
					"a string containing digits or an int fitting into u64"
				)
			}
			fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
				Ok(v)
			}
			fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				s.parse().map_err(de::Error::custom)
			}
		}
		deserializer.deserialize_any(Visitor)
	}
}

/// As above, for Options
pub mod opt_string_or_u64 {
	use std::fmt;

	use serde::{de, Deserializer, Serializer};

	/// serialize into string or none
	pub fn serialize<T, S>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
	where
		T: fmt::Display,
		S: Serializer,
	{
		match value {
			Some(v) => serializer.collect_str(v),
			None => serializer.serialize_none(),
		}
	}

	/// deser from 'null', literal or string
	pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
	where
		D: Deserializer<'de>,
	{
		struct Visitor;
		impl<'a> de::Visitor<'a> for Visitor {
			type Value = Option<u64>;
			fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
				write!(
					formatter,
					"null, a string containing digits or an int fitting into u64"
				)
			}
			fn visit_unit<E>(self) -> Result<Self::Value, E> {
				Ok(None)
			}
			fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
				Ok(Some(v))
			}
			fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				let val: u64 = s.parse().map_err(de::Error::custom)?;
				Ok(Some(val))
			}
		}
		deserializer.deserialize_any(Visitor)
	}
}

// Test serialization methods of components that are being used
#[cfg(test)]
mod test {
	use super::*;
	use crate::libtx::aggsig;
	use crate::util::secp::key::{PublicKey, SecretKey};
	use crate::util::secp::{Message, Signature};
	use crate::util::static_secp_instance;

	use serde_json;

	use rand::{thread_rng, Rng};

	#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
	struct SerTest {
		#[serde(with = "pubkey_serde")]
		pub pub_key: PublicKey,
		#[serde(with = "option_sig_serde")]
		pub opt_sig: Option<Signature>,
		#[serde(with = "sig_serde")]
		pub sig: Signature,
		#[serde(with = "string_or_u64")]
		pub num: u64,
		#[serde(with = "opt_string_or_u64")]
		pub opt_num: Option<u64>,
	}

	impl SerTest {
		pub fn random() -> SerTest {
			let static_secp = static_secp_instance();
			let secp = static_secp.lock();
			let sk = SecretKey::new(&secp, &mut thread_rng());
			let mut msg = [0u8; 32];
			thread_rng().fill(&mut msg);
			let msg = Message::from_slice(&msg).unwrap();
			let sig = aggsig::sign_single(&secp, &msg, &sk, None, None).unwrap();
			SerTest {
				pub_key: PublicKey::from_secret_key(&secp, &sk).unwrap(),
				opt_sig: Some(sig.clone()),
				sig: sig.clone(),
				num: 30,
				opt_num: Some(33),
			}
		}
	}

	#[test]
	fn ser_secp_primitives() {
		for _ in 0..10 {
			let s = SerTest::random();
			println!("Before Serialization: {:?}", s);
			let serialized = serde_json::to_string_pretty(&s).unwrap();
			println!("JSON: {}", serialized);
			let deserialized: SerTest = serde_json::from_str(&serialized).unwrap();
			println!("After Serialization: {:?}", deserialized);
			println!();
			assert_eq!(s, deserialized);
		}
	}
}
<|endoftext|>


<commit_before>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use std::f32;

pub fn is_mrw(buf: &[u8]) -> bool {
  BEu32(buf,0) == 0x004D524D
}

#[derive(Debug, Clone)]
pub struct MrwDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  data_offset: usize,
  raw_width: u16,
  raw_height: u16,
  packed: bool,
  wb_vals: [u16;4],
  tiff: TiffIFD<'a>,
}

impl<'a> MrwDecoder<'a> {
  pub fn new(buf: &'a [u8], rawloader: &'a RawLoader) -> MrwDecoder<'a> {
    let data_offset: usize = (BEu32(buf, 4) + 8) as usize;
    let mut raw_height: u16 = 0;
    let mut raw_width: u16 = 0;
    let mut packed = false;
    let mut wb_vals: [u16;4] = [0;4];
    let mut tiffpos: usize = 0;

    let mut currpos: usize = 8;
    // At most we read 20 bytes from currpos so check we don't step outside that
    while currpos+20 < data_offset {
      let tag: u32 = BEu32(buf,currpos);
      let len: u32 = BEu32(buf,currpos+4);

      match tag {
        0x505244 => { // PRD
          raw_height = BEu16(buf,currpos+16);
          raw_width = BEu16(buf,currpos+18);
          packed = buf[currpos+24] == 12;
        }
        0x574247 => { // WBG
          for i in 0..4 {
            wb_vals[i] = BEu16(buf, currpos+12+i*2);
          }
        }
        0x545457 => { // TTW
          // Base value for offsets needs to be at the beginning of the
          // TIFF block, not the file
          tiffpos = currpos+8;
        }
        _ => {}
      }
      currpos += (len+8) as usize;
    }

    MrwDecoder {
      buffer: buf,
      data_offset: data_offset,
      raw_width: raw_width,
      raw_height: raw_height,
      packed: packed,
      wb_vals: wb_vals,
      tiff: TiffIFD::new(&buf[tiffpos .. buf.len()], 8, 0, BIG_ENDIAN),
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for MrwDecoder<'a> {
  fn identify(&self) -> Result<&Camera, String> {
    let make = match self.tiff.find_entry(Tag::MAKE) {
      Some(val) => val,
      None => return Err("MRW: Couldn't find the maker".to_string()),
    }.get_str();
    let model = match self.tiff.find_entry(Tag::MODEL) {
      Some(val) => val,
      None => return Err("MRW: Couldn't find the model".to_string()),
    }.get_str();

    self.rawloader.check_supported(make, model)
  }

  fn image(&self) -> Result<Image,String> {
    let src = &self.buffer[self.data_offset .. self.buffer.len()];
    let w = self.raw_width as usize;
    let h = self.raw_height as usize;

    let buffer = if self.packed {
      decode_12be(&src, w, h)
    }
    else {
      decode_12be_unpacked(&src, w, h)
    };

    let swapped_wb = false;

    let wb_coeffs = if swapped_wb {
      [self.wb_vals[2] as f32,
       self.wb_vals[0] as f32,
       self.wb_vals[1] as f32,
       f32::NAN]
    } else {
      [self.wb_vals[0] as f32,
       self.wb_vals[1] as f32,
       self.wb_vals[3] as f32,
       f32::NAN]
    };

    let camera = match self.identify() {
      Ok(val) => val,
      Err(e) => {return Err(e)},
    };

    Ok(Image {
      width: self.raw_width as u32,
      height: self.raw_height as u32,
      wb_coeffs: wb_coeffs,
      data: buffer.into_boxed_slice(),
      blacklevels: camera.blacklevels,
      whitelevels: camera.whitelevels,
      color_matrix: camera.color_matrix,
      dcraw_filters: camera.dcraw_filters,
      crops: camera.crops,
    })
  }
}
<commit_msg>MRW: simplify Make/Model error handling<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use std::f32;

pub fn is_mrw(buf: &[u8]) -> bool {
  BEu32(buf,0) == 0x004D524D
}

#[derive(Debug, Clone)]
pub struct MrwDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  data_offset: usize,
  raw_width: u16,
  raw_height: u16,
  packed: bool,
  wb_vals: [u16;4],
  tiff: TiffIFD<'a>,
}

impl<'a> MrwDecoder<'a> {
  pub fn new(buf: &'a [u8], rawloader: &'a RawLoader) -> MrwDecoder<'a> {
    let data_offset: usize = (BEu32(buf, 4) + 8) as usize;
    let mut raw_height: u16 = 0;
    let mut raw_width: u16 = 0;
    let mut packed = false;
    let mut wb_vals: [u16;4] = [0;4];
    let mut tiffpos: usize = 0;

    let mut currpos: usize = 8;
    // At most we read 20 bytes from currpos so check we don't step outside that
    while currpos+20 < data_offset {
      let tag: u32 = BEu32(buf,currpos);
      let len: u32 = BEu32(buf,currpos+4);

      match tag {
        0x505244 => { // PRD
          raw_height = BEu16(buf,currpos+16);
          raw_width = BEu16(buf,currpos+18);
          packed = buf[currpos+24] == 12;
        }
        0x574247 => { // WBG
          for i in 0..4 {
            wb_vals[i] = BEu16(buf, currpos+12+i*2);
          }
        }
        0x545457 => { // TTW
          // Base value for offsets needs to be at the beginning of the
          // TIFF block, not the file
          tiffpos = currpos+8;
        }
        _ => {}
      }
      currpos += (len+8) as usize;
    }

    MrwDecoder {
      buffer: buf,
      data_offset: data_offset,
      raw_width: raw_width,
      raw_height: raw_height,
      packed: packed,
      wb_vals: wb_vals,
      tiff: TiffIFD::new(&buf[tiffpos .. buf.len()], 8, 0, BIG_ENDIAN),
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for MrwDecoder<'a> {
  fn identify(&self) -> Result<&Camera, String> {
    let make = try!(self.tiff.find_entry(Tag::MAKE).ok_or("MRW: Couldn't find Make".to_string())).get_str();
    let model = try!(self.tiff.find_entry(Tag::MODEL).ok_or("MRW: Couldn't find Model".to_string())).get_str();
    self.rawloader.check_supported(make, model)
  }

  fn image(&self) -> Result<Image,String> {
    let src = &self.buffer[self.data_offset .. self.buffer.len()];
    let w = self.raw_width as usize;
    let h = self.raw_height as usize;

    let buffer = if self.packed {
      decode_12be(&src, w, h)
    }
    else {
      decode_12be_unpacked(&src, w, h)
    };

    let swapped_wb = false;

    let wb_coeffs = if swapped_wb {
      [self.wb_vals[2] as f32,
       self.wb_vals[0] as f32,
       self.wb_vals[1] as f32,
       f32::NAN]
    } else {
      [self.wb_vals[0] as f32,
       self.wb_vals[1] as f32,
       self.wb_vals[3] as f32,
       f32::NAN]
    };

    let camera = match self.identify() {
      Ok(val) => val,
      Err(e) => {return Err(e)},
    };

    Ok(Image {
      width: self.raw_width as u32,
      height: self.raw_height as u32,
      wb_coeffs: wb_coeffs,
      data: buffer.into_boxed_slice(),
      blacklevels: camera.blacklevels,
      whitelevels: camera.whitelevels,
      color_matrix: camera.color_matrix,
      dcraw_filters: camera.dcraw_filters,
      crops: camera.crops,
    })
  }
}
<|endoftext|>


<commit_before>// run-pass
// aux-build:span-api-tests.rs
// aux-build:span-test-macros.rs

// ignore-pretty

#![feature(proc_macro_hygiene)]

#[macro_use]
extern crate span_test_macros;

extern crate span_api_tests;

use span_api_tests::{reemit, assert_source_file, macro_stringify};

macro_rules! say_hello {
    ($macname:ident) => ( $macname! { "Hello, world!" })
}

assert_source_file! { "Hello, world!" }

say_hello! { assert_source_file }

reemit_legacy! {
    assert_source_file! { "Hello, world!" }
}

say_hello_extern! { assert_source_file }

reemit! {
    assert_source_file! { "Hello, world!" }
}

fn main() {
    let s = macro_stringify!(Hello, world!);
    assert_eq!(s, "Hello, world!");
    assert_eq!(macro_stringify!(Hello, world!), "Hello, world!");
    assert_eq!(reemit_legacy!(macro_stringify!(Hello, world!)), "Hello, world!");
    reemit_legacy!(assert_eq!(macro_stringify!(Hello, world!), "Hello, world!"));
    // reemit change the span to be that of the call site
    assert_eq!(
        reemit!(macro_stringify!(Hello, world!)),
        "reemit!(macro_stringify!(Hello, world!))"
    );
    let r = "reemit!(assert_eq!(macro_stringify!(Hello, world!), r));";
    reemit!(assert_eq!(macro_stringify!(Hello, world!), r));

    assert_eq!(macro_stringify!(
        Hello,
        world!
    ), "Hello,\n        world!");

    assert_eq!(macro_stringify!(Hello, /*world */ !), "Hello, /*world */ !");
        assert_eq!(macro_stringify!(
        Hello,
        // comment
        world!
    ), "Hello,\n        // comment\n        world!");

    assert_eq!(say_hello! { macro_stringify }, "\"Hello, world!\"");
    assert_eq!(say_hello_extern! { macro_stringify }, "\"Hello, world!\"");
}
<commit_msg>span-api-tests: leave FIXME<commit_after>// run-pass
// aux-build:span-api-tests.rs
// aux-build:span-test-macros.rs

// ignore-pretty

#![feature(proc_macro_hygiene)]

#[macro_use]
extern crate span_test_macros;

extern crate span_api_tests;

// FIXME(69775): Investigate `assert_fake_source_file`.

use span_api_tests::{reemit, assert_source_file, macro_stringify};

macro_rules! say_hello {
    ($macname:ident) => ( $macname! { "Hello, world!" })
}

assert_source_file! { "Hello, world!" }

say_hello! { assert_source_file }

reemit_legacy! {
    assert_source_file! { "Hello, world!" }
}

say_hello_extern! { assert_source_file }

reemit! {
    assert_source_file! { "Hello, world!" }
}

fn main() {
    let s = macro_stringify!(Hello, world!);
    assert_eq!(s, "Hello, world!");
    assert_eq!(macro_stringify!(Hello, world!), "Hello, world!");
    assert_eq!(reemit_legacy!(macro_stringify!(Hello, world!)), "Hello, world!");
    reemit_legacy!(assert_eq!(macro_stringify!(Hello, world!), "Hello, world!"));
    // reemit change the span to be that of the call site
    assert_eq!(
        reemit!(macro_stringify!(Hello, world!)),
        "reemit!(macro_stringify!(Hello, world!))"
    );
    let r = "reemit!(assert_eq!(macro_stringify!(Hello, world!), r));";
    reemit!(assert_eq!(macro_stringify!(Hello, world!), r));

    assert_eq!(macro_stringify!(
        Hello,
        world!
    ), "Hello,\n        world!");

    assert_eq!(macro_stringify!(Hello, /*world */ !), "Hello, /*world */ !");
        assert_eq!(macro_stringify!(
        Hello,
        // comment
        world!
    ), "Hello,\n        // comment\n        world!");

    assert_eq!(say_hello! { macro_stringify }, "\"Hello, world!\"");
    assert_eq!(say_hello_extern! { macro_stringify }, "\"Hello, world!\"");
}
<|endoftext|>


<commit_before>extern crate dominoes;

use CheckResult::*;

type Domino = (usize, usize);

#[derive(Debug)]
enum CheckResult {
    GotInvalid,             // chain returned None
    Correct,
    ChainingFailure(Vec<Domino>), // failure to match the dots at the right side of one domino with
    // the one on the left side of the next
    LengthMismatch(Vec<Domino>),
    DominoMismatch(Vec<Domino>), // different dominoes are used in input and output
}

fn normalize(d: &Domino) -> Domino {
    match d {
        &(m, n) if m > n => (n, m),
        &(m, n) => (m, n)
    }
}

fn check(input: &Vec<Domino>) -> CheckResult {
    let output = match dominoes::chain(input) {
        None => return GotInvalid,
        Some(o) => o
    };
    if input.len() != output.len() {
        return LengthMismatch(output);
    }
    else if input.len() == 0 { // and thus output.len() == 0
        return Correct;
    }

    let mut output_sorted = output.iter().map(|d| normalize(d)).collect::<Vec<Domino>>();
    output_sorted.sort();
    let mut input_sorted = input.iter().map(|d| normalize(d)).collect::<Vec<Domino>>();
    input_sorted.sort();
    if input_sorted != output_sorted {
        return DominoMismatch(output);
    }

    // both input and output have at least 1 element
    // This essentially puts the first element after the last one, thereby making it
    // easy to check whether the domino chains "wraps around".
    let mut fail = false;
    {
        let mut n = output[0].1;
        let iter = output.iter().skip(1).chain(output.iter().take(1));
        for &(first, second) in iter {
            if n != first {
                fail = true;
                break
            }
            n = second
        }
    }
    if fail {
        ChainingFailure(output)
    }
    else {
        Correct
    }
}

fn assert_correct(input: &Vec<Domino>) {
    match check(&input) {
        Correct => (),
        GotInvalid => panic!("Unexpectedly got invalid on input {:?}", input),
        ChainingFailure(output) => panic!("Chaining failure for input {:?}, output {:?}", input, output),
        LengthMismatch(output) => panic!("Length mismatch for input {:?}, output {:?}", input, output),
        DominoMismatch(output) => panic!("Domino mismatch for input {:?}, output {:?}", input, output),
    }
}

#[test]
fn empty_input_empty_output() {
    let input = vec!();
    assert_eq!(dominoes::chain(&input), Some(vec!()));
}

#[test]
#[ignore]
fn singleton_input_singleton_output() {
    let input = vec!((1, 1));
    assert_correct(&input);
}

#[test]
#[ignore]
fn no_repeat_numbers() {
    let input = vec!((1, 2), (3, 1), (2, 3));
    assert_correct(&input);
}

#[test]
#[ignore]
fn invalid_input() {
    let input = vec!((1, 2), (4, 1), (2, 3));
    assert_eq!(dominoes::chain(&input), None);
}

#[test]
#[ignore]
fn ten_elements() {
    let input = vec!((1, 2), (5, 3), (3, 1), (1, 2), (2, 4), (1, 6), (2, 3), (3, 4), (5, 6));
    assert_correct(&input);
}
<commit_msg>dominoes: Add more tests<commit_after>extern crate dominoes;

use CheckResult::*;

type Domino = (usize, usize);

#[derive(Debug)]
enum CheckResult {
    GotInvalid,             // chain returned None
    Correct,
    ChainingFailure(Vec<Domino>), // failure to match the dots at the right side of one domino with
    // the one on the left side of the next
    LengthMismatch(Vec<Domino>),
    DominoMismatch(Vec<Domino>), // different dominoes are used in input and output
}

fn normalize(d: &Domino) -> Domino {
    match d {
        &(m, n) if m > n => (n, m),
        &(m, n) => (m, n)
    }
}

fn check(input: &Vec<Domino>) -> CheckResult {
    let output = match dominoes::chain(input) {
        None => return GotInvalid,
        Some(o) => o
    };
    if input.len() != output.len() {
        return LengthMismatch(output);
    }
    else if input.len() == 0 { // and thus output.len() == 0
        return Correct;
    }

    let mut output_sorted = output.iter().map(|d| normalize(d)).collect::<Vec<Domino>>();
    output_sorted.sort();
    let mut input_sorted = input.iter().map(|d| normalize(d)).collect::<Vec<Domino>>();
    input_sorted.sort();
    if input_sorted != output_sorted {
        return DominoMismatch(output);
    }

    // both input and output have at least 1 element
    // This essentially puts the first element after the last one, thereby making it
    // easy to check whether the domino chains "wraps around".
    let mut fail = false;
    {
        let mut n = output[0].1;
        let iter = output.iter().skip(1).chain(output.iter().take(1));
        for &(first, second) in iter {
            if n != first {
                fail = true;
                break
            }
            n = second
        }
    }
    if fail {
        ChainingFailure(output)
    }
    else {
        Correct
    }
}

fn assert_correct(input: &Vec<Domino>) {
    match check(&input) {
        Correct => (),
        GotInvalid => panic!("Unexpectedly got invalid on input {:?}", input),
        ChainingFailure(output) => panic!("Chaining failure for input {:?}, output {:?}", input, output),
        LengthMismatch(output) => panic!("Length mismatch for input {:?}, output {:?}", input, output),
        DominoMismatch(output) => panic!("Domino mismatch for input {:?}, output {:?}", input, output),
    }
}

#[test]
fn empty_input_empty_output() {
    let input = vec!();
    assert_eq!(dominoes::chain(&input), Some(vec!()));
}

#[test]
#[ignore]
fn singleton_input_singleton_output() {
    let input = vec!((1, 1));
    assert_correct(&input);
}

#[test]
#[ignore]
fn no_repeat_numbers() {
    let input = vec!((1, 2), (3, 1), (2, 3));
    assert_correct(&input);
}

#[test]
#[ignore]
fn can_reverse_dominoes() {
    let input = vec![(1, 2), (1, 3), (2, 3)];
    assert_correct(&input);
}

#[test]
#[ignore]
fn invalid_input() {
    let input = vec!((1, 2), (4, 1), (2, 3));
    assert_eq!(dominoes::chain(&input), None);
}

#[test]
#[ignore]
fn disconnected_simple() {
    let input = vec![(1, 1), (2, 2)];
    assert_eq!(dominoes::chain(&input), None);
}

#[test]
#[ignore]
fn disconnected_double_loop() {
    let input = vec![(1, 2), (2, 1), (3, 4), (4, 3)];
    assert_eq!(dominoes::chain(&input), None);
}

#[test]
#[ignore]
fn disconnected_single_isolated() {
    let input = vec![(1, 2), (2, 3), (3, 1), (4, 4)];
    assert_eq!(dominoes::chain(&input), None);
}

#[test]
#[ignore]
fn need_backtrack() {
    let input = vec![(1, 2), (2, 3), (3, 1), (2, 4), (2, 4)];
    assert_correct(&input);
}

#[test]
#[ignore]
fn separate_loops() {
    let input = vec![(1, 2), (2, 3), (3, 1), (1, 1), (2, 2), (3, 3)];
    assert_correct(&input);
}

#[test]
#[ignore]
fn ten_elements() {
    let input = vec!((1, 2), (5, 3), (3, 1), (1, 2), (2, 4), (1, 6), (2, 3), (3, 4), (5, 6));
    assert_correct(&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/. */

//! Implements traversal over the DOM tree. The traversal starts in sequential
//! mode, and optionally parallelizes as it discovers work.

#![deny(missing_docs)]

use context::{StyleContext, ThreadLocalStyleContext};
use dom::{SendNode, TElement, TNode};
use parallel;
use parallel::{DispatchMode, WORK_UNIT_MAX};
use rayon;
use scoped_tls::ScopedTLS;
use std::collections::VecDeque;
use std::mem;
use time;
use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken};

/// Do a DOM traversal for top-down and (optionally) bottom-up processing,
/// generic over `D`.
///
/// We use an adaptive traversal strategy. We start out with simple sequential
/// processing, until we arrive at a wide enough level in the DOM that the
/// parallel traversal would parallelize it. If a thread pool is provided, we
/// then transfer control over to the parallel traversal.
///
/// Returns true if the traversal was parallel, and also returns the statistics
/// object containing information on nodes traversed (on nightly only). Not
/// all of its fields will be initialized since we don't call finish().
pub fn traverse_dom<E, D>(
    traversal: &D,
    token: PreTraverseToken<E>,
    pool: Option<&rayon::ThreadPool>
)
where
    E: TElement,
    D: DomTraversal<E>,
{
    let root =
        token.traversal_root().expect("Should've ensured we needed to traverse");

    let dump_stats = traversal.shared_context().options.dump_style_statistics;
    let is_nightly  = traversal.shared_context().options.is_nightly();
    let start_time = if dump_stats { Some(time::precise_time_s()) } else { None };

    // Declare the main-thread context, as well as the worker-thread contexts,
    // which we may or may not instantiate. It's important to declare the worker-
    // thread contexts first, so that they get dropped second. This matters because:
    //   * ThreadLocalContexts borrow AtomicRefCells in TLS.
    //   * Dropping a ThreadLocalContext can run SequentialTasks.
    //   * Sequential tasks may call into functions like
    //     Servo_StyleSet_GetBaseComputedValuesForElement, which instantiate a
    //     ThreadLocalStyleContext on the main thread. If the main thread
    //     ThreadLocalStyleContext has not released its TLS borrow by that point,
    //     we'll panic on double-borrow.
    let mut maybe_tls: Option<ScopedTLS<ThreadLocalStyleContext<E>>> = None;
    let mut tlc = ThreadLocalStyleContext::new(traversal.shared_context());
    let mut context = StyleContext {
        shared: traversal.shared_context(),
        thread_local: &mut tlc,
    };

    // Process the nodes breadth-first, just like the parallel traversal does.
    // This helps keep similar traversal characteristics for the style sharing
    // cache.
    let mut discovered =
        VecDeque::<SendNode<E::ConcreteNode>>::with_capacity(WORK_UNIT_MAX * 2);
    let mut depth = root.depth();
    let mut nodes_remaining_at_current_depth = 1;
    discovered.push_back(unsafe { SendNode::new(root.as_node()) });
    while let Some(node) = discovered.pop_front() {
        let mut children_to_process = 0isize;
        let traversal_data = PerLevelTraversalData { current_dom_depth: depth };
        traversal.process_preorder(&traversal_data, &mut context, *node, |n| {
            children_to_process += 1;
            discovered.push_back(unsafe { SendNode::new(n) });
        });

        traversal.handle_postorder_traversal(&mut context, root.as_node().opaque(),
                                             *node, children_to_process);

        nodes_remaining_at_current_depth -= 1;
        if nodes_remaining_at_current_depth == 0 {
            depth += 1;
            // If there is enough work to parallelize over, and the caller allows
            // parallelism, switch to the parallel driver. We do this only when
            // moving to the next level in the dom so that we can pass the same
            // depth for all the children.
            if pool.is_some() && discovered.len() > WORK_UNIT_MAX {
                let pool = pool.unwrap();
                maybe_tls = Some(ScopedTLS::<ThreadLocalStyleContext<E>>::new(pool));
                let root_opaque = root.as_node().opaque();
                let drain = discovered.drain(..);
                pool.install(|| {
                    rayon::scope(|scope| {
                        parallel::traverse_nodes(
                            drain,
                            DispatchMode::TailCall,
                            /* recursion_ok = */ true,
                            root_opaque,
                            PerLevelTraversalData { current_dom_depth: depth },
                            scope,
                            pool,
                            traversal,
                            maybe_tls.as_ref().unwrap()
                        );
                    });
                });
                break;
            }
            nodes_remaining_at_current_depth = discovered.len();
        }
    }
    // Accumulate statistics
    if dump_stats || is_nightly {
        let mut aggregate =
            mem::replace(&mut context.thread_local.statistics, Default::default());
        let parallel = maybe_tls.is_some();
        if let Some(ref mut tls) = maybe_tls {
            let slots = unsafe { tls.unsafe_get() };
            aggregate = slots.iter().fold(aggregate, |acc, t| {
                match *t.borrow() {
                    None => acc,
                    Some(ref cx) => &cx.statistics + &acc,
                }
            });
        }

        // dump to stdout if requested
        if dump_stats && aggregate.is_large_traversal() {
            aggregate.finish(traversal, parallel, start_time.unwrap());
             println!("{}", aggregate);
        }
    }
}
<commit_msg>Stop unconditionally collecting traversal statistics in nightly builds.<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/. */

//! Implements traversal over the DOM tree. The traversal starts in sequential
//! mode, and optionally parallelizes as it discovers work.

#![deny(missing_docs)]

use context::{StyleContext, ThreadLocalStyleContext};
use dom::{SendNode, TElement, TNode};
use parallel;
use parallel::{DispatchMode, WORK_UNIT_MAX};
use rayon;
use scoped_tls::ScopedTLS;
use std::collections::VecDeque;
use std::mem;
use time;
use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken};

/// Do a DOM traversal for top-down and (optionally) bottom-up processing,
/// generic over `D`.
///
/// We use an adaptive traversal strategy. We start out with simple sequential
/// processing, until we arrive at a wide enough level in the DOM that the
/// parallel traversal would parallelize it. If a thread pool is provided, we
/// then transfer control over to the parallel traversal.
///
/// Returns true if the traversal was parallel, and also returns the statistics
/// object containing information on nodes traversed (on nightly only). Not
/// all of its fields will be initialized since we don't call finish().
pub fn traverse_dom<E, D>(
    traversal: &D,
    token: PreTraverseToken<E>,
    pool: Option<&rayon::ThreadPool>
)
where
    E: TElement,
    D: DomTraversal<E>,
{
    let root =
        token.traversal_root().expect("Should've ensured we needed to traverse");

    let dump_stats = traversal.shared_context().options.dump_style_statistics;
    let start_time = if dump_stats { Some(time::precise_time_s()) } else { None };

    // Declare the main-thread context, as well as the worker-thread contexts,
    // which we may or may not instantiate. It's important to declare the worker-
    // thread contexts first, so that they get dropped second. This matters because:
    //   * ThreadLocalContexts borrow AtomicRefCells in TLS.
    //   * Dropping a ThreadLocalContext can run SequentialTasks.
    //   * Sequential tasks may call into functions like
    //     Servo_StyleSet_GetBaseComputedValuesForElement, which instantiate a
    //     ThreadLocalStyleContext on the main thread. If the main thread
    //     ThreadLocalStyleContext has not released its TLS borrow by that point,
    //     we'll panic on double-borrow.
    let mut maybe_tls: Option<ScopedTLS<ThreadLocalStyleContext<E>>> = None;
    let mut tlc = ThreadLocalStyleContext::new(traversal.shared_context());
    let mut context = StyleContext {
        shared: traversal.shared_context(),
        thread_local: &mut tlc,
    };

    // Process the nodes breadth-first, just like the parallel traversal does.
    // This helps keep similar traversal characteristics for the style sharing
    // cache.
    let mut discovered =
        VecDeque::<SendNode<E::ConcreteNode>>::with_capacity(WORK_UNIT_MAX * 2);
    let mut depth = root.depth();
    let mut nodes_remaining_at_current_depth = 1;
    discovered.push_back(unsafe { SendNode::new(root.as_node()) });
    while let Some(node) = discovered.pop_front() {
        let mut children_to_process = 0isize;
        let traversal_data = PerLevelTraversalData { current_dom_depth: depth };
        traversal.process_preorder(&traversal_data, &mut context, *node, |n| {
            children_to_process += 1;
            discovered.push_back(unsafe { SendNode::new(n) });
        });

        traversal.handle_postorder_traversal(&mut context, root.as_node().opaque(),
                                             *node, children_to_process);

        nodes_remaining_at_current_depth -= 1;
        if nodes_remaining_at_current_depth == 0 {
            depth += 1;
            // If there is enough work to parallelize over, and the caller allows
            // parallelism, switch to the parallel driver. We do this only when
            // moving to the next level in the dom so that we can pass the same
            // depth for all the children.
            if pool.is_some() && discovered.len() > WORK_UNIT_MAX {
                let pool = pool.unwrap();
                maybe_tls = Some(ScopedTLS::<ThreadLocalStyleContext<E>>::new(pool));
                let root_opaque = root.as_node().opaque();
                let drain = discovered.drain(..);
                pool.install(|| {
                    rayon::scope(|scope| {
                        parallel::traverse_nodes(
                            drain,
                            DispatchMode::TailCall,
                            /* recursion_ok = */ true,
                            root_opaque,
                            PerLevelTraversalData { current_dom_depth: depth },
                            scope,
                            pool,
                            traversal,
                            maybe_tls.as_ref().unwrap()
                        );
                    });
                });
                break;
            }
            nodes_remaining_at_current_depth = discovered.len();
        }
    }

    // dump statistics to stdout if requested
    if dump_stats {
        let mut aggregate =
            mem::replace(&mut context.thread_local.statistics, Default::default());
        let parallel = maybe_tls.is_some();
        if let Some(ref mut tls) = maybe_tls {
            let slots = unsafe { tls.unsafe_get() };
            aggregate = slots.iter().fold(aggregate, |acc, t| {
                match *t.borrow() {
                    None => acc,
                    Some(ref cx) => &cx.statistics + &acc,
                }
            });
        }

        aggregate.finish(traversal, parallel, start_time.unwrap());
        if aggregate.is_large_traversal() {
             println!("{}", aggregate);
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::process::Command;

#[cfg(not(feature = "rustc-dep-of-std"))]
fn build() {
	let out_dir = env::var("OUT_DIR").unwrap();
	let profile = env::var("PROFILE").expect("PROFILE was not set");

	let _output = Command::new("cargo")
		.current_dir(out_dir.clone())
		.arg("download")
		.arg("--output")
		.arg(out_dir.clone()+"/rusty-hermit")
		.arg("--extract")
		.arg("rusty-hermit")
		.output()
		.expect("Unable to download rusty-hermit. Please install `cargo-download`.");

	if profile == "release" {
		let _output = Command::new("cargo")
			.current_dir(out_dir.clone() + "/rusty-hermit")
			.arg("build")
			.arg("-Z")
			.arg("build-std=core,alloc")
			.arg("--target")
			.arg("x86_64-unknown-hermit-kernel")
			.arg("--release")
			.output()
			.expect("Unable to build kernel");
	} else {
		let _output = Command::new("cargo")
			.current_dir(out_dir.clone() + "/rusty-hermit")
			.arg("build")
			.arg("-Z")
			.arg("build-std=core,alloc")
			.arg("--target")
			.arg("x86_64-unknown-hermit-kernel")
			.output()
			.expect("Unable to build kernel");
	}

	println!(
		"cargo:rustc-link-search=native={}/rusty-hermit/target/x86_64-unknown-hermit-kernel/{}",
		out_dir.clone(),
		profile
	);
	println!("cargo:rustc-link-lib=static=hermit");
}

fn main() {
	#[cfg(not(feature = "rustc-dep-of-std"))]
	build();
}
<commit_msg>minor changes to pass the format check<commit_after>use std::env;
use std::process::Command;

#[cfg(not(feature = "rustc-dep-of-std"))]
fn build() {
	let out_dir = env::var("OUT_DIR").unwrap();
	let profile = env::var("PROFILE").expect("PROFILE was not set");

	let _output = Command::new("cargo")
		.current_dir(out_dir.clone())
		.arg("download")
		.arg("--output")
		.arg(out_dir.clone() + "/rusty-hermit")
		.arg("--extract")
		.arg("rusty-hermit")
		.output()
		.expect("Unable to download rusty-hermit. Please install `cargo-download`.");

	if profile == "release" {
		let _output = Command::new("cargo")
			.current_dir(out_dir.clone() + "/rusty-hermit")
			.arg("build")
			.arg("-Z")
			.arg("build-std=core,alloc")
			.arg("--target")
			.arg("x86_64-unknown-hermit-kernel")
			.arg("--release")
			.output()
			.expect("Unable to build kernel");
	} else {
		let _output = Command::new("cargo")
			.current_dir(out_dir.clone() + "/rusty-hermit")
			.arg("build")
			.arg("-Z")
			.arg("build-std=core,alloc")
			.arg("--target")
			.arg("x86_64-unknown-hermit-kernel")
			.output()
			.expect("Unable to build kernel");
	}

	println!(
		"cargo:rustc-link-search=native={}/rusty-hermit/target/x86_64-unknown-hermit-kernel/{}",
		out_dir.clone(),
		profile
	);
	println!("cargo:rustc-link-lib=static=hermit");
}

fn main() {
	#[cfg(not(feature = "rustc-dep-of-std"))]
	build();
}
<|endoftext|>


<commit_before>use core::{slice, str};

// The size of an ELF header tag, in bytes. This was calculated
// from reading the ELF format specification.
const ELF_SECTION_HEADER_SIZE: u64 = 64;

#[derive(Debug)]
#[repr(C, packed)]
pub struct ElfSectionTag {
    tag_type: u32,
    size: u32,
    num: u32,
    entsize: u32,
    shndx: u16,
    reserved: u16,
    first_section: ElfSectionHeader
}

impl ElfSectionTag {
    pub fn elf_sections(&'static self) -> ElfSectionIter {
        ElfSectionIter {
            current_section: &self.first_section,
            section_index: 0,
            total_sections: self.num as u32,
            entry_size: self.entsize as u64
        }
    }

    pub fn section_count(&self) -> usize {
        self.num as usize
    }

    pub fn size(&self) -> usize {
        self.size as usize
    }

    pub fn entry_size(&self) -> usize {
        self.entsize as usize
    }

    pub fn string_table_index(&self) -> usize {
        self.shndx as usize
    }

    pub fn string_table(&self) -> &'static StringTable {
        let string_table_header = unsafe {
            (&self.first_section as *const ElfSectionHeader).offset(self.shndx as isize)
        };

        let string_table_ptr = unsafe {
            &*((*string_table_header).section_start_address() as *const StringTable)
        };

        string_table_ptr
    }
}

#[derive(Debug)]
#[repr(C)]
pub struct ElfSectionHeader {
    sh_name: u32,
    sh_type: u32,
    sh_flags: u64,
    sh_addr: u64,
    sh_offset: u64,
    sh_size: u64,
    sh_link: u32,
    sh_info: u32,
    sh_addralign: u64,
    sh_entsize: u64
}

impl ElfSectionHeader {
    /// The type of an ELF section.
    pub fn section_type(&self) -> usize {
        self.sh_type as usize
    }

    /// The start address of an ELF section.
    pub fn section_start_address(&self) -> usize {
        self.sh_addr as usize
    }

    /// The end address of an ELF section.
    pub fn section_end_address(&self) -> usize {
        (self.sh_addr + self.sh_size) as usize
    }

    /// The size of an ELF section in bytes.
    pub fn size_bytes(&self) -> usize {
        self.sh_size as usize
    }

    /// ELF section flags.
    pub fn flags(&self) -> usize {
        self.sh_flags as usize
    }

    /// The size of an ELF header entry.
    pub fn entry_size(&self) -> usize {
        self.sh_entsize as usize
    }
}

pub struct ElfSectionIter {
    current_section: &'static ElfSectionHeader,
    section_index: u32,
    total_sections: u32,
    entry_size: u64
}

impl Iterator for ElfSectionIter {
    type Item = &'static ElfSectionHeader;

    fn next(&mut self) -> Option<Self::Item> {
        if self.section_index >= self.total_sections {
            return None;
        } else {
            let section = self.current_section;
            let next_section_addr =
                (self.current_section as *const ElfSectionHeader as u64) + self.entry_size;
            let next_section = unsafe {
                &*(next_section_addr as *const ElfSectionHeader)
            };

            self.current_section = next_section;
            self.section_index += 1;

            Some(section)
        }
    }
}

pub struct StringTable {
    first_char: u8
}

impl StringTable {
    fn section_name(&self, section: &ElfSectionHeader) -> &'static str {
        let string_ptr = unsafe {
            (&self.first_char as *const u8).offset(section.sh_name as isize)
        };

        let string_length = unsafe {
            let mut length = 0;
            let mut current_char = self.first_char;

            while current_char != 0x00 {
                length += 1;
                current_char = *string_ptr.offset(length as isize);
            }

            length
        };

        let string_slice = unsafe {
            slice::from_raw_parts(string_ptr, string_length)
        };

        str::from_utf8(string_slice).unwrap()
    }
}
<commit_msg>Fix bug in section name code where the string parser is initialized to point at the first character in the string table instead of the first character in the name of the Elf Section.<commit_after>use core::{slice, str};

// The size of an ELF header tag, in bytes. This was calculated
// from reading the ELF format specification.
const ELF_SECTION_HEADER_SIZE: u64 = 64;

#[derive(Debug)]
#[repr(C, packed)]
pub struct ElfSectionTag {
    tag_type: u32,
    size: u32,
    num: u32,
    entsize: u32,
    shndx: u16,
    reserved: u16,
    first_section: ElfSectionHeader
}

impl ElfSectionTag {
    pub fn elf_sections(&'static self) -> ElfSectionIter {
        ElfSectionIter {
            current_section: &self.first_section,
            section_index: 0,
            total_sections: self.num as u32,
            entry_size: self.entsize as u64
        }
    }

    pub fn section_count(&self) -> usize {
        self.num as usize
    }

    pub fn size(&self) -> usize {
        self.size as usize
    }

    pub fn entry_size(&self) -> usize {
        self.entsize as usize
    }

    pub fn string_table_index(&self) -> usize {
        self.shndx as usize
    }

    pub fn string_table(&self) -> &'static StringTable {
        let string_table_header = unsafe {
            (&self.first_section as *const ElfSectionHeader).offset(self.shndx as isize)
        };

        let string_table_ptr = unsafe {
            &*((*string_table_header).section_start_address() as *const StringTable)
        };

        string_table_ptr
    }
}

#[derive(Debug)]
#[repr(C)]
pub struct ElfSectionHeader {
    sh_name: u32,
    sh_type: u32,
    sh_flags: u64,
    sh_addr: u64,
    sh_offset: u64,
    sh_size: u64,
    sh_link: u32,
    sh_info: u32,
    sh_addralign: u64,
    sh_entsize: u64
}

impl ElfSectionHeader {
    /// The type of an ELF section.
    pub fn section_type(&self) -> usize {
        self.sh_type as usize
    }

    /// The start address of an ELF section.
    pub fn section_start_address(&self) -> usize {
        self.sh_addr as usize
    }

    /// The end address of an ELF section.
    pub fn section_end_address(&self) -> usize {
        (self.sh_addr + self.sh_size) as usize
    }

    /// The size of an ELF section in bytes.
    pub fn size_bytes(&self) -> usize {
        self.sh_size as usize
    }

    /// ELF section flags.
    pub fn flags(&self) -> usize {
        self.sh_flags as usize
    }

    /// The size of an ELF header entry.
    pub fn entry_size(&self) -> usize {
        self.sh_entsize as usize
    }
}

pub struct ElfSectionIter {
    current_section: &'static ElfSectionHeader,
    section_index: u32,
    total_sections: u32,
    entry_size: u64
}

impl Iterator for ElfSectionIter {
    type Item = &'static ElfSectionHeader;

    fn next(&mut self) -> Option<Self::Item> {
        if self.section_index >= self.total_sections {
            return None;
        } else {
            let section = self.current_section;
            let next_section_addr =
                (self.current_section as *const ElfSectionHeader as u64) + self.entry_size;
            let next_section = unsafe {
                &*(next_section_addr as *const ElfSectionHeader)
            };

            self.current_section = next_section;
            self.section_index += 1;

            Some(section)
        }
    }
}

pub struct StringTable {
    first_char: u8
}

impl StringTable {
    pub fn section_name(&self, section: &ElfSectionHeader) -> &'static str {
        let string_ptr = unsafe {
            (&self.first_char as *const u8).offset(section.sh_name as isize)
        };

        let string_length = unsafe {
            let mut length = 0;
            let mut current_char = *string_ptr.offset(length as isize);

            while current_char != 0x00 {
                length += 1;
                current_char = *string_ptr.offset(length as isize);
            }

            length
        };

        let string_slice = unsafe {
            slice::from_raw_parts(string_ptr, string_length)
        };

        str::from_utf8(string_slice).unwrap()
    }
}
<|endoftext|>


<commit_before>use header::HeaderList;
use header::Header;
use header::ContentLength;
use header::StompHeaderSet;
use std::str::from_utf8;
use frame::{Frame, Transmission};
use std::collections::VecDeque;

pub struct FrameBuffer {
  buffer: VecDeque<u8>,
  parse_state: ParseState
}

struct ParseState {
  offset: u32,
  command: Option<String>,
  headers: HeaderList,
  body: Option<Vec<u8>>,
  section: FrameSection,
}

impl ParseState {
  fn new() -> ParseState {
    ParseState {
      offset: 0,
      command: None,
      headers: header_list![],
      body: None,
      section: FrameSection::Command
    }
  }
}

enum FrameSection {
  Command,
  Headers,
  Body
}

enum ReadCommandResult {
  HeartBeat,
  Command(String),
  Incomplete
}

enum ReadHeaderResult {
  Header(Header),
  EndOfHeaders,
  Incomplete
}

enum ReadBodyResult {
  Body(Vec<u8>),
  Incomplete
}

impl FrameBuffer {
  pub fn new() -> FrameBuffer {
    FrameBuffer {
      buffer: VecDeque::with_capacity(1024 * 65), //TODO: VecDeque?
      parse_state: ParseState::new()
    }
  }

  pub fn len(&self) -> usize {
    self.buffer.len()
  }

  pub fn append(&mut self, bytes: &[u8]) { // TODO: Return result?
    for byte in bytes {
      self.buffer.push_back(*byte);
    }
    debug!("Copied {} bytes into the frame buffer.", bytes.len());
  }

  pub fn read_transmission(&mut self) -> Option<Transmission> {
    match self.parse_state.section {
      FrameSection::Command => self.resume_parsing_at_command(),
      FrameSection::Headers => self.resume_parsing_at_headers(),
      FrameSection::Body    => self.resume_parsing_at_body()
    }
  }

  fn resume_parsing_at_command(&mut self) -> Option<Transmission> {
    debug!("Parsing command.");
    match self.read_command() {
      ReadCommandResult::HeartBeat => Some(Transmission::HeartBeat),
      ReadCommandResult::Command(command_string) => {
        self.parse_state.command = Some(command_string);
        self.parse_state.section = FrameSection::Headers;
        self.resume_parsing_at_headers()
      },
      ReadCommandResult::Incomplete => None
    }
  }

  fn resume_parsing_at_headers(&mut self) -> Option<Transmission> {
    debug!("Parsing headers.");
    match self.read_header() {
      ReadHeaderResult::Header(header) => {
        self.parse_state.headers.push(header);
        self.resume_parsing_at_headers()
      },
      ReadHeaderResult::EndOfHeaders => {
        self.parse_state.section = FrameSection::Body;
        self.resume_parsing_at_body()
      },
      ReadHeaderResult::Incomplete => None
    }
  }

//TODO: Eliminate clone()s
  fn resume_parsing_at_body(&mut self) -> Option<Transmission> {
    debug!("Parsing body.");
    match self.read_body() {
      ReadBodyResult::Body(body_bytes) => {
        //self.parse_state.body = Some(body_bytes);
        let command = match self.parse_state.command {
          Some(ref command) => command.to_string(),
          None => panic!("No COMMAND found.")
        };
        let headers = self.parse_state.headers.clone();
        let body = body_bytes;
        let frame = Frame {
          command: command,
          headers: headers,
          body: body
        };
        self.reset_parse_state();
        Some(Transmission::CompleteFrame(frame))
      },
      ReadBodyResult::Incomplete => None
    }
  }

  fn reset_parse_state(&mut self) {
    self.parse_state.offset = 0;
    self.parse_state.command = None;
    self.parse_state.headers = header_list![];
    self.parse_state.body = None;
    self.parse_state.section = FrameSection::Command;
  }

  // Replace these methods with bridge-buffer concept
  fn read_into_vec(&mut self, n: usize) -> Vec<u8> {
    let mut vec = Vec::with_capacity(n);
    for _ in 0..n {
      let byte = match self.buffer.pop_front() {
        Some(byte) => byte,
        None => panic!("Attempted to read beyond the end of the buffer!")
      };
      vec.push(byte);
    }
    debug!("Removed {} bytes from frame buffer, new size: {}", n, self.buffer.len());
    vec
  }

  // Wasteful with allocations
  fn read_into_string(&mut self, n: usize) -> String {
    let vec = self.read_into_vec(n);
    let string = from_utf8(&vec)
      .ok()
      .expect("Attempted to read a string that was not utf8.");
    return string.to_string();
  }

  fn chomp(mut line: String) -> String {
    // This may be suboptimal, but fine for now
    let chomped_length : usize;
    {
      let chars_to_remove : &[char] = &['\r', '\n'];
      let trimmed_line : &str = line.trim_right_matches(chars_to_remove);
      chomped_length = trimmed_line.len();
    }
    line.truncate(chomped_length);
    line
  }

  fn read_command(&mut self) -> ReadCommandResult {
    use frame_buffer::ReadCommandResult::*;
    //TODO: check for \r\n
    match self.find_next('\n' as u8) {
/*      Some(0) => {
        debug!("Found Heartbeat");
        let num_bytes = 1;
        self.discard(num_bytes);
        HeartBeat
      },
*/
      Some(index) => {
        debug!("Found command ending @ index {}", index);
        let num_bytes = index + 1;
        let command = self.read_into_string(num_bytes as usize);
        let command = FrameBuffer::chomp(command);
        debug!("Chomped length: {}", command.len());
        if command == "" {
          debug!("Found HeartBeat");
          return HeartBeat;
        }
        if command.len() == 1 {
          debug!("Byte: {}", command.as_bytes()[0]);
        }
        debug!("Command -> '{}'", command);
        Command(command)
      },
      None => Incomplete
    }
  }

  fn read_header(&mut self) -> ReadHeaderResult {
    match self.find_next('\n' as u8) {
      Some(index) => {
        debug!("Found header ending @ index {}", index);
        let num_bytes = index + 1;
        let header_string = self.read_into_string(num_bytes as usize);
        let header_string = FrameBuffer::chomp(header_string);
        debug!("Header -> '{}'", header_string);
        if header_string == "" {
          return ReadHeaderResult::EndOfHeaders;
        }
        let header = Header::decode_string(&header_string).expect("Invalid header encountered.");
        ReadHeaderResult::Header(header)
      },
      None => ReadHeaderResult::Incomplete
    }
  }

  // TODO: Need to read both by Content-Length and by null byte
  // This is easier if we've already created the header set
  fn read_body(&mut self) -> ReadBodyResult {
    let maybe_body : Option<Vec<u8>> = match self.parse_state.headers.get_content_length() {
      Some(ContentLength(num_bytes)) => self.read_body_by_content_length(num_bytes as usize),
      None => self.read_body_by_null_octet()
    };
    match maybe_body {
      Some(body) => ReadBodyResult::Body(body),
      None => ReadBodyResult::Incomplete
    }
  }

  fn read_body_by_content_length(&mut self, content_length: usize) -> Option<Vec<u8>> {
    debug!("Reading body by content length.");
    let bytes_needed = content_length + 1; // null octet
    if self.buffer.len() < bytes_needed {
      debug!("Not enough bytes to form body; needed {}, only had {}.", content_length, self.buffer.len());
      return None;
    }
    let mut body = self.read_into_vec(bytes_needed);
    body.pop(); // Discard null octet
    debug!("Body -> '{}'", FrameBuffer::body_as_string(&body));
    Some(body)
  }

  fn read_body_by_null_octet(&mut self) -> Option<Vec<u8>> {
    debug!("Reading body by null octet.");
    match self.find_next(0u8) {
      Some(index) => {
        debug!("Found body ending @ index {}", index);
        let num_bytes = index + 1;
        let mut body = self.read_into_vec(num_bytes as usize);
        body.pop(); // Discard null octet
        debug!("Body -> '{}'", FrameBuffer::body_as_string(&body));
        Some(body)
      },
      None => None
    }
  }

  fn body_as_string(body: &Vec<u8>) -> &str {
    match from_utf8(&body) {
      Ok(ref s) => *s,
      Err(_) => "<Non-utf8 Binary Content>"
    }
  }

  fn find_next(&self, needle: u8) -> Option<u32> {
    let mut step = 0u32;
    for byte in &self.buffer {
      if *byte == needle {
        return Some(step);
      }
      step += 1;
    }
    None
  }
}
<commit_msg>Removed comments, removed erroneous "offset" field in FrameBuffer.<commit_after>use header::HeaderList;
use header::Header;
use header::ContentLength;
use header::StompHeaderSet;
use std::str::from_utf8;
use frame::{Frame, Transmission};
use std::collections::VecDeque;

pub struct FrameBuffer {
  buffer: VecDeque<u8>,
  parse_state: ParseState
}

struct ParseState {
  command: Option<String>,
  headers: HeaderList,
  body: Option<Vec<u8>>,
  section: FrameSection,
}

impl ParseState {
  fn new() -> ParseState {
    ParseState {
      command: None,
      headers: header_list![],
      body: None,
      section: FrameSection::Command
    }
  }
}

enum FrameSection {
  Command,
  Headers,
  Body
}

enum ReadCommandResult {
  HeartBeat,
  Command(String),
  Incomplete
}

enum ReadHeaderResult {
  Header(Header),
  EndOfHeaders,
  Incomplete
}

enum ReadBodyResult {
  Body(Vec<u8>),
  Incomplete
}

impl FrameBuffer {
  pub fn new() -> FrameBuffer {
    FrameBuffer::with_capacity(1024 * 64)
  }

  pub fn with_capacity(capacity: usize) -> FrameBuffer {
    FrameBuffer {
      buffer: VecDeque::with_capacity(capacity),
      parse_state: ParseState::new()
    }
  }

  pub fn len(&self) -> usize {
    self.buffer.len()
  }

  pub fn append(&mut self, bytes: &[u8]) {
    for byte in bytes {
      self.buffer.push_back(*byte);
    }
    debug!("Copied {} bytes into the frame buffer.", bytes.len());
  }

  pub fn read_transmission(&mut self) -> Option<Transmission> {
    match self.parse_state.section {
      FrameSection::Command => self.resume_parsing_at_command(),
      FrameSection::Headers => self.resume_parsing_at_headers(),
      FrameSection::Body    => self.resume_parsing_at_body()
    }
  }

  fn resume_parsing_at_command(&mut self) -> Option<Transmission> {
    debug!("Parsing command.");
    match self.read_command() {
      ReadCommandResult::HeartBeat => Some(Transmission::HeartBeat),
      ReadCommandResult::Command(command_string) => {
        self.parse_state.command = Some(command_string);
        self.parse_state.section = FrameSection::Headers;
        self.resume_parsing_at_headers()
      },
      ReadCommandResult::Incomplete => None
    }
  }

  fn resume_parsing_at_headers(&mut self) -> Option<Transmission> {
    debug!("Parsing headers.");
    match self.read_header() {
      ReadHeaderResult::Header(header) => {
        self.parse_state.headers.push(header);
        self.resume_parsing_at_headers()
      },
      ReadHeaderResult::EndOfHeaders => {
        self.parse_state.section = FrameSection::Body;
        self.resume_parsing_at_body()
      },
      ReadHeaderResult::Incomplete => None
    }
  }

//TODO: Eliminate clone()s
  fn resume_parsing_at_body(&mut self) -> Option<Transmission> {
    debug!("Parsing body.");
    match self.read_body() {
      ReadBodyResult::Body(body_bytes) => {
        let command = match self.parse_state.command {
          Some(ref command) => command.to_string(),
          None => panic!("No COMMAND found.")
        };
        let headers = self.parse_state.headers.clone();
        let body = body_bytes;
        let frame = Frame {
          command: command,
          headers: headers,
          body: body
        };
        self.reset_parse_state();
        Some(Transmission::CompleteFrame(frame))
      },
      ReadBodyResult::Incomplete => None
    }
  }

  fn reset_parse_state(&mut self) {
    self.parse_state.command = None;
    self.parse_state.headers = header_list![];
    self.parse_state.body = None;
    self.parse_state.section = FrameSection::Command;
  }

  // Replace these methods with bridge-buffer concept
  fn read_into_vec(&mut self, n: usize) -> Vec<u8> {
    let mut vec = Vec::with_capacity(n);
    for _ in 0..n {
      let byte = match self.buffer.pop_front() {
        Some(byte) => byte,
        None => panic!("Attempted to read beyond the end of the buffer!")
      };
      vec.push(byte);
    }
    debug!("Removed {} bytes from frame buffer, new size: {}", n, self.buffer.len());
    vec
  }

  // Wasteful with allocations
  fn read_into_string(&mut self, n: usize) -> String {
    let vec = self.read_into_vec(n);
    let string = from_utf8(&vec)
      .ok()
      .expect("Attempted to read a string that was not utf8.");
    return string.to_string();
  }

  fn chomp(mut line: String) -> String {
    // This may be suboptimal, but fine for now
    let chomped_length : usize;
    {
      let chars_to_remove : &[char] = &['\r', '\n'];
      let trimmed_line : &str = line.trim_right_matches(chars_to_remove);
      chomped_length = trimmed_line.len();
    }
    line.truncate(chomped_length);
    line
  }

  fn read_command(&mut self) -> ReadCommandResult {
    use frame_buffer::ReadCommandResult::*;
    //TODO: check for \r\n
    match self.find_next('\n' as u8) {
/*      Some(0) => {
        debug!("Found Heartbeat");
        let num_bytes = 1;
        self.discard(num_bytes);
        HeartBeat
      },
*/
      Some(index) => {
        debug!("Found command ending @ index {}", index);
        let num_bytes = index + 1;
        let command = self.read_into_string(num_bytes as usize);
        let command = FrameBuffer::chomp(command);
        debug!("Chomped length: {}", command.len());
        if command == "" {
          debug!("Found HeartBeat");
          return HeartBeat;
        }
        if command.len() == 1 {
          debug!("Byte: {}", command.as_bytes()[0]);
        }
        debug!("Command -> '{}'", command);
        Command(command)
      },
      None => Incomplete
    }
  }

  fn read_header(&mut self) -> ReadHeaderResult {
    match self.find_next('\n' as u8) {
      Some(index) => {
        debug!("Found header ending @ index {}", index);
        let num_bytes = index + 1;
        let header_string = self.read_into_string(num_bytes as usize);
        let header_string = FrameBuffer::chomp(header_string);
        debug!("Header -> '{}'", header_string);
        if header_string == "" {
          return ReadHeaderResult::EndOfHeaders;
        }
        let header = Header::decode_string(&header_string).expect("Invalid header encountered.");
        ReadHeaderResult::Header(header)
      },
      None => ReadHeaderResult::Incomplete
    }
  }

  // TODO: Need to read both by Content-Length and by null byte
  // This is easier if we've already created the header set
  fn read_body(&mut self) -> ReadBodyResult {
    let maybe_body : Option<Vec<u8>> = match self.parse_state.headers.get_content_length() {
      Some(ContentLength(num_bytes)) => self.read_body_by_content_length(num_bytes as usize),
      None => self.read_body_by_null_octet()
    };
    match maybe_body {
      Some(body) => ReadBodyResult::Body(body),
      None => ReadBodyResult::Incomplete
    }
  }

  fn read_body_by_content_length(&mut self, content_length: usize) -> Option<Vec<u8>> {
    debug!("Reading body by content length.");
    let bytes_needed = content_length + 1; // null octet
    if self.buffer.len() < bytes_needed {
      debug!("Not enough bytes to form body; needed {}, only had {}.", content_length, self.buffer.len());
      return None;
    }
    let mut body = self.read_into_vec(bytes_needed);
    body.pop(); // Discard null octet
    debug!("Body -> '{}'", FrameBuffer::body_as_string(&body));
    Some(body)
  }

  fn read_body_by_null_octet(&mut self) -> Option<Vec<u8>> {
    debug!("Reading body by null octet.");
    match self.find_next(0u8) {
      Some(index) => {
        debug!("Found body ending @ index {}", index);
        let num_bytes = index + 1;
        let mut body = self.read_into_vec(num_bytes as usize);
        body.pop(); // Discard null octet
        debug!("Body -> '{}'", FrameBuffer::body_as_string(&body));
        Some(body)
      },
      None => None
    }
  }

  fn body_as_string(body: &Vec<u8>) -> &str {
    match from_utf8(&body) {
      Ok(ref s) => *s,
      Err(_) => "<Non-utf8 Binary Content>"
    }
  }

  fn find_next(&self, needle: u8) -> Option<u32> {
    let mut step = 0u32;
    for byte in &self.buffer {
      if *byte == needle {
        return Some(step);
      }
      step += 1;
    }
    None
  }
}
<|endoftext|>


<commit_before>use crate::GpuState;
use std::mem;

#[derive(Copy, Clone)]
pub(crate) struct GenHeightmapsUniforms {
    pub position: [i32; 2],
    pub origin: [i32; 2],
    pub spacing: f32,
    pub in_slot: i32,
    pub out_slot: i32,
    pub level_resolution: i32,
}
unsafe impl bytemuck::Zeroable for GenHeightmapsUniforms {}
unsafe impl bytemuck::Pod for GenHeightmapsUniforms {}

#[derive(Copy, Clone)]
pub(crate) struct GenDisplacementsUniforms {
    pub origin: [i32; 2],
    pub stride: i32,
    pub heightmaps_slot: i32,
    pub displacements_slot: i32,
}
unsafe impl bytemuck::Zeroable for GenDisplacementsUniforms {}
unsafe impl bytemuck::Pod for GenDisplacementsUniforms {}

#[repr(C)]
#[derive(Copy, Clone)]
pub(crate) struct GenNormalsUniforms {
    pub cspace_origin: [f64; 4],
    pub cspace_dx: [f64; 4],
    pub cspace_dy: [f64; 4],
    pub heightmaps_origin: [i32; 2],
    pub parent_origin: [u32; 2],
    pub heightmaps_slot: i32,
    pub normals_slot: i32,
    pub albedo_slot: i32,
    pub parent_slot: i32,
    pub spacing: f32,
    pub padding: i32,
}
unsafe impl bytemuck::Zeroable for GenNormalsUniforms {}
unsafe impl bytemuck::Pod for GenNormalsUniforms {}

pub(crate) struct ComputeShader<U> {
    shader: rshader::ShaderSet,
    bindgroup_pipeline: Option<(wgpu::BindGroup, wgpu::ComputePipeline)>,
    uniforms: wgpu::Buffer,
    _phantom: std::marker::PhantomData<U>,
}
impl<U: bytemuck::Pod> ComputeShader<U> {
    pub fn new(device: &wgpu::Device, shader: rshader::ShaderSet) -> Self {
        Self {
            shader,
            bindgroup_pipeline: None,
            uniforms: device.create_buffer(&wgpu::BufferDescriptor {
                size: mem::size_of::<U>() as u64,
                usage: wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
                mapped_at_creation: false,
                label: None,
            }),
            _phantom: std::marker::PhantomData,
        }
    }

    pub fn refresh(&mut self) -> bool {
        if self.shader.refresh() {
            self.bindgroup_pipeline = None;
            true
        } else {
            false
        }
    }

    pub fn run(
        &mut self,
        device: &wgpu::Device,
        encoder: &mut wgpu::CommandEncoder,
        state: &GpuState,
        dimensions: (u32, u32, u32),
        uniforms: &U,
    ) {
        if self.bindgroup_pipeline.is_none() {
            let (bind_group, bind_group_layout) = state.bind_group_for_shader(
                device,
                &self.shader,
                Some(wgpu::BindingResource::Buffer {
                    buffer: &self.uniforms,
                    offset: 0,
                    size: None,
                }),
            );
            self.bindgroup_pipeline = Some((
                bind_group,
                device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
                    layout: Some(&device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
                        bind_group_layouts: [&bind_group_layout][..].into(),
                        push_constant_ranges: &[],
                        label: None,
                    })),
                    compute_stage: wgpu::ProgrammableStageDescriptor {
                        module: &device.create_shader_module(wgpu::ShaderModuleSource::SpirV(
                            self.shader.compute().into(),
                        )),
                        entry_point: "main".into(),
                    },
                    label: None,
                }),
            ));
        }

        let staging = device.create_buffer(&wgpu::BufferDescriptor {
            size: mem::size_of::<U>() as u64,
            usage: wgpu::BufferUsage::COPY_SRC,
            label: None,
            mapped_at_creation: true,
        });
        let mut buffer_view = staging.slice(..).get_mapped_range_mut();
        bytemuck::cast_slice_mut(&mut *buffer_view)[0] = *uniforms;
        drop(buffer_view);
        staging.unmap();

        encoder.copy_buffer_to_buffer(&staging, 0, &self.uniforms, 0, mem::size_of::<U>() as u64);

        let mut cpass = encoder.begin_compute_pass();
        cpass.set_pipeline(&self.bindgroup_pipeline.as_ref().unwrap().1);
        cpass.set_bind_group(0, &self.bindgroup_pipeline.as_ref().unwrap().0, &[]);
        cpass.dispatch(dimensions.0, dimensions.1, dimensions.2);
    }

    pub fn hash(&self) -> &[u8] {
        self.shader.digest()
    }
}
<commit_msg>Fix memory alignment bug<commit_after>use crate::GpuState;
use std::mem;

#[derive(Copy, Clone)]
pub(crate) struct GenHeightmapsUniforms {
    pub position: [i32; 2],
    pub origin: [i32; 2],
    pub spacing: f32,
    pub in_slot: i32,
    pub out_slot: i32,
    pub level_resolution: i32,
}
unsafe impl bytemuck::Zeroable for GenHeightmapsUniforms {}
unsafe impl bytemuck::Pod for GenHeightmapsUniforms {}

#[derive(Copy, Clone)]
pub(crate) struct GenDisplacementsUniforms {
    pub origin: [i32; 2],
    pub stride: i32,
    pub heightmaps_slot: i32,
    pub displacements_slot: i32,
}
unsafe impl bytemuck::Zeroable for GenDisplacementsUniforms {}
unsafe impl bytemuck::Pod for GenDisplacementsUniforms {}

#[repr(C)]
#[derive(Copy, Clone)]
pub(crate) struct GenNormalsUniforms {
    pub cspace_origin: [f64; 4],
    pub cspace_dx: [f64; 4],
    pub cspace_dy: [f64; 4],
    pub heightmaps_origin: [i32; 2],
    pub parent_origin: [u32; 2],
    pub heightmaps_slot: i32,
    pub normals_slot: i32,
    pub albedo_slot: i32,
    pub parent_slot: i32,
    pub spacing: f32,
    pub padding: i32,
}
unsafe impl bytemuck::Zeroable for GenNormalsUniforms {}
unsafe impl bytemuck::Pod for GenNormalsUniforms {}

pub(crate) struct ComputeShader<U> {
    shader: rshader::ShaderSet,
    bindgroup_pipeline: Option<(wgpu::BindGroup, wgpu::ComputePipeline)>,
    uniforms: wgpu::Buffer,
    _phantom: std::marker::PhantomData<U>,
}
impl<U: bytemuck::Pod> ComputeShader<U> {
    pub fn new(device: &wgpu::Device, shader: rshader::ShaderSet) -> Self {
        Self {
            shader,
            bindgroup_pipeline: None,
            uniforms: device.create_buffer(&wgpu::BufferDescriptor {
                size: mem::size_of::<U>() as u64,
                usage: wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
                mapped_at_creation: false,
                label: None,
            }),
            _phantom: std::marker::PhantomData,
        }
    }

    pub fn refresh(&mut self) -> bool {
        if self.shader.refresh() {
            self.bindgroup_pipeline = None;
            true
        } else {
            false
        }
    }

    pub fn run(
        &mut self,
        device: &wgpu::Device,
        encoder: &mut wgpu::CommandEncoder,
        state: &GpuState,
        dimensions: (u32, u32, u32),
        uniforms: &U,
    ) {
        if self.bindgroup_pipeline.is_none() {
            let (bind_group, bind_group_layout) = state.bind_group_for_shader(
                device,
                &self.shader,
                Some(wgpu::BindingResource::Buffer {
                    buffer: &self.uniforms,
                    offset: 0,
                    size: None,
                }),
            );
            self.bindgroup_pipeline = Some((
                bind_group,
                device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
                    layout: Some(&device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
                        bind_group_layouts: [&bind_group_layout][..].into(),
                        push_constant_ranges: &[],
                        label: None,
                    })),
                    compute_stage: wgpu::ProgrammableStageDescriptor {
                        module: &device.create_shader_module(wgpu::ShaderModuleSource::SpirV(
                            self.shader.compute().into(),
                        )),
                        entry_point: "main".into(),
                    },
                    label: None,
                }),
            ));
        }

        let staging = device.create_buffer(&wgpu::BufferDescriptor {
            size: mem::size_of::<U>() as u64,
            usage: wgpu::BufferUsage::COPY_SRC,
            label: None,
            mapped_at_creation: true,
        });
        let mut buffer_view = staging.slice(..).get_mapped_range_mut();
        buffer_view[..mem::size_of::<U>()].copy_from_slice(bytemuck::bytes_of(uniforms));
        drop(buffer_view);
        staging.unmap();

        encoder.copy_buffer_to_buffer(&staging, 0, &self.uniforms, 0, mem::size_of::<U>() as u64);

        let mut cpass = encoder.begin_compute_pass();
        cpass.set_pipeline(&self.bindgroup_pipeline.as_ref().unwrap().1);
        cpass.set_bind_group(0, &self.bindgroup_pipeline.as_ref().unwrap().0, &[]);
        cpass.dispatch(dimensions.0, dimensions.1, dimensions.2);
    }

    pub fn hash(&self) -> &[u8] {
        self.shader.digest()
    }
}
<|endoftext|>


<commit_before>extern crate log_domain;
extern crate num_traits;
extern crate rustomata;

use log_domain::LogDomain;
use num_traits::identities::One;
use std::fs::File;
use std::io::Read;
use std::marker::PhantomData;

use rustomata::approximation::ApproximationStrategy;
use rustomata::approximation::equivalence_classes::EquivalenceRelation;
use rustomata::approximation::relabel::RlbElement;
use rustomata::cfg::*;
use rustomata::push_down_automaton::*;
use rustomata::recognisable::*;

fn example_pushdown_automaton()
    -> PushDownAutomaton<PushState<String, String>, String, LogDomain<f64>>
{
    let mut grammar_file = File::open("examples/example2.cfg").unwrap();
    let mut grammar_string = String::new();
    let _ = grammar_file.read_to_string(&mut grammar_string);
    let grammar: CFG<String, String, _> = grammar_string.parse().unwrap();

    PushDownAutomaton::from(grammar)
}

fn example_equivalence_relation() -> EquivalenceRelation<String, String> {
    let mut relation_file = File::open("examples/example.classes").unwrap();
    let mut relation_string = String::new();
    let _ = relation_file.read_to_string(&mut relation_string);

    relation_string.parse().unwrap()
}

#[test]
fn test_relabel_pushdown() {
    //create (and test) initial push down automata
    let r0_string = "S → [Nt A] # 1";
    let r1_string = "A → [T a, Nt A, Nt B  ] # 0.6";
    let r2_string = "A → [T a              ] # 0.4";
    let r3_string = "B → [T b, Nt B, Nt A  ] # 0.3";
    let r4_string = "B → [T b              ] # 0.7";

    let mut g_string = String::from("initial: [S, B]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r4_string.clone());

    let g: CFG<String, String, LogDomain<f64>> = g_string.parse().unwrap();

    let a = PushDownAutomaton::from(g);

    let mut e_string = String::from("S [S]\n");
    e_string.push_str("N [A, B]\n");
    e_string.push_str("R *\n");

    let e: EquivalenceRelation<String, String> = e_string.parse().unwrap();

    let f = |ps: &PushState<_, _>| ps.map(|nt| e.project(nt));
    let rlb = RlbElement::new(&f);

    let (b, _) = rlb.approximate_automaton(&a);

    assert_ne!(None, b.recognise(vec!["a".to_string() ]).next());
    assert_eq!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string() ]).next());
    assert_ne!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string(), "b".to_string(), "b".to_string(), "a".to_string() ]).next());
    assert_ne!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string(), "b".to_string() ]).next());

    assert_ne!(None, b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "a".to_string(), "a".to_string() ]).next());
}

#[test]
fn test_relabel_check() {
    //create (and test) initial push down automata
    let r0_string = "S → [Nt A] # 1";
    let r1_string = "A → [T a, Nt A, Nt B  ] # 0.6";
    let r2_string = "A → [T a              ] # 0.4";
    let r3_string = "B → [T b, Nt B, Nt A  ] # 0.3";
    let r4_string = "B → [T b              ] # 0.7";

    let mut g_string = String::from("initial: [S, B]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r4_string.clone());

    let g: CFG<String, String, LogDomain<f64>> = g_string.parse().unwrap();

    let a = PushDownAutomaton::from(g);

    let mut e_string = String::from("S [S]\n");
    e_string.push_str("N [A, B]\n");
    e_string.push_str("R *\n");

    let e: EquivalenceRelation<String, String> = e_string.parse().unwrap();

    let f = |ps: &PushState<_, _>| ps.map(|nt| e.project(nt));
    let rlb = RlbElement::new(&f);

    let (b, _) = rlb.approximate_automaton(&a);

    let itemb = b.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "a".to_string(), "a".to_string() ]).next();
    assert_ne!(None, itemb);
}

#[test]
fn test_from_str_cfg() {
    let c0 : CFGComposition<String,String> = CFGComposition {
        composition: vec![LetterT::Label("A".to_string())],
    };

    let c1 : CFGComposition<String,String>  = CFGComposition {
        composition: vec![LetterT::Value("a".to_string()),LetterT::Label("A".to_string()),LetterT::Label("B".to_string())]
    };

    let c2 : CFGComposition<String,String>  = CFGComposition {
        composition: vec![LetterT::Value("a".to_string())],
    };

    let c3 : CFGComposition<String,String>  = CFGComposition {
        composition: vec![LetterT::Value("b".to_string())],
    };

    let r0: CFGRule<String, String, LogDomain<f64>> = CFGRule {
        head: "S".to_string(),
        composition: c0.clone(),
        weight: LogDomain::one(),
    };

    let r1: CFGRule<String, String, LogDomain<f64>> = CFGRule {
        head: "A".to_string(),
        composition: c1.clone(),
        weight: LogDomain::new(0.6).unwrap(),
    };

    let r2: CFGRule<String, String, LogDomain<f64>> = CFGRule {
        head: "A".to_string(),
        composition: c2.clone(),
        weight: LogDomain::new(0.4).unwrap(),
    };

    let r3: CFGRule<String, String, LogDomain<f64>> = CFGRule {
        head: "B".to_string(),
        composition: c3.clone(),
        weight: LogDomain::one(),
    };

    let r0_string = "S → [Nt A]";
    let r1_string = "A → [T a, Nt A, Nt B] # 0.6";
    let r2_string = "A → [T a] # 0.4";
    let r3_string = "B → [T b] # 1";

    assert_eq!(Ok(r0.clone()),
               r0_string.parse::<CFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r1.clone()),
               r1_string.parse::<CFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r2.clone()),
               r2_string.parse::<CFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r3.clone()),
               r3_string.parse::<CFGRule<String, String, LogDomain<f64>>>());

    let g: CFG<String, String, LogDomain<f64>> = CFG {
        _dummy: PhantomData,
        initial: vec!["S".to_string(),"B".to_string()],
        rules: vec![r0.clone(), r1.clone(), r2.clone(), r3.clone()],
    };

    let mut g_string = String::from("initial: [S, B]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());

    assert_eq!(Ok(g.clone()), g_string.parse());

    let a = PushDownAutomaton::from(g);

    assert_ne!(None, a.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string(), "b".to_string()]).next());
}
<commit_msg>tests/cfg.rs: reworked integration test for rlb<commit_after>extern crate log_domain;
extern crate num_traits;
extern crate rustomata;

use log_domain::LogDomain;
use num_traits::identities::One;
use std::fs::File;
use std::io::Read;
use std::marker::PhantomData;

use rustomata::approximation::ApproximationStrategy;
use rustomata::approximation::equivalence_classes::EquivalenceRelation;
use rustomata::approximation::relabel::RlbElement;
use rustomata::cfg::*;
use rustomata::push_down_automaton::*;
use rustomata::recognisable::*;

fn example_pushdown_automaton()
    -> PushDownAutomaton<PushState<String, String>, String, LogDomain<f64>>
{
    let mut grammar_file = File::open("examples/example2.cfg").unwrap();
    let mut grammar_string = String::new();
    let _ = grammar_file.read_to_string(&mut grammar_string);
    let grammar: CFG<String, String, _> = grammar_string.parse().unwrap();

    PushDownAutomaton::from(grammar)
}

fn example_equivalence_relation() -> EquivalenceRelation<String, String> {
    let mut relation_file = File::open("examples/example.classes").unwrap();
    let mut relation_string = String::new();
    let _ = relation_file.read_to_string(&mut relation_string);

    relation_string.parse().unwrap()
}

#[test]
fn test_relabel_pushdown_correctness() {
    let automaton = example_pushdown_automaton();
    let rel = example_equivalence_relation();
    let mapping = |ps: &PushState<_, _>| ps.map(|nt| rel.project(nt));
    let rlb = RlbElement::new(&mapping);
    let (relabelled_automaton, _) = rlb.approximate_automaton(&automaton);

    let true_positives_and_true_negatives = vec![
        "aab",
        "bba",
        "aaabb",
        "aabba",
        "",
        "aa",
        "aaab",
        "bbbbbb",
    ];

    for word in true_positives_and_true_negatives {
        let input: Vec<_> = String::from(word).chars().map(|x| x.to_string()).collect();
        assert_eq!(
            automaton.recognise(input.clone()).next().is_some(),
            relabelled_automaton.recognise(input).next().is_some()
        );
    }

    let false_positives = vec![
        "aaa",
        "bbb",
        "aabaa",
        "abaaa",
    ];

    for word in false_positives {
        let input: Vec<_> = String::from(word).chars().map(|x| x.to_string()).collect();
        assert_eq!(false, automaton.recognise(input.clone()).next().is_some());
        assert_eq!(true, relabelled_automaton.recognise(input).next().is_some());
    }
}

#[test]
fn test_from_str_cfg() {
    let c0 : CFGComposition<String,String> = CFGComposition {
        composition: vec![LetterT::Label("A".to_string())],
    };

    let c1 : CFGComposition<String,String>  = CFGComposition {
        composition: vec![LetterT::Value("a".to_string()),LetterT::Label("A".to_string()),LetterT::Label("B".to_string())]
    };

    let c2 : CFGComposition<String,String>  = CFGComposition {
        composition: vec![LetterT::Value("a".to_string())],
    };

    let c3 : CFGComposition<String,String>  = CFGComposition {
        composition: vec![LetterT::Value("b".to_string())],
    };

    let r0: CFGRule<String, String, LogDomain<f64>> = CFGRule {
        head: "S".to_string(),
        composition: c0.clone(),
        weight: LogDomain::one(),
    };

    let r1: CFGRule<String, String, LogDomain<f64>> = CFGRule {
        head: "A".to_string(),
        composition: c1.clone(),
        weight: LogDomain::new(0.6).unwrap(),
    };

    let r2: CFGRule<String, String, LogDomain<f64>> = CFGRule {
        head: "A".to_string(),
        composition: c2.clone(),
        weight: LogDomain::new(0.4).unwrap(),
    };

    let r3: CFGRule<String, String, LogDomain<f64>> = CFGRule {
        head: "B".to_string(),
        composition: c3.clone(),
        weight: LogDomain::one(),
    };

    let r0_string = "S → [Nt A]";
    let r1_string = "A → [T a, Nt A, Nt B] # 0.6";
    let r2_string = "A → [T a] # 0.4";
    let r3_string = "B → [T b] # 1";

    assert_eq!(Ok(r0.clone()),
               r0_string.parse::<CFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r1.clone()),
               r1_string.parse::<CFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r2.clone()),
               r2_string.parse::<CFGRule<String, String, LogDomain<f64>>>());
    assert_eq!(Ok(r3.clone()),
               r3_string.parse::<CFGRule<String, String, LogDomain<f64>>>());

    let g: CFG<String, String, LogDomain<f64>> = CFG {
        _dummy: PhantomData,
        initial: vec!["S".to_string(),"B".to_string()],
        rules: vec![r0.clone(), r1.clone(), r2.clone(), r3.clone()],
    };

    let mut g_string = String::from("initial: [S, B]\n\n");
    g_string.push_str(r0_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r1_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r2_string.clone());
    g_string.push_str("\n");
    g_string.push_str(r3_string.clone());

    assert_eq!(Ok(g.clone()), g_string.parse());

    let a = PushDownAutomaton::from(g);

    assert_ne!(None, a.recognise(vec!["a".to_string(), "a".to_string(), "a".to_string(), "b".to_string(), "b".to_string()]).next());
}
<|endoftext|>