fuchsia_pkg/
meta_package.rsuse crate::errors::MetaPackageError;
use crate::path::PackagePath;
use fuchsia_url::{PackageName, PackageVariant};
use serde::{Deserialize, Serialize};
use std::convert::TryInto as _;
use std::io;
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct MetaPackage {
name: PackageName,
variant: PackageVariant,
}
impl MetaPackage {
pub const PATH: &'static str = "meta/package";
pub fn from_name_and_variant_zero(name: PackageName) -> Self {
Self { name, variant: PackageVariant::zero() }
}
pub fn name(&self) -> &PackageName {
&self.name
}
pub fn variant(&self) -> &PackageVariant {
&self.variant
}
pub fn into_path(self) -> PackagePath {
PackagePath::from_name_and_variant(self.name, self.variant)
}
pub fn deserialize(reader: impl io::BufRead) -> Result<Self, MetaPackageError> {
MetaPackage::from_v0(serde_json::from_reader(reader)?)
}
pub fn serialize(&self, writer: impl io::Write) -> Result<(), MetaPackageError> {
serde_json::to_writer(
writer,
&MetaPackageV0Serialize { name: self.name.as_ref(), variant: self.variant.as_ref() },
)?;
Ok(())
}
fn from_v0(v0: MetaPackageV0Deserialize) -> Result<MetaPackage, MetaPackageError> {
Ok(MetaPackage {
name: v0.name.try_into().map_err(MetaPackageError::PackageName)?,
variant: v0.variant.try_into().map_err(MetaPackageError::PackageVariant)?,
})
}
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
struct MetaPackageV0Deserialize {
name: String,
#[serde(rename = "version")]
variant: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
struct MetaPackageV0Serialize<'a> {
name: &'a str,
#[serde(rename = "version")]
variant: &'a str,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test::*;
use lazy_static::lazy_static;
use proptest::prelude::*;
use regex::Regex;
#[test]
fn test_accessors() {
let meta_package = MetaPackage::from_name_and_variant_zero("foo".parse().unwrap());
assert_eq!(meta_package.name(), &"foo".parse::<PackageName>().unwrap());
assert_eq!(meta_package.variant(), &"0".parse::<PackageVariant>().unwrap());
}
#[test]
fn test_serialize() {
let meta_package = MetaPackage::from_name_and_variant_zero("package-name".parse().unwrap());
let mut v: Vec<u8> = Vec::new();
meta_package.serialize(&mut v).unwrap();
let expected = r#"{"name":"package-name","version":"0"}"#;
assert_eq!(v.as_slice(), expected.as_bytes());
}
#[test]
fn test_deserialize() {
let json_bytes = r#"{"name":"package-name","version":"0"}"#.as_bytes();
assert_eq!(
MetaPackage::deserialize(json_bytes).unwrap(),
MetaPackage { name: "package-name".parse().unwrap(), variant: "0".parse().unwrap() }
);
}
proptest! {
#![proptest_config(ProptestConfig{
failure_persistence: None,
..Default::default()
})]
#[test]
fn test_serialize_deserialize_is_identity(
meta_package in random_meta_package(),
) {
let mut v: Vec<u8> = Vec::new();
meta_package.serialize(&mut v).unwrap();
let meta_package_round_trip = MetaPackage::deserialize(v.as_slice()).unwrap();
assert_eq!(meta_package, meta_package_round_trip);
}
#[test]
fn test_serialized_contains_no_whitespace(
meta_package in random_meta_package(),
) {
lazy_static! {
static ref RE: Regex = Regex::new(r"(\p{White_Space})").unwrap();
}
let mut v: Vec<u8> = Vec::new();
meta_package.serialize(&mut v).unwrap();
assert!(!RE.is_match(std::str::from_utf8(v.as_slice()).unwrap()));
}
}
}