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
22impl std::fmt::Debug for DocumentId {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 let as_string = bs58::encode(&self.0).with_check().into_string();
25 write!(f, "{as_string}")
26 }
27}
28
29impl std::fmt::Display for DocumentId {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 let as_string = bs58::encode(&self.0).with_check().into_string();
32 write!(f, "{as_string}")
33 }
34}
35
36#[derive(Debug, thiserror::Error)]
37#[error("Invalid document ID: {0}")]
38pub struct BadDocumentId(String);
39
40impl TryFrom<Vec<u8>> for DocumentId {
41 type Error = BadDocumentId;
42
43 fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
44 match uuid::Uuid::from_slice(v.as_slice()) {
45 Ok(id) => Ok(Self(id)),
46 Err(e) => Err(BadDocumentId(format!("invalid uuid: {e}"))),
47 }
48 }
49}
50
51impl FromStr for DocumentId {
52 type Err = BadDocumentId;
53
54 fn from_str(s: &str) -> Result<Self, Self::Err> {
55 match bs58::decode(s).with_check(None).into_vec() {
56 Ok(bytes) => Self::try_from(bytes),
57 Err(_) => {
58 let uuid = uuid::Uuid::parse_str(s).map_err(|_| {
60 BadDocumentId(
61 "expected either a bs58-encoded document ID or a UUID".to_string(),
62 )
63 })?;
64 Ok(Self(uuid))
65 }
66 }
67 }
68}