oci_image_spec/image_digest/
digest.rs1use serde::{Deserialize, Serialize};
2use std::string::String;
3
4#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
5pub struct Digest {
6 pub name: String,
7 pub digest: String,
8}
9
10impl Digest {
11 pub fn new(alg: super::algorithm::Algorithm, digest: &str) -> Self {
12 let name = alg.name.to_string();
13 let digest = format!("{}:{}", name, digest.to_string());
14 Self { name, digest }
15 }
16
17 pub fn new_from_bytes(alg: super::algorithm::Algorithm, bytes: &[u8]) -> Self {
18 let name = alg.name.to_string();
19 let digest = format!("{}:{}", name, String::from_utf8(bytes.to_vec()).unwrap());
20 Self { name, digest }
21 }
22
23 pub fn string(self: Self) -> String {
24 self.digest.to_string()
25 }
26
27 pub fn algorithm(self: &Self) -> String {
28 self.digest[..self.sep_index()].to_string()
29 }
30
31 pub fn encoded(self: Self) -> String {
32 self.digest[self.sep_index() + 1..].to_string()
33 }
34
35 fn sep_index(&self) -> usize {
36 self.digest.find(':').unwrap()
37 }
38
39 pub fn validate(self: &Self) -> Result<(), std::io::Error> {
40 let alg = self.algorithm();
41 match alg.as_str() {
42 super::algorithm::SHA256 | super::algorithm::SHA384 | super::algorithm::SHA512 => {}
43 _ => {
44 return Err(std::io::Error::new(
45 std::io::ErrorKind::InvalidData,
46 "invalid checksum digest algorithm",
47 ));
48 }
49 }
50 let re = regex::Regex::new(r"^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$").unwrap();
51 if re.is_match(&self.digest) {
52 Ok(())
53 } else {
54 Err(std::io::Error::new(
55 std::io::ErrorKind::InvalidData,
56 "invalid checksum digest format",
57 ))
58 }
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn test_validate() {
68 let d = Digest {
69 name: "sha256".to_string(),
70 digest: "sha256:abcdefghijklmnopqrstuvwxyz0123456789".to_string(),
71 };
72 assert!(d.validate().is_ok());
73 }
74}