update_package/
packages.rs1use fuchsia_url::fuchsia_pkg::PinnedAbsolutePackageUrl;
6use serde::{Deserialize, Serialize};
7
8#[derive(Serialize, Deserialize, Debug)]
9#[serde(tag = "version", content = "content", deny_unknown_fields)]
10enum Packages {
11 #[serde(rename = "1")]
12 V1(Vec<PinnedAbsolutePackageUrl>),
13}
14
15#[derive(Debug, thiserror::Error)]
18#[allow(missing_docs)]
19pub enum ParsePackageError {
20 #[error("could not parse url from line: {0:?}")]
21 URLParseError(String, #[source] fuchsia_url::errors::ParseError),
22
23 #[error("json parsing error while reading `packages.json`")]
24 JsonError(#[source] serde_json::error::Error),
25}
26
27#[derive(Debug, thiserror::Error)]
30#[allow(missing_docs)]
31pub enum SerializePackageError {
32 #[error("serialization error while constructing `packages.json`")]
33 JsonError(#[source] serde_json::error::Error),
34}
35
36pub fn parse_packages_json(
38 contents: &[u8],
39) -> Result<Vec<PinnedAbsolutePackageUrl>, ParsePackageError> {
40 match serde_json::from_slice(contents).map_err(ParsePackageError::JsonError)? {
41 Packages::V1(packages) => Ok(packages),
42 }
43}
44
45pub fn serialize_packages_json(
47 pkg_urls: &[PinnedAbsolutePackageUrl],
48) -> Result<Vec<u8>, SerializePackageError> {
49 serde_json::to_vec(&Packages::V1(pkg_urls.into())).map_err(SerializePackageError::JsonError)
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use assert_matches::assert_matches;
56
57 fn pkg_urls<'a>(v: impl IntoIterator<Item = &'a str>) -> Vec<PinnedAbsolutePackageUrl> {
58 v.into_iter().map(|s| s.parse().unwrap()).collect()
59 }
60
61 #[test]
62 fn smoke_test_parse_packages_json() {
63 let pkg_urls = pkg_urls([
64 "fuchsia-pkg://fuchsia.com/ls/0?hash=71bad1a35b87a073f72f582065f6b6efec7b6a4a129868f37f6131f02107f1ea",
65 "fuchsia-pkg://fuchsia.com/pkg-resolver/0?hash=26d43a3fc32eaa65e6981791874b6ab80fae31fbfca1ce8c31ab64275fd4e8c0",
66 ]);
67 let packages = Packages::V1(pkg_urls.clone());
68 let packages_json = serde_json::to_vec(&packages).unwrap();
69 assert_eq!(parse_packages_json(&packages_json).unwrap(), pkg_urls);
70 }
71
72 #[test]
73 fn smoke_test_serialize_packages_json() {
74 let input = pkg_urls([
75 "fuchsia-pkg://fuchsia.com/ls/0?hash=71bad1a35b87a073f72f582065f6b6efec7b6a4a129868f37f6131f02107f1ea",
76 "fuchsia-pkg://fuchsia.com/pkg-resolver/0?hash=26d43a3fc32eaa65e6981791874b6ab80fae31fbfca1ce8c31ab64275fd4e8c0",
77 ]);
78 let output =
79 parse_packages_json(serialize_packages_json(input.as_slice()).unwrap().as_slice())
80 .unwrap();
81 assert_eq!(input, output);
82 }
83
84 #[test]
85 fn expect_failure_parse_packages_json() {
86 assert_matches!(parse_packages_json(&[]), Err(ParsePackageError::JsonError(_)));
87 }
88
89 #[test]
90 fn reject_unpinned_urls() {
91 assert_matches!(
92 parse_packages_json(serde_json::json!({
93 "version": "1",
94 "content": ["fuchsia-pkg://fuchsia.example/unpinned"]
95 })
96 .to_string().as_bytes()),
97 Err(ParsePackageError::JsonError(e)) if e.to_string().contains("missing hash")
98 )
99 }
100}