Skip to main content

wip_protocol/
model.rs

1use std::collections::BTreeMap;
2
3use crate::{ProtocolError, ValidationError};
4
5/// Human-readable plain-text documentation attached to a protocol declaration.
6#[derive(Debug, Clone, PartialEq, Eq, Default)]
7pub struct Documentation {
8    /// A short, self-contained description.
9    pub summary: String,
10    /// Optional extended documentation.
11    pub details: Option<String>,
12}
13
14/// The protocol projection currently published at one Worldspace path.
15///
16/// `name` is a path segment, `interfaces` is an ordered set of opaque interface
17/// references, `r#ref` is optional object identity, and `validator` is an
18/// independent optional observation precondition. In particular, neither the
19/// path nor `r#ref` is a mandatory object identifier.
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct Object {
22    /// Path-segment name. The root object's name is empty.
23    pub name: String,
24    /// Short public description of the object.
25    pub description: Option<String>,
26    /// Opaque interface references in host publication order.
27    pub interfaces: Vec<String>,
28    /// Optional opaque identity within one client-facing Worldspace.
29    pub r#ref: Option<String>,
30    /// Optional opaque validator for the object's observed state.
31    pub validator: Option<Vec<u8>>,
32}
33
34/// Transport-independent description of one interface.
35///
36/// Interface identity is supplied by interaction fields such as
37/// [`FetchInterfaceResponse::interface`], not embedded in the descriptor.
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct InterfaceDescriptor {
40    /// Descriptor format version understood by clients and hosts.
41    pub format: String,
42    /// Optional interface documentation.
43    pub documentation: Option<Documentation>,
44    /// Named declarations local to this descriptor.
45    pub types: Vec<TypeDeclaration>,
46    /// Operations exposed by this interface.
47    pub operations: Vec<OperationDeclaration>,
48}
49
50/// A descriptor-local named type declaration.
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct TypeDeclaration {
53    /// Descriptor-local type name.
54    pub name: String,
55    /// Optional type documentation.
56    pub documentation: Option<Documentation>,
57    /// Definition associated with `name`.
58    pub definition: TypeExpr,
59}
60
61/// A type expression used by declarations, fields, parameters, and returns.
62///
63/// [`TypeExpr::Named`] references are resolved only within the containing
64/// descriptor. Recursive references, including recursion through lists,
65/// records, and unions, are invalid.
66#[derive(Debug, Clone, PartialEq, Eq)]
67pub enum TypeExpr {
68    /// A value carrying no data.
69    Unit,
70    /// A boolean.
71    Boolean,
72    /// A JavaScript-lossless signed integer.
73    Integer,
74    /// A finite IEEE-754 binary64 number.
75    Number,
76    /// A Unicode string.
77    String,
78    /// An opaque byte sequence.
79    Bytes,
80    /// A schema-opaque JSON-compatible value tree.
81    Json,
82    /// A canonical absolute Worldspace path represented by a string value.
83    Entry,
84    /// A descriptor-local named declaration.
85    Named {
86        /// Referenced declaration name.
87        name: String,
88    },
89    /// A record with named fields.
90    Record {
91        /// Fields in declaration order.
92        fields: Vec<FieldDeclaration>,
93    },
94    /// An ordered list.
95    List {
96        /// Type of every list item.
97        items: Box<TypeExpr>,
98    },
99    /// A closed set of payload-free cases represented by strings.
100    Enum {
101        /// Cases in declaration order.
102        cases: Vec<EnumCase>,
103    },
104    /// A discriminated union represented by a record.
105    Union {
106        /// Cases in declaration order.
107        cases: Vec<UnionCase>,
108    },
109}
110
111/// Declaration of a record field.
112#[derive(Debug, Clone, PartialEq, Eq)]
113pub struct FieldDeclaration {
114    /// Field name.
115    pub name: String,
116    /// Whether the field must be present.
117    pub required: bool,
118    /// Optional field documentation.
119    pub documentation: Option<Documentation>,
120    /// Field value type.
121    pub r#type: TypeExpr,
122}
123
124/// One payload-free enum case.
125#[derive(Debug, Clone, PartialEq, Eq)]
126pub struct EnumCase {
127    /// Case name.
128    pub name: String,
129    /// Optional case documentation.
130    pub documentation: Option<Documentation>,
131}
132
133/// One union case with zero or one payload.
134#[derive(Debug, Clone, PartialEq, Eq)]
135pub struct UnionCase {
136    /// Case name.
137    pub name: String,
138    /// Optional case documentation.
139    pub documentation: Option<Documentation>,
140    /// Optional payload type.
141    pub payload: Option<TypeExpr>,
142}
143
144/// Declaration of one interface operation.
145#[derive(Debug, Clone, PartialEq, Eq)]
146pub struct OperationDeclaration {
147    /// Operation name, unique within its descriptor.
148    pub name: String,
149    /// Optional operation documentation.
150    pub documentation: Option<Documentation>,
151    /// Parameters in declaration order.
152    pub parameters: Vec<ParameterDeclaration>,
153    /// Return declaration. No-data operations return [`TypeExpr::Unit`].
154    pub returns: ReturnDeclaration,
155}
156
157/// Declaration of one operation parameter.
158#[derive(Debug, Clone, PartialEq, Eq)]
159pub struct ParameterDeclaration {
160    /// Parameter name.
161    pub name: String,
162    /// Whether the parameter must be present.
163    pub required: bool,
164    /// Optional parameter documentation.
165    pub documentation: Option<Documentation>,
166    /// Parameter value type.
167    pub r#type: TypeExpr,
168}
169
170/// Declaration of an operation return value.
171#[derive(Debug, Clone, PartialEq, Eq)]
172pub struct ReturnDeclaration {
173    /// Optional return-value documentation.
174    pub documentation: Option<Documentation>,
175    /// Return value type.
176    pub r#type: TypeExpr,
177}
178
179/// A schema-neutral logical protocol value.
180///
181/// Enum cases, union cases, entries, and JSON are interpretations imposed by a
182/// descriptor. They are deliberately not variants of this enum. Record key
183/// ordering is not protocol-significant.
184#[derive(Debug, Clone, PartialEq)]
185pub enum Value {
186    /// A value carrying no data; it also represents JSON null under `Json`.
187    Unit,
188    /// A boolean.
189    Boolean(bool),
190    /// A JavaScript-lossless integer.
191    Integer(i64),
192    /// A finite IEEE-754 binary64 number.
193    Number(f64),
194    /// A Unicode string.
195    String(String),
196    /// An opaque byte sequence.
197    Bytes(Vec<u8>),
198    /// String-keyed fields with order-insensitive semantics.
199    Record(BTreeMap<String, Value>),
200    /// An ordered sequence.
201    List(Vec<Value>),
202}
203
204impl Value {
205    /// Returns the structural kind used by validation diagnostics.
206    #[must_use]
207    pub fn kind(&self) -> crate::ValueKind {
208        match self {
209            Self::Unit => crate::ValueKind::Unit,
210            Self::Boolean(_) => crate::ValueKind::Boolean,
211            Self::Integer(_) => crate::ValueKind::Integer,
212            Self::Number(_) => crate::ValueKind::Number,
213            Self::String(_) => crate::ValueKind::String,
214            Self::Bytes(_) => crate::ValueKind::Bytes,
215            Self::Record(_) => crate::ValueKind::Record,
216            Self::List(_) => crate::ValueKind::List,
217        }
218    }
219}
220
221/// Request for the object currently published at one path and its indexable descendants.
222#[derive(Debug, Clone, PartialEq, Eq)]
223pub struct ObserveRequest {
224    /// Canonical absolute path of the observation root.
225    pub path: String,
226    /// Maximum observed depth, where the requested object has depth zero.
227    pub depth: u32,
228}
229
230/// One node in an object observation.
231#[derive(Debug, Clone, PartialEq, Eq)]
232pub struct ObjectObservation {
233    /// Object observed at this Worldspace position.
234    pub object: Object,
235    /// Complete direct children when observed, or `None` at the requested depth boundary.
236    pub children: Option<Vec<ObjectObservation>>,
237}
238
239/// Successful `observe` response.
240pub type ObserveResponse = ObjectObservation;
241
242/// Request for the current descriptor of one opaque interface reference.
243#[derive(Debug, Clone, PartialEq, Eq)]
244pub struct FetchInterfaceRequest {
245    /// Opaque interface reference obtained from an object.
246    pub interface: String,
247}
248
249/// Successful `fetch_interface` response.
250#[derive(Debug, Clone, PartialEq, Eq)]
251pub struct FetchInterfaceResponse {
252    /// Opaque interface reference corresponding to the request.
253    pub interface: String,
254    /// Current validated descriptor.
255    pub descriptor: InterfaceDescriptor,
256    /// Optional opaque validator for this descriptor observation.
257    pub validator: Option<Vec<u8>>,
258}
259
260/// Object portion of an operation target.
261#[derive(Debug, Clone, PartialEq, Eq)]
262pub struct Target {
263    /// Canonical absolute path of the target object.
264    pub path: String,
265    /// Optional validator copied from the object observation.
266    pub validator: Option<Vec<u8>>,
267}
268
269/// Interface portion of an operation target.
270#[derive(Debug, Clone, PartialEq, Eq)]
271pub struct InterfaceTarget {
272    /// Opaque interface reference selected from the object's interface set.
273    pub reference: String,
274    /// Optional validator copied from the interface observation.
275    pub validator: Option<Vec<u8>>,
276}
277
278/// Transport-independent request to execute one operation.
279#[derive(Debug, Clone, PartialEq)]
280pub struct CallOperationRequest {
281    /// Path and optional object-state precondition.
282    pub target: Target,
283    /// Interface reference and its independent optional precondition.
284    pub interface: InterfaceTarget,
285    /// Operation name within the selected descriptor.
286    pub operation: String,
287    /// Named arguments; map iteration order has no protocol meaning.
288    pub arguments: BTreeMap<String, Value>,
289}
290
291/// Successful operation response.
292#[derive(Debug, Clone, PartialEq)]
293pub struct CallOperationResponse {
294    /// Application result validated against the operation return declaration.
295    pub result: Value,
296    /// Optional validator for the object state observed after execution.
297    pub validator: Option<Vec<u8>>,
298}
299
300/// Logical outcome of any core interaction.
301#[derive(Debug, Clone, PartialEq, Eq)]
302pub enum ProtocolResult<T> {
303    /// The interaction succeeded.
304    Success(T),
305    /// The interaction failed at the protocol boundary.
306    Failure(ProtocolError),
307}
308
309impl Object {
310    /// Validates the object-independent name and ordered-interface-set rules.
311    pub fn validate(&self) -> Result<(), ValidationError> {
312        crate::validation::validate_object(self)
313    }
314
315    /// Validates this object as the response observed at `path`.
316    pub fn validate_at_path(&self, path: &str) -> Result<(), ValidationError> {
317        crate::validation::validate_object_at_path(self, path)
318    }
319
320    /// Validates equal representations for a shared ref and present validator.
321    pub fn validate_consistency_with(&self, other: &Self) -> Result<(), ValidationError> {
322        crate::validation::validate_object_consistency(self, other)
323    }
324}
325
326impl InterfaceDescriptor {
327    /// Validates declaration structure, named references, and absence of cycles.
328    pub fn validate(&self) -> Result<(), ValidationError> {
329        crate::validation::validate_descriptor(self)
330    }
331
332    /// Validates a raw value against a type expression in this descriptor.
333    pub fn validate_value(&self, r#type: &TypeExpr, value: &Value) -> Result<(), ValidationError> {
334        crate::validation::validate_root_value(self, r#type, value)
335    }
336
337    /// Validates named arguments for one declared operation.
338    pub fn validate_arguments(
339        &self,
340        operation: &str,
341        arguments: &BTreeMap<String, Value>,
342    ) -> Result<(), ValidationError> {
343        crate::validation::validate_arguments(self, operation, arguments)
344    }
345
346    /// Validates one operation result against its return declaration.
347    pub fn validate_result(&self, operation: &str, result: &Value) -> Result<(), ValidationError> {
348        crate::validation::validate_result(self, operation, result)
349    }
350
351    /// Validates the path, operation, and arguments in a call request.
352    pub fn validate_call(&self, request: &CallOperationRequest) -> Result<(), ValidationError> {
353        crate::validation::validate_call(self, request)
354    }
355}
356
357impl ObserveRequest {
358    /// Validates the request path.
359    pub fn validate(&self) -> Result<(), ValidationError> {
360        crate::validation::validate_path(&self.path)
361    }
362
363    /// Validates observation shape, names, and requested depth.
364    ///
365    /// Failure means the Client received an invalid success response; it is not a
366    /// Host-returned [`crate::ProtocolErrorCode`].
367    pub fn validate_response(&self, response: &ObserveResponse) -> Result<(), ValidationError> {
368        crate::validation::validate_observe_response(response, self)
369    }
370}
371
372impl FetchInterfaceResponse {
373    /// Validates request correspondence and descriptor semantics.
374    ///
375    /// Failure means the Client received an invalid success response; it is not a
376    /// Host-returned [`crate::ProtocolErrorCode`]. Descriptor format support is a
377    /// separate Client concern: an otherwise valid descriptor with an unsupported
378    /// `format` is a Client-local `UnsupportedDescriptorFormat`.
379    pub fn validate_for(&self, request: &FetchInterfaceRequest) -> Result<(), ValidationError> {
380        crate::validation::validate_fetch_interface_response(self, request)
381    }
382}
383
384impl CallOperationRequest {
385    /// Validates this call against the descriptor selected by `interface`.
386    pub fn validate_with(&self, descriptor: &InterfaceDescriptor) -> Result<(), ValidationError> {
387        descriptor.validate_call(self)
388    }
389}
390
391impl CallOperationResponse {
392    /// Validates this result against the named operation in `descriptor`.
393    ///
394    /// Failure means the Client received an invalid success response; it is not a
395    /// Host-returned [`crate::ProtocolErrorCode`].
396    pub fn validate_for(
397        &self,
398        descriptor: &InterfaceDescriptor,
399        operation: &str,
400    ) -> Result<(), ValidationError> {
401        descriptor.validate_result(operation, &self.result)
402    }
403}