-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbucket_id.rs
More file actions
80 lines (72 loc) · 2.24 KB
/
Copy pathbucket_id.rs
File metadata and controls
80 lines (72 loc) · 2.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use ::base64::Engine;
use ::base64::prelude::BASE64_URL_SAFE_NO_PAD;
use binary_codec::{FromBytes, ToBytes};
use serde::{Deserialize, Serialize};
use serde_with::base64::{Base64, UrlSafe};
use serde_with::formats::Unpadded;
use serde_with::serde_as;
use crate::crypto::hash_128;
/// Bucket Identifier
#[serde_as]
#[derive(Debug, Serialize, ToBytes, FromBytes, PartialEq, Clone)]
#[serde(transparent)]
pub struct BucketId {
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
pub data: [u8; 16],
}
impl BucketId {
/// Parse BucketId from string
/// Accepts a 16-byte base64-urlencoded string, or a UTF-8 string prefixed with magic prefix `#` (hash with Blake2b) or `@` (hash with Blake3)
pub fn parse(repr: &str) -> Option<Self> {
match repr.chars().next()? {
'#' => Some(Self {
data: hash_128(false, vec![&repr.as_bytes()[1..]]),
}),
'@' => {
let hash = hash_128(true, vec![&repr.as_bytes()[1..]]);
Some(Self { data: hash })
}
_ => {
let decode = BASE64_URL_SAFE_NO_PAD.decode(repr).ok()?;
Some(Self {
data: decode.try_into().ok()?,
})
}
}
}
}
impl<'de> Deserialize<'de> for BucketId {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let str = String::deserialize(deserializer)?;
Ok(Self::parse(&str).expect("Not a valid base64 url-encoded string"))
}
}
#[cfg(test)]
mod tests {
use base64::{Engine, prelude::BASE64_URL_SAFE_NO_PAD};
use crate::core::BucketId;
#[test]
fn can_create_hashed_bucket_id_with_blake2b() {
let id = BucketId::parse("#test").unwrap();
assert_eq!(
id.data,
BASE64_URL_SAFE_NO_PAD
.decode("RKiZXdULZlegN6eDkwRTWw")
.unwrap()[..]
)
}
#[cfg(feature = "blake-3")]
#[test]
fn can_create_hashed_bucket_id_with_blake3() {
let id = BucketId::parse("@test").unwrap();
assert_eq!(
id.data,
BASE64_URL_SAFE_NO_PAD
.decode("SHjKBCXHOfpCf37aIP6EXw")
.unwrap()[..]
)
}
}