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
use crate::{Record, TypedValue, UntypedRecord};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub use crate::resolver::{ResolveError, Resolver};
pub fn extract_refs<T: TypedValue>(refs: &mut [Reference<T>]) -> Vec<UntypedRecord> {
refs.iter_mut()
.filter_map(|r| {
r.extract_record()
.and_then(|record| record.into_untyped().ok())
})
.collect()
}
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
#[serde(untagged)]
pub enum Reference<T: Clone> {
Id(String),
Resolved(Record<T>),
}
impl<T: TypedValue> Reference<T> {
pub fn id(&self) -> &str {
match self {
Self::Id(id) => id,
Self::Resolved(record) => record.guid(),
}
}
pub fn guid(&self) -> &str {
match self {
Self::Id(id) => id,
Self::Resolved(record) => record.guid(),
}
}
pub fn record(&self) -> Option<&Record<T>> {
match self {
Self::Resolved(record) => Some(record),
Self::Id(_) => None,
}
}
pub fn record_mut(&mut self) -> Option<&mut Record<T>> {
match self {
Self::Resolved(record) => Some(record),
Self::Id(_) => None,
}
}
pub fn into_record(self) -> Option<Record<T>> {
match self {
Self::Resolved(record) => Some(record),
Self::Id(_) => None,
}
}
pub fn extract_record(&mut self) -> Option<Record<T>> {
match self {
Self::Resolved(_) => {
let id = self.id().to_string();
let next = Self::Id(id);
let this = std::mem::replace(self, next);
this.into_record()
}
Self::Id(_) => None,
}
}
pub fn resolved(&self) -> bool {
matches!(self, Self::Resolved(_))
}
pub async fn resolve<R: Resolver>(&mut self, resolver: &R) -> Result<(), ResolveError> {
if !self.resolved() {
self.force_resolve(resolver).await?;
}
Ok(())
}
pub async fn force_resolve<R: Resolver>(&mut self, resolver: &R) -> Result<(), ResolveError> {
let record = resolver
.resolve(self.id())
.await
.map_err(|err| ResolveError::new(self.id(), anyhow::Error::new(err)))?;
*self = Self::Resolved(record);
Ok(())
}
pub async fn into_resolved<R: Resolver>(mut self, resolver: &R) -> Result<Self, ResolveError> {
self.resolve(resolver).await?;
Ok(self)
}
pub fn set_resolved(&mut self, record: Record<T>) {
*self = Self::Resolved(record)
}
}