-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdoc_ref.rs
More file actions
151 lines (130 loc) · 4.05 KB
/
doc_ref.rs
File metadata and controls
151 lines (130 loc) · 4.05 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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! Document reference.
use std::fmt::Display;
use catalyst_types::uuid::{CborContext, UuidV7};
use cbork_utils::{array::Array, decode_context::DecodeCtx};
use minicbor::{Decode, Encode};
use super::doc_locator::DocLocator;
use crate::CatalystSignedDocument;
/// Number of item that should be in each document reference instance.
const DOC_REF_ARR_ITEM: u64 = 3;
/// Reference to a Document.
#[derive(Clone, Debug, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
pub struct DocumentRef {
/// Reference to the Document Id
id: UuidV7,
/// Reference to the Document Ver
ver: UuidV7,
/// Document locator
#[serde(rename = "cid", default)]
doc_locator: DocLocator,
}
impl DocumentRef {
/// Create a new instance of document reference.
#[must_use]
pub fn new(
id: UuidV7,
ver: UuidV7,
doc_locator: DocLocator,
) -> Self {
Self {
id,
ver,
doc_locator,
}
}
/// Create a new instance of another document reference without including
/// `doc_locator`.
#[must_use]
pub fn from_without_locator(other: &Self) -> Self {
Self::new(*other.id(), *other.ver(), DocLocator::default())
}
/// Get Document Id.
#[must_use]
pub fn id(&self) -> &UuidV7 {
&self.id
}
/// Get Document Ver.
#[must_use]
pub fn ver(&self) -> &UuidV7 {
&self.ver
}
/// Get Document Locator.
#[must_use]
pub fn doc_locator(&self) -> &DocLocator {
&self.doc_locator
}
}
impl TryFrom<&CatalystSignedDocument> for DocumentRef {
type Error = anyhow::Error;
fn try_from(value: &CatalystSignedDocument) -> Result<Self, Self::Error> {
Ok(Self::new(
value.doc_id()?,
value.doc_ver()?,
DocLocator::default(),
))
}
}
impl Display for DocumentRef {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
write!(
f,
"id: {}, ver: {}, document_locator: {}",
self.id, self.ver, self.doc_locator
)
}
}
impl Decode<'_, ()> for DocumentRef {
fn decode(
d: &mut minicbor::Decoder<'_>,
_ctx: &mut (),
) -> Result<Self, minicbor::decode::Error> {
const CONTEXT: &str = "DocumentRef decoding";
let arr = Array::decode(d, &mut DecodeCtx::Deterministic)
.map_err(|e| minicbor::decode::Error::message(format!("{CONTEXT}: {e}")))?;
let doc_ref = match arr.as_slice() {
[id_bytes, ver_bytes, locator_bytes] => {
let id = UuidV7::decode(
&mut minicbor::Decoder::new(id_bytes.as_slice()),
&mut CborContext::Tagged,
)
.map_err(|e| e.with_message("Invalid ID UUIDv7"))?;
let ver = UuidV7::decode(
&mut minicbor::Decoder::new(ver_bytes.as_slice()),
&mut CborContext::Tagged,
)
.map_err(|e| e.with_message("Invalid Ver UUIDv7"))?;
let doc_locator = minicbor::Decoder::new(locator_bytes.as_slice())
.decode()
.map_err(|e| e.with_message("Failed to decode locator"))?;
DocumentRef {
id,
ver,
doc_locator,
}
},
_ => {
return Err(minicbor::decode::Error::message(format!(
"{CONTEXT}: expected {DOC_REF_ARR_ITEM} items, found {}",
arr.len()
)));
},
};
Ok(doc_ref)
}
}
impl Encode<()> for DocumentRef {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
ctx: &mut (),
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.array(DOC_REF_ARR_ITEM)?;
self.id.encode(e, &mut CborContext::Tagged)?;
self.ver.encode(e, &mut CborContext::Tagged)?;
self.doc_locator.encode(e, ctx)?;
Ok(())
}
}