docker_registry_client/image/
image_name.rs1use either::Either;
2
3pub mod digest;
4pub mod tag;
5
6use digest::Digest;
7use tag::Tag;
8
9#[derive(Debug)]
10pub enum FromStrError {
11 MissingNameDigest,
12 MissingNameTag,
13 MissingDigest,
14 ParseDigest(digest::FromStrError),
15 ParseTag(tag::FromStrError),
16}
17
18#[derive(Debug, PartialEq, Clone, Eq, Hash)]
19pub struct ImageName {
20 pub name: String,
21 pub identifier: Either<Tag, Digest>,
22}
23
24impl std::fmt::Display for FromStrError {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 Self::MissingNameDigest => f.write_str("missing name and digest"),
28 Self::MissingNameTag => f.write_str("missing name and tag"),
29 Self::MissingDigest => f.write_str("missing digest"),
30 Self::ParseDigest(e) => write!(f, "error parsing digest: {e}"),
31 Self::ParseTag(e) => write!(f, "error parsing tag: {e}"),
32 }
33 }
34}
35
36impl std::error::Error for FromStrError {}
37
38impl std::fmt::Display for ImageName {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 write!(
41 f,
42 "{image_name}:{identifier}",
43 image_name = self.name,
44 identifier = match &self.identifier {
45 Either::Left(tag) => tag.to_string(),
46 Either::Right(digest) => digest.to_string(),
47 }
48 )
49 }
50}
51
52impl std::str::FromStr for ImageName {
53 type Err = FromStrError;
54
55 fn from_str(s: &str) -> Result<Self, Self::Err> {
56 let has_digest = s.contains('@');
57
58 if has_digest {
59 let parts: Vec<&str> = s.split('@').collect();
60 let name = (*parts.first().ok_or(Self::Err::MissingNameDigest)?).to_string();
61
62 let digest = parts
63 .get(1)
64 .ok_or(Self::Err::MissingDigest)?
65 .parse()
66 .map_err(Self::Err::ParseDigest)?;
67
68 Ok(Self {
69 name,
70 identifier: Either::Right(digest),
71 })
72 } else {
73 let parts: Vec<&str> = s.split(':').collect();
74 let name = (*parts.first().ok_or(Self::Err::MissingNameTag)?).to_string();
75
76 let tag = parts
77 .get(1)
78 .unwrap_or(&"latest")
79 .parse()
80 .map_err(Self::Err::ParseTag)?;
81
82 Ok(Self {
83 name,
84 identifier: Either::Left(tag),
85 })
86 }
87 }
88}