stfs 0.1.0

Parser for Xbox 360 STFS (Secure Transacted File System) packages
Documentation
pub mod fixed {
	use serde::de;
	use serde::Deserializer;
	use serde::Serializer;

	#[cfg(feature = "base64-serde")]
	use base64::engine::general_purpose::STANDARD;
	#[cfg(feature = "base64-serde")]
	use base64::Engine;

	#[cfg(feature = "base64-serde")]
	pub fn serialize<const N: usize, S: Serializer>(bytes: &[u8; N], s: S) -> Result<S::Ok, S::Error> {
		s.serialize_str(&STANDARD.encode(bytes))
	}

	#[cfg(not(feature = "base64-serde"))]
	pub fn serialize<const N: usize, S: Serializer>(bytes: &[u8; N], s: S) -> Result<S::Ok, S::Error> {
		s.serialize_bytes(bytes)
	}

	#[cfg(feature = "base64-serde")]
	pub fn deserialize<'de, const N: usize, D: Deserializer<'de>>(d: D) -> Result<[u8; N], D::Error> {
		let s: &str = de::Deserialize::deserialize(d)?;
		let bytes = STANDARD.decode(s).map_err(de::Error::custom)?;
		bytes.try_into().map_err(|v: Vec<u8>| de::Error::custom(format!("expected {} bytes, got {}", N, v.len())))
	}

	#[cfg(not(feature = "base64-serde"))]
	pub fn deserialize<'de, const N: usize, D: Deserializer<'de>>(d: D) -> Result<[u8; N], D::Error> {
		use de::Visitor;

		struct ByteArrayVisitor<const M: usize>;

		impl<'de, const M: usize> Visitor<'de> for ByteArrayVisitor<M> {
			type Value = [u8; M];

			fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
				write!(f, "{} bytes", M)
			}

			fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<[u8; M], E> {
				v.try_into().map_err(|_| de::Error::custom(format!("expected {} bytes, got {}", M, v.len())))
			}

			fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<[u8; M], A::Error> {
				let mut arr = [0u8; M];
				for (i, byte) in arr.iter_mut().enumerate() {
					*byte = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(i, &self))?;
				}
				Ok(arr)
			}
		}

		d.deserialize_any(ByteArrayVisitor::<N>)
	}
}

pub mod fixed_opt {
	use serde::de;
	use serde::Deserialize;
	use serde::Deserializer;
	use serde::Serializer;

	pub fn serialize<const N: usize, S: Serializer>(bytes: &Option<[u8; N]>, s: S) -> Result<S::Ok, S::Error> {
		match bytes {
			Some(b) => super::fixed::serialize(b, s),
			None => s.serialize_none(),
		}
	}

	pub fn deserialize<'de, const N: usize, D: Deserializer<'de>>(d: D) -> Result<Option<[u8; N]>, D::Error> {
		let opt: Option<HelperProxy<N>> = Deserialize::deserialize(d)?;
		Ok(opt.map(|h| h.0))
	}

	struct HelperProxy<const N: usize>([u8; N]);

	impl<'de, const N: usize> de::Deserialize<'de> for HelperProxy<N> {
		fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
			super::fixed::deserialize(d).map(HelperProxy)
		}
	}
}

pub mod vec {
	use serde::de;
	use serde::Deserializer;
	use serde::Serializer;

	#[cfg(feature = "base64-serde")]
	use base64::engine::general_purpose::STANDARD;
	#[cfg(feature = "base64-serde")]
	use base64::Engine;

	#[cfg(feature = "base64-serde")]
	pub fn serialize<S: Serializer>(bytes: &[u8], s: S) -> Result<S::Ok, S::Error> {
		s.serialize_str(&STANDARD.encode(bytes))
	}

	#[cfg(not(feature = "base64-serde"))]
	pub fn serialize<S: Serializer>(bytes: &[u8], s: S) -> Result<S::Ok, S::Error> {
		s.serialize_bytes(bytes)
	}

	#[cfg(feature = "base64-serde")]
	pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
		let s: &str = de::Deserialize::deserialize(d)?;
		STANDARD.decode(s).map_err(de::Error::custom)
	}

	#[cfg(not(feature = "base64-serde"))]
	pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
		use de::Visitor;

		struct ByteVecVisitor;

		impl<'de> Visitor<'de> for ByteVecVisitor {
			type Value = Vec<u8>;

			fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
				write!(f, "byte array")
			}

			fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Vec<u8>, E> {
				Ok(v.to_vec())
			}

			fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Vec<u8>, A::Error> {
				let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or(0));
				while let Some(b) = seq.next_element()? {
					vec.push(b);
				}
				Ok(vec)
			}
		}

		d.deserialize_any(ByteVecVisitor)
	}
}