sim_lib_doc_core/
model.rs1use sim_kernel::{Cx, Object, Result, Value};
4
5pub const DOC_KIND_ARTICLE: &str = "article";
7pub const DOC_KIND_REPORT: &str = "report";
9pub const DOC_KIND_README: &str = "readme";
11
12#[derive(Clone, Debug, PartialEq)]
14pub struct Doc {
15 pub kind: DocKind,
17 pub id: DocId,
19 pub body: Value,
21 pub origin: Vec<ExternalRef>,
23}
24
25impl Doc {
26 #[must_use]
28 pub fn new(kind: DocKind, id: DocId, body: Value, origin: Vec<ExternalRef>) -> Self {
29 Self {
30 kind,
31 id,
32 body,
33 origin,
34 }
35 }
36}
37
38impl Object for Doc {
39 fn display(&self, _cx: &mut Cx) -> Result<String> {
40 Ok(format!("#<doc {} {}>", self.kind.0, self.id.0))
41 }
42
43 fn as_any(&self) -> &dyn std::any::Any {
44 self
45 }
46}
47
48impl sim_kernel::ObjectCompat for Doc {}
49
50#[derive(
52 Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize,
53)]
54pub struct DocKind(pub String);
55
56impl DocKind {
57 #[must_use]
59 pub fn new(kind: impl Into<String>) -> Self {
60 Self(kind.into())
61 }
62
63 #[must_use]
65 pub fn as_str(&self) -> &str {
66 &self.0
67 }
68}
69
70#[derive(
72 Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize,
73)]
74pub struct DocId(pub String);
75
76impl DocId {
77 #[must_use]
79 pub fn new(id: impl Into<String>) -> Self {
80 Self(id.into())
81 }
82
83 #[must_use]
85 pub fn as_str(&self) -> &str {
86 &self.0
87 }
88}
89
90#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
92pub struct ExternalRef {
93 pub backend: String,
95 pub external_id: String,
97 pub version: Option<String>,
99 pub web_url: Option<String>,
101}
102
103impl ExternalRef {
104 #[must_use]
106 pub fn new(
107 backend: impl Into<String>,
108 external_id: impl Into<String>,
109 version: Option<String>,
110 web_url: Option<String>,
111 ) -> Self {
112 Self {
113 backend: backend.into(),
114 external_id: external_id.into(),
115 version,
116 web_url,
117 }
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn doc_json_round_trip() {
127 let refs = vec![ExternalRef::new(
128 "codec/plain",
129 "doc-1",
130 Some("rev-2".to_owned()),
131 Some("https://example.com/doc-1".to_owned()),
132 )];
133 let encoded = serde_json::to_string(&refs).unwrap();
134 let decoded: Vec<ExternalRef> = serde_json::from_str(&encoded).unwrap();
135 assert_eq!(decoded, refs);
136 }
137
138 #[test]
139 fn prose_kind_constants_are_reserved() {
140 assert_eq!(DocKind::new(DOC_KIND_ARTICLE).as_str(), "article");
141 assert_eq!(DocKind::new(DOC_KIND_REPORT).as_str(), "report");
142 assert_eq!(DocKind::new(DOC_KIND_README).as_str(), "readme");
143 }
144}