ridl_rt/port.rs
1//! The ports: the traits a runtime implements and generated code calls.
2//!
3//! Every port method returns without waiting. Waiting — blocking, `async`, or
4//! a loop that drives the runtime — belongs to a face over a port, and this
5//! crate defines no face. A port carries interface numbers, ordinals and
6//! bytes, never a payload type: the generated binding decodes. No port method
7//! takes the current time; a runtime reads its own [`Clock`].
8//!
9//! A port is attached to one catalog ([`Attached`]), and the interface numbers
10//! and ordinals its methods take are scoped by that catalog.
11//!
12//! [`ScannableSignals`] and [`CoherentSignals`] are extensions. They describe
13//! mechanisms some runtimes have, not interaction semantics every runtime must
14//! present, so a runtime may omit them. [`Wakeable`] is an extension too: it
15//! is how a face that waits learns when to read a port again, and a runtime
16//! that serves a generated async client implements it.
17//!
18//! Each trait below names the generated method it backs, so a reader who
19//! arrived from generated code can find the port under it. The crate-level
20//! documentation has the whole table, and
21//! `docs/technotes/ridl-rt-by-example.md` in this repository walks it against
22//! concrete generated code.
23
24use core::task::Waker;
25
26use crate::contract::{CatalogRef, InterfaceNo, Ordinal};
27use crate::error::{CallError, Contract};
28use crate::sample::{Duration, Envelope, Freshness, Provenance, Timestamp};
29
30/// A port attached to one catalog.
31pub trait Attached {
32 /// The catalog this port serves.
33 fn catalog(&self) -> &CatalogRef;
34}
35
36/// The clock envelopes are stamped from. A runtime has one.
37pub trait Clock {
38 /// The current time in the platform time base.
39 fn now(&self) -> Timestamp;
40}
41
42/// Signals, consumer side.
43///
44/// A generated `Client` has one method per signal over this port. It reads
45/// into a stack buffer sized from the payload's
46/// [`MAX_SIZE`](crate::payload::Payload::MAX_SIZE), checks the bytes, and
47/// returns a [`Sample`](crate::sample::Sample). Bytes that fail their check
48/// are not an error there: the sample carries the channel's init value and a
49/// provenance of [`Invalid`](crate::sample::Provenance::Invalid), so the
50/// [`ReadError`] here reports the read itself.
51pub trait SignalReader: Attached {
52 /// Copies the signal's current value into the front of `out` and returns
53 /// its provenance, its freshness and its envelope. The runtime resolves
54 /// both the provenance and the freshness.
55 ///
56 /// A sample whose provenance is `Init` or `Invalid(Declared)` may carry
57 /// zero bytes, because the runtime has no value to copy; `len` is then 0,
58 /// and a generated face returns the channel's init value under that
59 /// provenance (ADR-0021 decision 17).
60 ///
61 /// Returns `ReadError::Short` when `out` is shorter than the value.
62 fn read(
63 &self,
64 iface: InterfaceNo,
65 ord: Ordinal,
66 out: &mut [u8],
67 ) -> Result<RawSample, ReadError>;
68}
69
70/// What [`SignalReader::read`] returns beside the copied bytes.
71#[derive(Clone, Copy, Debug, PartialEq, Eq)]
72pub struct RawSample {
73 /// Where the value comes from.
74 pub provenance: Provenance,
75 /// How old the value is.
76 pub freshness: Freshness,
77 /// The sender's timestamp and sequence number.
78 pub envelope: Envelope,
79 /// The number of bytes copied into `out`.
80 pub len: usize,
81}
82
83/// Signals, provider side.
84///
85/// `set`, `invalidate` and `touch` stage a change. Each fails with
86/// [`WriteError::Contract`] when the ordinal names no member, and with
87/// [`WriteError::NotOwner`] when it names a member this provider does not
88/// own. `commit` publishes every staged change, with one generation
89/// increment and one timestamp per interface, taken from the runtime's
90/// [`Clock`].
91///
92/// A generated `Publisher` has one method per signal over `set`, plus an
93/// `invalidate_<name>` and a `commit`. The staging split is why a provider
94/// that updates several signals of one interface and then commits produces one
95/// coherent publication rather than several.
96pub trait SignalWriter: Attached {
97 /// Stages a new value.
98 fn set(&mut self, iface: InterfaceNo, ord: Ordinal, bytes: &[u8]) -> Result<(), WriteError>;
99 /// Stages the invalid state (ridl §4.5), with
100 /// [`Cause::Declared`](crate::sample::Cause::Declared).
101 fn invalidate(&mut self, iface: InterfaceNo, ord: Ordinal) -> Result<(), WriteError>;
102 /// Stages a re-affirmation of the current value, without a new value.
103 fn touch(&mut self, iface: InterfaceNo, ord: Ordinal) -> Result<(), WriteError>;
104 /// Publishes everything staged. It cannot fail, so it reports nothing —
105 /// including that the runtime behind the port is gone. A caller learns
106 /// that from [`WriteError::Detached`] on a later `set`, `invalidate` or
107 /// `touch`, never from that `commit`. What becomes of the changes staged
108 /// before a commit whose runtime has already detached is not fixed here.
109 fn commit(&mut self);
110}
111
112/// Events, consumer side.
113///
114/// A generated `Client` has a `subscribe_<name>` per event, but a single
115/// `next_event` for the whole interface, because [`next`](EventSource::next)
116/// returns the next occurrence of anything subscribed and the payload type is
117/// not known until its ordinal has been read. The generated method routes on
118/// that ordinal into an enum with one variant per event.
119pub trait EventSource: Attached {
120 /// Starts delivery of the listed events.
121 fn subscribe(&mut self, iface: InterfaceNo, ords: &[Ordinal]) -> Result<(), SubscribeError>;
122 /// Stops delivery of the listed events.
123 fn unsubscribe(&mut self, iface: InterfaceNo, ords: &[Ordinal]);
124 /// Copies the next occurrence into the front of `out`. `Ok(None)` when no
125 /// occurrence is waiting.
126 ///
127 /// Occurrences come in order, and a gap in `seq` is a loss (ridl §3.1). An
128 /// occurrence older than its time to live is discarded here (ridl §5.2).
129 /// `ReadError::Short` does not consume the occurrence: the next call
130 /// returns the same one.
131 fn next(&mut self, out: &mut [u8]) -> Result<Option<RawOccurrence>, ReadError>;
132}
133
134/// What [`EventSource::next`] returns beside the copied bytes.
135#[derive(Clone, Copy, Debug, PartialEq, Eq)]
136pub struct RawOccurrence {
137 /// The interface of the event.
138 pub iface: InterfaceNo,
139 /// The ordinal of the event.
140 pub ord: Ordinal,
141 /// The sender's timestamp and sequence number.
142 pub envelope: Envelope,
143 /// The number of bytes copied into `out`.
144 pub len: usize,
145}
146
147/// Events, provider side.
148///
149/// A generated `Publisher` has one method per event over this port. Unlike a
150/// signal, an occurrence is not staged and there is no `commit`: there is no
151/// coherent set to assemble.
152pub trait EventSink: Attached {
153 /// Raises one occurrence.
154 fn raise(&mut self, iface: InterfaceNo, ord: Ordinal, bytes: &[u8]) -> Result<(), RaiseError>;
155}
156
157/// Calls, consumer side.
158///
159/// A command and a query are separate methods, because their outcomes differ
160/// (ridl §6, §7).
161///
162/// A generated `Client` has one method per command and query over this port,
163/// each returning a named future rather than an outcome, because nothing
164/// here waits. The method sends when it is called; the future's `poll` reads
165/// the outcome — [`ack`](Caller::ack) for a command, [`reply`](Caller::reply)
166/// for a query — and calls [`forget`](Caller::forget) when it leaves the
167/// waiting phase. A `require` clause is evaluated before sending, so a
168/// failing precondition costs no round trip and is reported as
169/// [`SendError::Contract`].
170pub trait Caller: Attached {
171 /// Sends a command and returns the correlation of its outcome.
172 fn command(
173 &mut self,
174 iface: InterfaceNo,
175 ord: Ordinal,
176 args: &[u8],
177 ) -> Result<Correlation, SendError>;
178 /// Sends a query and returns the correlation of its reply.
179 fn query(
180 &mut self,
181 iface: InterfaceNo,
182 ord: Ordinal,
183 args: &[u8],
184 ) -> Result<Correlation, SendError>;
185 /// A command's delivery acknowledgment (ridl §6.1), once it is known:
186 /// `Ok(())` when accepted, `Err(CallError::Contract(_))` when rejected,
187 /// `Err(CallError::Transport(Transport::Corrupt))` when the provider could
188 /// not read the command's argument bytes,
189 /// `Err(CallError::Transport(Transport::Busy))` when the providing runtime
190 /// refused the command at admission, and
191 /// `Err(CallError::Transport(Transport::Undelivered))` when no
192 /// acknowledgment came within the bound. `None` while unknown, and always
193 /// `None` for a query's correlation.
194 ///
195 /// `None` has two causes this method does not separate: the acknowledgment
196 /// is not known yet, and `c` is a query's correlation, for which `None` is
197 /// the standing answer. A caller that polls `ack` for a query's
198 /// correlation therefore never finishes. The return carries no error, so
199 /// keep the correlations [`command`](Caller::command) returned and ask
200 /// only about those. After [`forget`](Caller::forget) a correlation's
201 /// outcome is no longer retrievable, so do not ask about it.
202 fn ack(&mut self, c: Correlation) -> Option<Result<(), CallError>>;
203 /// A query's reply, once it is known: the reply bytes copied into the front
204 /// of `out` and their length, or the error. `Ok(None)` while unknown.
205 /// `ReadError::Short` does not consume the reply.
206 ///
207 /// The outer [`ReadError`] reports the port call itself: `Short` when
208 /// `out` is too short, and `Detached` when the local runtime is gone.
209 /// `reply` never returns `ReadError::Contract`. The inner [`CallError`] is
210 /// the outcome from the peer or the transport, such as a contract error
211 /// the provider settled, or `Transport::Down` when the connection to the
212 /// peer is lost.
213 fn reply(
214 &mut self,
215 c: Correlation,
216 out: &mut [u8],
217 ) -> Result<Option<Result<usize, CallError>>, ReadError>;
218 /// Releases a correlation whose outcome the caller no longer needs.
219 fn forget(&mut self, c: Correlation);
220}
221
222/// Identifies one sent call to its caller.
223#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
224pub struct Correlation(pub u64);
225
226/// Calls, provider side.
227///
228/// `next_claim` presents each delivered call once. A retransmission of a call
229/// already presented is not presented again and receives the cached
230/// acknowledgment. Two calls are presented again. One is a claim a dropped
231/// handler held and did not settle: the runtime returns it to the waiting
232/// calls, so another handler that serves the member can take it, as many
233/// times as a holder is dropped (ADR-0021 decision 5). The other is a claim
234/// offered through [`ReadError::ShortClaim`], which stays the next call, under
235/// the same id, until it is read with a large enough buffer or settled by
236/// that id (decision 5, amended 2026-09-28). Calls from two callers are never
237/// merged, even when they carry the same `seq`. A call lost in transport is never presented. The
238/// caller of a lost command sees `Transport::Undelivered` from `Caller::ack`;
239/// the caller of a lost query sees `Transport::Timeout` from `Caller::reply`
240/// once the response bound passes.
241///
242/// Every claim is settled. For a command, the generated dispatch settles
243/// `Ok(&[])` after the arguments and `require` pass, before application code
244/// runs. For a query, it settles with the reply bytes or the outcome the
245/// caller sees.
246///
247/// An application implements neither this trait nor a claim loop. It
248/// implements the generated `Provider` trait and polls the future the
249/// generated `serve` returns, which on each poll makes one pass over the
250/// claims already waiting, routes each by ordinal, decodes, evaluates
251/// `require`, calls the provider, evaluates a query's `ensure`, and settles.
252/// That future resolves in two cases only: at once, when this port's `serve`
253/// refused the members, and later, when this port fails.
254pub trait Handler: Attached {
255 /// Starts presenting calls to the listed members.
256 fn serve(&mut self, iface: InterfaceNo, ords: &[Ordinal]) -> Result<(), ServeError>;
257 /// Copies the next call's arguments into the front of `out`. `Ok(None)`
258 /// when no call is waiting. When `out` is shorter than the next call's
259 /// arguments, returns [`ReadError::ShortClaim`] with that call's
260 /// `ClaimId` and the bytes it needs, and does not consume the call: a
261 /// later `next_claim` with a buffer of at least `needed` bytes presents
262 /// the same call under the same id. The id is assigned when the call is
263 /// first presented, whether through `ShortClaim` or through `Ok(Some)`,
264 /// and is unique in its channel. `next_claim` never returns
265 /// `ReadError::Short`.
266 fn next_claim(&mut self, out: &mut [u8]) -> Result<Option<Claim>, ReadError>;
267 /// Settles a claim with the reply bytes (empty for a command) or the
268 /// outcome the caller sees. A provider settles
269 /// [`CallError::Contract`] when the arguments break their typl
270 /// constraints, a `require` clause fails, or an `ensure` clause fails,
271 /// and `CallError::Transport(Transport::Corrupt)` when the argument
272 /// bytes fail the structure check.
273 ///
274 /// A claim presented through [`ReadError::ShortClaim`] is settled the
275 /// same way, with any outcome, although its arguments were never read:
276 /// `settle` does not distinguish a read claim from an unread one. The
277 /// settlement takes the call out of the waiting calls, so a later
278 /// `next_claim` does not present it.
279 fn settle(
280 &mut self,
281 claim: ClaimId,
282 outcome: Result<&[u8], CallError>,
283 ) -> Result<(), SettleError>;
284}
285
286/// One call presented to a provider.
287#[derive(Clone, Copy, Debug, PartialEq, Eq)]
288pub struct Claim {
289 /// Unique in its channel.
290 pub id: ClaimId,
291 /// The interface of the call.
292 pub iface: InterfaceNo,
293 /// The ordinal of the call. The descriptor at this ordinal gives the kind.
294 pub ord: Ordinal,
295 /// The caller's timestamp and sequence number. `seq` is unique for each
296 /// caller, not for each channel.
297 pub envelope: Envelope,
298 /// The time left before the response bound passes. `None` when the call
299 /// has no response bound (ridl §9.3).
300 pub remaining: Option<Duration>,
301 /// The number of argument bytes copied into `out`.
302 pub len: usize,
303}
304
305/// Identifies one claim to its provider.
306#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
307pub struct ClaimId(pub u64);
308
309/// `fixed`, consumer side (ridl §8).
310///
311/// The generated face carries no method over this port in this version: a
312/// `fixed` is provisioned rather than interacted with, so the emitter writes
313/// its descriptor and nothing else, and an application that needs a
314/// provisioned value calls [`read_fixed`](FixedReader::read_fixed) itself.
315/// There is no provider side either — a provisioned constant is supplied to
316/// the runtime, not published by application code.
317pub trait FixedReader: Attached {
318 /// Copies the provisioned value into the front of `out` and returns its
319 /// length.
320 fn read_fixed(
321 &self,
322 iface: InterfaceNo,
323 ord: Ordinal,
324 out: &mut [u8],
325 ) -> Result<usize, ReadError>;
326}
327
328/// Extension: signals in a store a consumer can walk. A runtime may omit it.
329pub trait ScannableSignals: SignalReader {
330 /// The interface's generation: a counter that each commit to the interface
331 /// increments.
332 ///
333 /// The return carries no error, so an interface the port's catalog does
334 /// not hold has no reserved answer: it gives a `u64` the caller cannot
335 /// tell from a real generation. Ask only about an interface of
336 /// [`catalog`](Attached::catalog).
337 fn generation(&self, iface: InterfaceNo) -> u64;
338 /// Writes the changes into `out`, interface by interface, in the order of
339 /// `marks`, and updates `marks`. An interface's changes are written all
340 /// together or not at all: when they do not fit in the rest of `out`,
341 /// none of them is written, that interface's mark is not updated, and
342 /// `scan` returns the number of entries written so far.
343 ///
344 /// The count alone does not say whether changes are still waiting, because
345 /// a return of 0 has two causes. To tell them apart, compare each mark
346 /// with its interface's [`generation`](ScannableSignals::generation) after
347 /// the call:
348 ///
349 /// - every mark's `generation` equals `generation(iface)` — nothing had
350 /// changed, and the scan is complete;
351 /// - some mark's `generation` is behind `generation(iface)` — that
352 /// interface's changes did not fit in `out`. When `scan` also returned
353 /// 0, `out` is shorter than the changes of the first such interface in
354 /// the order of `marks`, and no call can make progress until `out` is
355 /// longer.
356 ///
357 /// A caller that scans in a loop therefore grows `out` when `scan` returns
358 /// 0 and a mark is still behind its interface's generation.
359 fn scan(&self, marks: &mut [Watermark], out: &mut [Changed]) -> usize;
360}
361
362/// How far a consumer has scanned one interface.
363#[derive(Clone, Copy, Debug, PartialEq, Eq)]
364pub struct Watermark {
365 /// The interface.
366 pub iface: InterfaceNo,
367 /// The generation last scanned. Named `generation`, not `gen`, because
368 /// `gen` is a reserved keyword in the 2024 edition.
369 pub generation: u64,
370 /// The sequence number last scanned.
371 pub seq: u64,
372}
373
374/// A signal that changed since a [`Watermark`].
375#[derive(Clone, Copy, Debug, PartialEq, Eq)]
376pub struct Changed {
377 /// The interface of the signal.
378 pub iface: InterfaceNo,
379 /// The ordinal of the signal.
380 pub ord: Ordinal,
381 /// The signal's sequence number.
382 pub seq: u64,
383}
384
385/// Extension: reads of several signals of one interface from one publication.
386/// A runtime whose binding delivers each field separately cannot present this
387/// and omits it.
388pub trait CoherentSignals: SignalReader {
389 /// Answers every ordinal in `ords` from one publication. Copies the values
390 /// into `out` one after another, writes one `RawSample` for each ordinal
391 /// into `samples` in the order of `ords`, and returns the number of bytes
392 /// written to `out`.
393 ///
394 /// Returns `ReadError::Short` with the size the whole set needs when `out`
395 /// is too short, `ReadError::TooFewSamples` with the number of entries
396 /// `samples` needs when `samples` is shorter than `ords`, and
397 /// `ReadError::Contract(Contract::UnknownInteraction)` when an ordinal
398 /// names no member.
399 fn read_coherent(
400 &self,
401 iface: InterfaceNo,
402 ords: &[Ordinal],
403 out: &mut [u8],
404 samples: &mut [RawSample],
405 ) -> Result<usize, ReadError>;
406}
407
408/// Extension: a port that can wake a task. A runtime that serves a generated
409/// async client implements it.
410///
411/// No port method waits, so a task registers its interest here, reads the
412/// port, and returns when the read finds nothing; the runtime wakes the task
413/// when the thing it waits for may have changed, and the task reads the port
414/// again.
415///
416/// The contract:
417///
418/// - **One waker per kind of key per handle.** [`wake_on`](Wakeable::wake_on)
419/// stores a clone of `waker` on the handle it is called on, one for each
420/// kind — `Slot`, `Event`, `Claim` — and an `Outcome` waker with its call.
421/// A change to any key of that kind that the handle observes wakes the
422/// stored waker, so a task that registers `Event(a)` and then `Event(b)` is
423/// woken by an occurrence of either; the task reads the port again and
424/// finds out which.
425/// - **A refresh or a displacement.** A `wake_on` whose waker
426/// [`will_wake`](Waker::will_wake) the stored one is a refresh:
427/// it replaces the stored waker without waking it, because a task
428/// registers on every poll and waking it for its own registration would
429/// schedule the next poll from every poll. A waker of another task
430/// displaces the stored one, and the displaced waker is woken, so no task
431/// waits on a registration that can no longer fire. A second task waiting
432/// for the same events holds a second handle, and each handle's waiter is
433/// woken.
434/// - **Woken at most once.** A stored waker is woken after every change of
435/// its kind becomes visible, and is cleared when woken. A spurious wake is
436/// allowed: a runtime with one unkeyed "something changed" source may wake
437/// every waiter it holds on any change.
438/// - **Register, then read.** The caller registers on every poll, and
439/// registers before it reads the port, so a change between the read and
440/// the return still wakes it.
441///
442/// [`Interest::Event`] and [`Interest::Claim`] are keyed per interface,
443/// because [`EventSource::next`] and [`Handler::next_claim`] drain one queue
444/// whatever the ordinal, and the subscription and the served set already
445/// filter by member.
446pub trait Wakeable {
447 /// Wakes `waker` when the thing `what` names may have changed, under the
448 /// contract above.
449 fn wake_on(&self, what: Interest, waker: &Waker);
450}
451
452/// What a task waits for, as [`Wakeable::wake_on`] takes it.
453///
454/// Exhaustive: a runtime handles every key, because an unknown key has no
455/// safe default. Ignoring it leaves the waiter waiting, and waking it at once
456/// makes a busy loop. A new key is a 0.x minor (ADR-0021 decision 13).
457#[derive(Clone, Copy, Debug, PartialEq, Eq)]
458pub enum Interest {
459 /// The outcome of one call is known.
460 Outcome(Correlation),
461 /// A slot for a new call is free.
462 Slot,
463 /// An occurrence of one of the interface's events is waiting.
464 Event(InterfaceNo),
465 /// A claim on one of the interface's members is waiting.
466 Claim(InterfaceNo),
467}
468
469/// A read that failed.
470///
471/// One enum serves every read on every port, so a variant can be unreachable
472/// for the method that returns it: [`TooFewSamples`](ReadError::TooFewSamples)
473/// belongs to [`CoherentSignals::read_coherent`] alone, and
474/// [`Caller::reply`] never returns [`Contract`](ReadError::Contract). Each
475/// method documents what it can return.
476#[non_exhaustive]
477#[derive(Clone, Copy, Debug, PartialEq, Eq)]
478pub enum ReadError {
479 /// The output buffer is too short. Nothing was consumed.
480 Short {
481 /// The bytes the read needs.
482 needed: usize,
483 },
484 /// The output buffer is too short for the next claim's arguments
485 /// ([`Handler::next_claim`] alone). Nothing was consumed: the claim stays
486 /// the next one, and a later `next_claim` with a buffer of at least
487 /// `needed` bytes presents it under the same `claim`. The id is reported
488 /// so that a provider can settle the claim without reading its
489 /// arguments; the generated `serve` settles it
490 /// `CallError::Transport(Transport::Corrupt)`, because an argument that
491 /// does not fit the serving interface's `MAX_BUFFER_SIZE` — its largest
492 /// argument or reply payload, larger than any valid encoding of its
493 /// members — is not a well-formed encoding of one; a claim naming another
494 /// interface may be validly larger, and is settled the same, because the
495 /// serving step cannot read it (ADR-0021 decision 5, amended
496 /// 2026-09-28).
497 ShortClaim {
498 /// The claim whose arguments did not fit.
499 claim: ClaimId,
500 /// The bytes the read needs.
501 needed: usize,
502 },
503 /// `samples` has fewer entries than `ords`. Nothing was consumed.
504 TooFewSamples {
505 /// The entries `samples` needs.
506 needed: usize,
507 },
508 /// A contract error, such as an unknown interaction.
509 Contract(Contract),
510 /// The runtime behind the port is gone.
511 Detached,
512}
513
514/// A [`SignalWriter::set`], [`SignalWriter::invalidate`] or
515/// [`SignalWriter::touch`] that failed.
516#[non_exhaustive]
517#[derive(Clone, Copy, Debug, PartialEq, Eq)]
518pub enum WriteError {
519 /// The value is larger than the signal's capacity.
520 TooLarge {
521 /// The capacity in bytes.
522 cap: usize,
523 },
524 /// This provider does not own the signal.
525 NotOwner,
526 /// A contract error, such as an unknown interaction.
527 Contract(Contract),
528 /// The runtime behind the port is gone.
529 Detached,
530}
531
532/// An [`EventSink::raise`] that failed.
533#[non_exhaustive]
534#[derive(Clone, Copy, Debug, PartialEq, Eq)]
535pub enum RaiseError {
536 /// The runtime cannot accept an occurrence now. Retryable.
537 Busy,
538 /// The occurrence is larger than the event's capacity.
539 TooLarge {
540 /// The capacity in bytes.
541 cap: usize,
542 },
543 /// This provider does not own the event.
544 NotOwner,
545 /// A contract error, such as an unknown interaction.
546 Contract(Contract),
547 /// The runtime behind the port is gone.
548 Detached,
549}
550
551/// A [`Caller::command`] or [`Caller::query`] that failed before sending.
552#[non_exhaustive]
553#[derive(Clone, Copy, Debug, PartialEq, Eq)]
554pub enum SendError {
555 /// The runtime cannot accept a call now. Retryable.
556 Busy,
557 /// The arguments are larger than the call's capacity.
558 TooLarge {
559 /// The capacity in bytes.
560 cap: usize,
561 },
562 /// A contract error, such as an unknown interaction.
563 Contract(Contract),
564 /// The runtime behind the port is gone.
565 Detached,
566}
567
568/// An [`EventSource::subscribe`] that failed.
569#[non_exhaustive]
570#[derive(Clone, Copy, Debug, PartialEq, Eq)]
571pub enum SubscribeError {
572 /// A contract error: an unknown interaction fails when subscribing (ridl
573 /// §10.2).
574 Contract(Contract),
575 /// The runtime behind the port is gone.
576 Detached,
577}
578
579/// A [`Handler::serve`] that failed.
580#[non_exhaustive]
581#[derive(Clone, Copy, Debug, PartialEq, Eq)]
582pub enum ServeError {
583 /// A contract error, such as an unknown interaction.
584 Contract(Contract),
585 /// This provider does not own the call.
586 NotOwner,
587 /// The runtime behind the port is gone.
588 Detached,
589}
590
591/// A [`Handler::settle`] that failed.
592#[non_exhaustive]
593#[derive(Clone, Copy, Debug, PartialEq, Eq)]
594pub enum SettleError {
595 /// The claim was already settled, or was never issued.
596 UnknownClaim,
597 /// The reply is larger than the call's capacity.
598 TooLarge {
599 /// The capacity in bytes.
600 cap: usize,
601 },
602 /// The runtime behind the port is gone.
603 Detached,
604}
605
606// Forwarding impls (ADR-0021 decision 11).
607//
608// Every port trait above is implemented for `&mut P`, and the seven whose
609// methods all take `&self` — `Attached`, `Clock`, `SignalReader`,
610// `FixedReader`, `ScannableSignals`, `CoherentSignals` and `Wakeable` — also
611// for `&P`.
612// What they buy is one thing: a value generic over a port trait, such as a
613// generated face, can be built over a reference to a port rather than over the
614// port itself. A wrapper that adds tracing and a test double are accepted by
615// such a bound with or without them, because each implements the port traits
616// itself.
617//
618// `impl<P: T + ?Sized> T for Box<P>` is deferred: it needs `alloc`, which only
619// the `std` feature brings in, and nothing needs a boxed port (ADR-0021 open
620// question 5).
621
622impl<P: Attached + ?Sized> Attached for &P {
623 fn catalog(&self) -> &CatalogRef {
624 (**self).catalog()
625 }
626}
627
628impl<P: Attached + ?Sized> Attached for &mut P {
629 fn catalog(&self) -> &CatalogRef {
630 (**self).catalog()
631 }
632}
633
634impl<P: Clock + ?Sized> Clock for &P {
635 fn now(&self) -> Timestamp {
636 (**self).now()
637 }
638}
639
640impl<P: Clock + ?Sized> Clock for &mut P {
641 fn now(&self) -> Timestamp {
642 (**self).now()
643 }
644}
645
646impl<P: SignalReader + ?Sized> SignalReader for &P {
647 fn read(
648 &self,
649 iface: InterfaceNo,
650 ord: Ordinal,
651 out: &mut [u8],
652 ) -> Result<RawSample, ReadError> {
653 (**self).read(iface, ord, out)
654 }
655}
656
657impl<P: SignalReader + ?Sized> SignalReader for &mut P {
658 fn read(
659 &self,
660 iface: InterfaceNo,
661 ord: Ordinal,
662 out: &mut [u8],
663 ) -> Result<RawSample, ReadError> {
664 (**self).read(iface, ord, out)
665 }
666}
667
668impl<P: SignalWriter + ?Sized> SignalWriter for &mut P {
669 fn set(&mut self, iface: InterfaceNo, ord: Ordinal, bytes: &[u8]) -> Result<(), WriteError> {
670 (**self).set(iface, ord, bytes)
671 }
672 fn invalidate(&mut self, iface: InterfaceNo, ord: Ordinal) -> Result<(), WriteError> {
673 (**self).invalidate(iface, ord)
674 }
675 fn touch(&mut self, iface: InterfaceNo, ord: Ordinal) -> Result<(), WriteError> {
676 (**self).touch(iface, ord)
677 }
678 fn commit(&mut self) {
679 (**self).commit();
680 }
681}
682
683impl<P: EventSource + ?Sized> EventSource for &mut P {
684 fn subscribe(&mut self, iface: InterfaceNo, ords: &[Ordinal]) -> Result<(), SubscribeError> {
685 (**self).subscribe(iface, ords)
686 }
687 fn unsubscribe(&mut self, iface: InterfaceNo, ords: &[Ordinal]) {
688 (**self).unsubscribe(iface, ords);
689 }
690 fn next(&mut self, out: &mut [u8]) -> Result<Option<RawOccurrence>, ReadError> {
691 (**self).next(out)
692 }
693}
694
695impl<P: EventSink + ?Sized> EventSink for &mut P {
696 fn raise(&mut self, iface: InterfaceNo, ord: Ordinal, bytes: &[u8]) -> Result<(), RaiseError> {
697 (**self).raise(iface, ord, bytes)
698 }
699}
700
701impl<P: Caller + ?Sized> Caller for &mut P {
702 fn command(
703 &mut self,
704 iface: InterfaceNo,
705 ord: Ordinal,
706 args: &[u8],
707 ) -> Result<Correlation, SendError> {
708 (**self).command(iface, ord, args)
709 }
710 fn query(
711 &mut self,
712 iface: InterfaceNo,
713 ord: Ordinal,
714 args: &[u8],
715 ) -> Result<Correlation, SendError> {
716 (**self).query(iface, ord, args)
717 }
718 fn ack(&mut self, c: Correlation) -> Option<Result<(), CallError>> {
719 (**self).ack(c)
720 }
721 fn reply(
722 &mut self,
723 c: Correlation,
724 out: &mut [u8],
725 ) -> Result<Option<Result<usize, CallError>>, ReadError> {
726 (**self).reply(c, out)
727 }
728 fn forget(&mut self, c: Correlation) {
729 (**self).forget(c);
730 }
731}
732
733impl<P: Handler + ?Sized> Handler for &mut P {
734 fn serve(&mut self, iface: InterfaceNo, ords: &[Ordinal]) -> Result<(), ServeError> {
735 (**self).serve(iface, ords)
736 }
737 fn next_claim(&mut self, out: &mut [u8]) -> Result<Option<Claim>, ReadError> {
738 (**self).next_claim(out)
739 }
740 fn settle(
741 &mut self,
742 claim: ClaimId,
743 outcome: Result<&[u8], CallError>,
744 ) -> Result<(), SettleError> {
745 (**self).settle(claim, outcome)
746 }
747}
748
749impl<P: FixedReader + ?Sized> FixedReader for &P {
750 fn read_fixed(
751 &self,
752 iface: InterfaceNo,
753 ord: Ordinal,
754 out: &mut [u8],
755 ) -> Result<usize, ReadError> {
756 (**self).read_fixed(iface, ord, out)
757 }
758}
759
760impl<P: FixedReader + ?Sized> FixedReader for &mut P {
761 fn read_fixed(
762 &self,
763 iface: InterfaceNo,
764 ord: Ordinal,
765 out: &mut [u8],
766 ) -> Result<usize, ReadError> {
767 (**self).read_fixed(iface, ord, out)
768 }
769}
770
771impl<P: ScannableSignals + ?Sized> ScannableSignals for &P {
772 fn generation(&self, iface: InterfaceNo) -> u64 {
773 (**self).generation(iface)
774 }
775 fn scan(&self, marks: &mut [Watermark], out: &mut [Changed]) -> usize {
776 (**self).scan(marks, out)
777 }
778}
779
780impl<P: ScannableSignals + ?Sized> ScannableSignals for &mut P {
781 fn generation(&self, iface: InterfaceNo) -> u64 {
782 (**self).generation(iface)
783 }
784 fn scan(&self, marks: &mut [Watermark], out: &mut [Changed]) -> usize {
785 (**self).scan(marks, out)
786 }
787}
788
789impl<P: CoherentSignals + ?Sized> CoherentSignals for &P {
790 fn read_coherent(
791 &self,
792 iface: InterfaceNo,
793 ords: &[Ordinal],
794 out: &mut [u8],
795 samples: &mut [RawSample],
796 ) -> Result<usize, ReadError> {
797 (**self).read_coherent(iface, ords, out, samples)
798 }
799}
800
801impl<P: CoherentSignals + ?Sized> CoherentSignals for &mut P {
802 fn read_coherent(
803 &self,
804 iface: InterfaceNo,
805 ords: &[Ordinal],
806 out: &mut [u8],
807 samples: &mut [RawSample],
808 ) -> Result<usize, ReadError> {
809 (**self).read_coherent(iface, ords, out, samples)
810 }
811}
812
813impl<P: Wakeable + ?Sized> Wakeable for &P {
814 fn wake_on(&self, what: Interest, waker: &Waker) {
815 (**self).wake_on(what, waker);
816 }
817}
818
819impl<P: Wakeable + ?Sized> Wakeable for &mut P {
820 fn wake_on(&self, what: Interest, waker: &Waker) {
821 (**self).wake_on(what, waker);
822 }
823}