Skip to main content

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}