samod_core/
document_id.rs1use serde::{Deserialize, Serialize};
2use std::str::FromStr;
3use uuid::Uuid;
4
5#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
11pub struct DocumentId(Uuid);
12
13impl DocumentId {
14 pub fn new<R: rand::Rng>(rng: &mut R) -> Self {
16 let bytes: [u8; 16] = rng.random();
17 let uuid = uuid::Builder::from_random_bytes(bytes).into_uuid();
18 Self(uuid)
19 }
20
21 pub fn as_bytes(&self) -> &[u8] {
22 self.0.as_bytes()
23 }
24}
25
26impl std::fmt::Debug for DocumentId {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 let as_string = bs58::encode(&self.0).with_check().into_string();
29 write!(f, "{as_string}")
30 }
31}
32
33impl std::fmt::Display for DocumentId {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 let as_string = bs58::encode(&self.0).with_check().into_string();
36 write!(f, "{as_string}")
37 }
38}
39
40#[derive(Debug, thiserror::Error)]
41#[error("Invalid document ID: {0}")]
42pub struct BadDocumentId(String);
43
44impl TryFrom<Vec<u8>> for DocumentId {
45 type Error = BadDocumentId;
46
47 fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
48 match uuid::Uuid::from_slice(v.as_slice()) {
49 Ok(id) => Ok(Self(id)),
50 Err(e) => Err(BadDocumentId(format!("invalid uuid: {e}"))),
51 }
52 }
53}
54
55impl FromStr for DocumentId {
56 type Err = BadDocumentId;
57
58 fn from_str(s: &str) -> Result<Self, Self::Err> {
59 match bs58::decode(s).with_check(None).into_vec() {
60 Ok(bytes) => Self::try_from(bytes),
61 Err(_) => {
62 let uuid = uuid::Uuid::parse_str(s).map_err(|_| {
64 BadDocumentId(
65 "expected either a bs58-encoded document ID or a UUID".to_string(),
66 )
67 })?;
68 Ok(Self(uuid))
69 }
70 }
71 }
72}