package_family_name/
lib.rs

1#![no_std]
2
3extern crate alloc;
4
5use alloc::borrow::ToOwned;
6use alloc::string::String;
7use core::fmt;
8use core::str::FromStr;
9
10use fast32::base32::CROCKFORD_LOWER;
11use sha2::{Digest, Sha256};
12
13use crate::publisher_id::PublisherId;
14
15mod publisher_id;
16
17#[cfg(feature = "serde")]
18mod serde;
19
20#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
21pub struct PackageFamilyName {
22    identity_name: String,
23    publisher_id: PublisherId,
24}
25
26impl PackageFamilyName {
27    pub fn new(identity_name: &str, identity_publisher: &str) -> Self {
28        PackageFamilyName {
29            identity_name: identity_name.to_owned(),
30            publisher_id: Self::get_id(identity_publisher),
31        }
32    }
33
34    pub fn get_id(identity_publisher: &str) -> PublisherId {
35        const HASH_TRUNCATION_LENGTH: usize = 8;
36
37        let publisher_sha_256 = identity_publisher
38            .encode_utf16()
39            .fold(Sha256::new(), |hasher, char| hasher.chain_update(char.to_le_bytes()))
40            .finalize();
41
42        let crockford_encoded = CROCKFORD_LOWER.encode(&publisher_sha_256[..HASH_TRUNCATION_LENGTH]);
43
44        PublisherId(heapless::String::from_str(&crockford_encoded).unwrap())
45    }
46}
47
48impl fmt::Display for PackageFamilyName {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        write!(f, "{}_{}", self.identity_name, self.publisher_id)
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use alloc::string::ToString;
57
58    use crate::PackageFamilyName;
59
60    #[test]
61    fn test_package_family_name() {
62        let package_family_name = PackageFamilyName::new("AppName", "Publisher Software");
63        assert_eq!(package_family_name.to_string(), "AppName_zj75k085cmj1a");
64    }
65
66    #[test]
67    fn test_publisher_id() {
68        let publisher_id = PackageFamilyName::get_id("Publisher Software");
69        assert_eq!(publisher_id.to_string(), "zj75k085cmj1a");
70    }
71
72    #[test]
73    fn test_different_publishers() {
74        let publisher_id1 = PackageFamilyName::get_id("Publisher Software");
75        let publisher_id2 = PackageFamilyName::get_id("Another Publisher");
76        assert_ne!(publisher_id1, publisher_id2);
77    }
78}