fuchsia_url/
fuchsia_pkg_package_url.rs1use crate::errors::ParseError;
6use crate::{FuchsiaPkgAbsolutePackageUrl, RelativePackageUrl, UrlParts};
7
8#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub enum FuchsiaPkgPackageUrl {
13 Absolute(FuchsiaPkgAbsolutePackageUrl),
14 Relative(RelativePackageUrl),
15}
16
17impl FuchsiaPkgPackageUrl {
18 pub fn parse(url: &str) -> Result<Self, ParseError> {
20 let parts = UrlParts::parse(url)?;
21 Ok(if parts.scheme.is_some() {
22 Self::Absolute(FuchsiaPkgAbsolutePackageUrl::from_parts(parts)?)
23 } else {
24 Self::Relative(RelativePackageUrl::from_parts(parts)?)
25 })
26 }
27}
28
29impl std::str::FromStr for FuchsiaPkgPackageUrl {
30 type Err = ParseError;
31
32 fn from_str(url: &str) -> Result<Self, Self::Err> {
33 Self::parse(url)
34 }
35}
36
37impl std::convert::TryFrom<&str> for FuchsiaPkgPackageUrl {
38 type Error = ParseError;
39
40 fn try_from(value: &str) -> Result<Self, Self::Error> {
41 Self::parse(value)
42 }
43}
44
45impl From<FuchsiaPkgAbsolutePackageUrl> for FuchsiaPkgPackageUrl {
46 fn from(absolute: FuchsiaPkgAbsolutePackageUrl) -> Self {
47 Self::Absolute(absolute)
48 }
49}
50
51impl From<RelativePackageUrl> for FuchsiaPkgPackageUrl {
52 fn from(relative: RelativePackageUrl) -> Self {
53 Self::Relative(relative)
54 }
55}
56
57impl std::fmt::Display for FuchsiaPkgPackageUrl {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 match self {
60 Self::Absolute(absolute) => absolute.fmt(f),
61 Self::Relative(relative) => relative.fmt(f),
62 }
63 }
64}
65
66impl serde::Serialize for FuchsiaPkgPackageUrl {
67 fn serialize<S: serde::Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
68 self.to_string().serialize(ser)
69 }
70}
71
72impl<'de> serde::Deserialize<'de> for FuchsiaPkgPackageUrl {
73 fn deserialize<D>(de: D) -> Result<Self, D::Error>
74 where
75 D: serde::Deserializer<'de>,
76 {
77 let url = String::deserialize(de)?;
78 Ok(Self::parse(&url).map_err(|err| serde::de::Error::custom(err))?)
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use assert_matches::assert_matches;
86 use std::convert::TryFrom as _;
87
88 #[test]
89 fn parse_err() {
90 for url in [
91 "fuchsia-boot://example.org/name",
92 "fuchsia-pkg://",
93 "fuchsia-pkg://example.org/",
94 "fuchsia-pkg://example.org//",
95 "fuchsia-pkg://exaMple.org/name",
96 "fuchsia-pkg:///name",
97 "fuchsia-pkg://name",
98 "example.org/name",
99 "name/variant",
100 "name#resource",
101 "name?hash=0000000000000000000000000000000000000000000000000000000000000000",
102 ] {
103 assert_matches!(FuchsiaPkgPackageUrl::parse(url), Err(_), "the url {:?}", url);
104 assert_matches!(url.parse::<FuchsiaPkgPackageUrl>(), Err(_), "the url {:?}", url);
105 assert_matches!(FuchsiaPkgPackageUrl::try_from(url), Err(_), "the url {:?}", url);
106 assert_matches!(
107 serde_json::from_str::<FuchsiaPkgPackageUrl>(url),
108 Err(_),
109 "the url {:?}",
110 url
111 );
112 }
113 }
114
115 #[test]
116 fn parse_ok_absolute() {
117 for url in [
118 "fuchsia-pkg://example.org/name",
119 "fuchsia-pkg://example.org/name/variant",
120 "fuchsia-pkg://example.org/name?hash=0000000000000000000000000000000000000000000000000000000000000000",
121 "fuchsia-pkg://example.org/name/variant?hash=0000000000000000000000000000000000000000000000000000000000000000",
122 ] {
123 let json_url = format!("\"{url}\"");
124 let validate = |parsed: &FuchsiaPkgPackageUrl| {
125 assert_eq!(parsed.to_string(), url);
126 assert_eq!(serde_json::to_string(&parsed).unwrap(), json_url);
127 };
128 validate(&FuchsiaPkgPackageUrl::parse(url).unwrap());
129 validate(&url.parse::<FuchsiaPkgPackageUrl>().unwrap());
130 validate(&FuchsiaPkgPackageUrl::try_from(url).unwrap());
131 validate(&serde_json::from_str::<FuchsiaPkgPackageUrl>(&json_url).unwrap());
132 }
133 }
134
135 #[test]
136 fn parse_ok_relative() {
137 for url in ["name", "other3-name"] {
138 let json_url = format!("\"{url}\"");
139 let validate = |parsed: &FuchsiaPkgPackageUrl| {
140 assert_eq!(parsed.to_string(), url);
141 assert_eq!(serde_json::to_string(&parsed).unwrap(), json_url);
142 };
143 validate(&FuchsiaPkgPackageUrl::parse(url).unwrap());
144 validate(&url.parse::<FuchsiaPkgPackageUrl>().unwrap());
145 validate(&FuchsiaPkgPackageUrl::try_from(url).unwrap());
146 validate(&serde_json::from_str::<FuchsiaPkgPackageUrl>(&json_url).unwrap());
147 }
148 }
149}