lightswitch_object/
buildid.rs1use std::fmt;
2use std::fmt::Display;
3use std::fmt::Formatter;
4use std::str;
5
6use anyhow::Result;
7use data_encoding::HEXLOWER;
8use ring::digest::Digest;
9
10#[derive(Hash, Eq, PartialEq, Clone, Debug)]
13pub enum BuildId {
14 Gnu(String),
15 Go(String),
16 Sha256(String),
17}
18
19impl BuildId {
20 pub fn gnu_from_bytes(bytes: &[u8]) -> Self {
21 BuildId::Gnu(
22 bytes
23 .iter()
24 .map(|b| format!("{:02x}", b))
25 .collect::<Vec<_>>()
26 .join(""),
27 )
28 }
29
30 pub fn go_from_bytes(bytes: &[u8]) -> Result<Self> {
31 Ok(BuildId::Go(str::from_utf8(bytes)?.to_string()))
32 }
33
34 pub fn sha256_from_digest(digest: &Digest) -> Self {
35 BuildId::Sha256(HEXLOWER.encode(digest.as_ref()))
36 }
37}
38
39impl Display for BuildId {
40 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
41 match self {
42 BuildId::Gnu(build_id) => {
43 write!(f, "gnu-{}", build_id)
44 }
45 BuildId::Go(build_id) => {
46 write!(f, "go-{}", build_id)
47 }
48 BuildId::Sha256(build_id) => {
49 write!(f, "sha256-{}", build_id)
50 }
51 }
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use ring::digest::{Context, SHA256};
59
60 #[test]
61 fn test_buildid_constructors() {
62 assert_eq!(
63 BuildId::gnu_from_bytes(&[0xbe, 0xef, 0xca, 0xfe]).to_string(),
64 "gnu-beefcafe"
65 );
66 assert_eq!(
67 BuildId::go_from_bytes("fake".as_bytes())
68 .unwrap()
69 .to_string(),
70 "go-fake"
71 );
72
73 let mut context = Context::new(&SHA256);
74 context.update(&[0xbe, 0xef, 0xca, 0xfe]);
75 let digest = context.finish();
76 assert_eq!(
77 BuildId::sha256_from_digest(&digest).to_string(),
78 "sha256-b80ad5b1508835ca2191ac800f4bb1a5ae1c3e47f13a8f5ed1b1593337ae5af5"
79 );
80 }
81
82 #[test]
83 fn test_buildid_display() {
84 assert_eq!(BuildId::Gnu("fake".into()).to_string(), "gnu-fake");
85 assert_eq!(BuildId::Go("fake".into()).to_string(), "go-fake");
86 assert_eq!(BuildId::Sha256("fake".into()).to_string(), "sha256-fake");
87 }
88}