jacquard_common/types.rs
1use serde::{Deserialize, Serialize};
2
3// Re-export Lazy from crate root for submodule use via `super::Lazy`
4pub use crate::Lazy;
5
6/// AT Protocol URI (at://) types and validation
7pub mod aturi;
8/// Blob references for binary data
9pub mod blob;
10/// Content Identifier (CID) types for IPLD
11pub mod cid;
12/// Repository collection trait for records
13pub mod collection;
14pub mod crypto;
15/// AT Protocol datetime string type
16pub mod datetime;
17/// Decentralized Identifier (DID) types and validation
18pub mod did;
19/// DID Document types and helpers
20pub mod did_doc;
21/// DID service audience types and validation.
22pub mod did_service;
23/// AT Protocol handle types and validation
24pub mod handle;
25/// AT Protocol identifier types (handle or DID)
26pub mod ident;
27pub mod integer;
28/// Language tag types per BCP 47
29pub mod language;
30/// Namespaced Identifier (NSID) types and validation
31pub mod nsid;
32/// Record key types and validation
33pub mod recordkey;
34/// Scope action and resource enums for AT Protocol OAuth
35pub mod scope_primitives;
36/// String types with format validation
37pub mod string;
38/// Timestamp Identifier (TID) types and generation
39pub mod tid;
40/// URI types with scheme validation
41pub mod uri;
42/// Generic data value types for lexicon data model
43pub mod value;
44
45/// Trait for a constant string literal type
46pub trait Literal: Clone + Copy + PartialEq + Eq + Send + Sync + 'static {
47 /// The string literal
48 const LITERAL: &'static str;
49}
50
51/// top-level domains which are not allowed in at:// handles or dids
52pub const DISALLOWED_TLDS: &[&str] = &[
53 ".local",
54 ".arpa",
55 ".invalid", // NOTE: if someone has a screwed up handle, this is what's returned
56 ".localhost",
57 ".internal",
58 ".example",
59 ".alt",
60 // policy could concievably change on ".onion" some day
61 ".onion",
62 // NOTE: .test is allowed in testing and devopment. In practical terms
63 // "should" "never" actually resolve and get registered in production
64];
65
66/// checks if a string ends with anything from the provided list of strings.
67pub fn ends_with(string: impl AsRef<str>, list: &[&str]) -> bool {
68 let string = string.as_ref();
69 for item in list {
70 if string.ends_with(item) {
71 return true;
72 }
73 }
74 false
75}
76
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
78#[serde(rename_all = "kebab-case")]
79/// Valid types in the AT protocol [data model](https://atproto.com/specs/data-model). Type marker only, used in concert with `[Data<'_>]`.
80pub enum DataModelType {
81 /// Null type. IPLD type `null`, JSON type `Null`, CBOR Special Value (major 7)
82 Null,
83 /// Boolean type. IPLD type `boolean`, JSON type Boolean, CBOR Special Value (major 7)
84 Boolean,
85 /// Integer type. IPLD type `integer`, JSON type Number, CBOR Special Value (major 7)
86 Integer,
87 /// Byte type. IPLD type `bytes`, in JSON a `{ "$bytes": bytes }` Object, CBOR Byte String (major 2)
88 Bytes,
89 /// CID (content identifier) link. IPLD type `link`, in JSON a `{ "$link": cid }` Object, CBOR CID (tag 42)
90 CidLink,
91 /// Blob type. No special IPLD type. in JSON a `{ "$type": "blob" }` Object. in CBOR a `{ "$type": "blob" }` Map.
92 Blob,
93 /// Array type. IPLD type `list`. JSON type `Array`, CBOR type Array (major 4)
94 Array,
95 /// Object type. IPLD type `map`. JSON type `Object`, CBOR type Map (major 5). keys are always SmolStr.
96 Object,
97 #[serde(untagged)]
98 /// String type (lots of variants). JSON String, CBOR UTF-8 String (major 3)
99 String(LexiconStringType),
100}
101
102impl core::fmt::Display for DataModelType {
103 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
104 match self {
105 DataModelType::Null => write!(f, "null"),
106 DataModelType::Boolean => write!(f, "boolean"),
107 DataModelType::Integer => write!(f, "integer"),
108 DataModelType::Bytes => write!(f, "bytes"),
109 DataModelType::CidLink => write!(f, "cid-link"),
110 DataModelType::Blob => write!(f, "blob"),
111 DataModelType::Array => write!(f, "array"),
112 DataModelType::Object => write!(f, "object"),
113 DataModelType::String(s) => write!(f, "{}", s),
114 }
115 }
116}
117
118/// Lexicon string format types for typed strings in the AT Protocol data model
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
120#[serde(rename_all = "kebab-case")]
121pub enum LexiconStringType {
122 /// ISO 8601 datetime string
123 Datetime,
124 /// AT Protocol URI (at://)
125 AtUri,
126 /// Decentralized Identifier
127 Did,
128 /// AT Protocol handle
129 Handle,
130 /// Handle or DID
131 AtIdentifier,
132 /// Namespaced Identifier
133 Nsid,
134 /// Content Identifier
135 Cid,
136 /// BCP 47 language tag
137 Language,
138 /// Timestamp Identifier
139 Tid,
140 /// Record key
141 RecordKey,
142 /// URI with type constraint
143 Uri(UriType),
144 /// Plain string
145 #[serde(untagged)]
146 String,
147}
148
149impl core::fmt::Display for LexiconStringType {
150 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
151 match self {
152 LexiconStringType::Datetime => write!(f, "datetime"),
153 LexiconStringType::AtUri => write!(f, "at-uri"),
154 LexiconStringType::Did => write!(f, "did"),
155 LexiconStringType::Handle => write!(f, "handle"),
156 LexiconStringType::AtIdentifier => write!(f, "at-identifier"),
157 LexiconStringType::Nsid => write!(f, "nsid"),
158 LexiconStringType::Cid => write!(f, "cid"),
159 LexiconStringType::Language => write!(f, "language"),
160 LexiconStringType::Tid => write!(f, "tid"),
161 LexiconStringType::RecordKey => write!(f, "record-key"),
162 LexiconStringType::Uri(u) => write!(f, "uri({})", u),
163 LexiconStringType::String => write!(f, "string"),
164 }
165 }
166}
167
168/// URI scheme types for lexicon URI format constraints
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
170#[serde(tag = "type")]
171pub enum UriType {
172 /// DID URI (did:)
173 Did,
174 /// AT Protocol URI (at://)
175 At,
176 /// HTTPS URI
177 Https,
178 /// WebSocket Secure URI
179 Wss,
180 /// CID URI
181 Cid,
182 /// DNS name
183 Dns,
184 /// Any valid URI
185 Any,
186}
187
188impl core::fmt::Display for UriType {
189 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
190 match self {
191 UriType::Did => write!(f, "did"),
192 UriType::At => write!(f, "at"),
193 UriType::Https => write!(f, "https"),
194 UriType::Wss => write!(f, "wss"),
195 UriType::Cid => write!(f, "cid"),
196 UriType::Dns => write!(f, "dns"),
197 UriType::Any => write!(f, "any"),
198 }
199 }
200}