Skip to main content

Ref

Struct Ref 

Source
pub struct Ref<'a, T: Payload<E>, E: Encoding> { /* private fields */ }
Expand description

A proof that some bytes passed T::verify or were written by T::encode.

The fields are private and Ref::verify and Ref::encode are the only constructors. A crate outside ridl-rt builds a Ref by checking:

use ridl_rt::encoding::ReprC;
use ridl_rt::payload::{Payload, Ref, VerifyError};

fn check<'a, T>(bytes: &'a [u8]) -> Result<Ref<'a, T, ReprC>, VerifyError>
where
    T: Payload<ReprC, View<'a> = &'a [u8]>,
{
    Ref::verify(bytes)
}

and cannot build one from its fields:

ⓘ
use core::marker::PhantomData;
use ridl_rt::encoding::ReprC;
use ridl_rt::payload::{Payload, Ref};

fn forge<'a, T>(bytes: &'a [u8]) -> Ref<'a, T, ReprC>
where
    T: Payload<ReprC, View<'a> = &'a [u8]>,
{
    Ref { bytes, view: bytes, _e: PhantomData }
}

Implementations§

Source§

impl<'a, T: Payload<E>, E: Encoding> Ref<'a, T, E>

Source

pub fn verify(buf: &'a [u8]) -> Result<Self, VerifyError>

Checks buf with T::verify and returns the proof.

Examples found in repository?
examples/read_sample.rs (line 135)
132pub fn read_speed(port: &dyn SignalReader) -> Result<Sample<Speed>, ReadError> {
133    let mut buf = [0u8; <Speed as Payload<ReprC>>::MAX_SIZE];
134    let raw = port.read(Drivetrain::NUMBER, SpeedSignal::MEMBER.ordinal, &mut buf)?;
135    let (value, provenance) = match Ref::<Speed, ReprC>::verify(&buf[..raw.len]) {
136        Ok(proof) => (proof.decode(), raw.provenance),
137        Err(VerifyError::Contract(violation)) => (
138            SpeedSignal::init(),
139            Provenance::Invalid(Cause::Detected(Detection::InvalidValue(violation))),
140        ),
141        Err(_) => (
142            SpeedSignal::init(),
143            Provenance::Invalid(Cause::Detected(Detection::Corrupt)),
144        ),
145    };
146    Ok(Sample {
147        value,
148        provenance,
149        freshness: raw.freshness,
150        envelope: raw.envelope,
151    })
152}
Source

pub fn encode(value: &T, out: &'a mut [u8]) -> Result<Self, EncodeError>

Encodes value into out with T::encode and returns the proof.

It does not check the value’s typl constraints: a value is trusted to be valid when constructed, and the receiver’s verify reports a value that is not.

Examples found in repository?
examples/read_sample.rs (line 307)
305fn publish(runtime: &mut Memory, speed: Speed) {
306    let mut buf = [0u8; <Speed as Payload<ReprC>>::MAX_SIZE];
307    let proof = Ref::<Speed, ReprC>::encode(&speed, &mut buf).expect("the buffer is MAX_SIZE");
308    runtime
309        .set(
310            Drivetrain::NUMBER,
311            SpeedSignal::MEMBER.ordinal,
312            proof.bytes(),
313        )
314        .expect("the runtime owns speed");
315    runtime.commit();
316}
317
318/// Moves `speed` through six states and returns the sample read after each:
319/// the init value; a live value; the same value once its staleness bound has
320/// passed; the invalid state the provider declares; a value the accessor's
321/// check rejects; and bytes the accessor cannot decode.
322pub fn walk() -> [Sample<Speed>; 6] {
323    let mut init = [0u8; <Speed as Payload<ReprC>>::MAX_SIZE];
324    let proof = Ref::<Speed, ReprC>::encode(&SpeedSignal::init(), &mut init)
325        .expect("the buffer is MAX_SIZE");
326    let mut runtime = Memory::new(Timestamp(1_000_000), proof.bytes());
327    let read = |runtime: &Memory| read_speed(runtime).expect("speed is in the catalog");
328
329    let at_init = read(&runtime);
330
331    runtime.advance(Duration(10_000));
332    publish(&mut runtime, Speed(88));
333    let live = read(&runtime);
334
335    runtime.advance(Duration(600_000));
336    let stale = read(&runtime);
337
338    runtime
339        .invalidate(Drivetrain::NUMBER, SpeedSignal::MEMBER.ordinal)
340        .expect("the runtime owns speed");
341    runtime.commit();
342    let declared = read(&runtime);
343
344    runtime
345        .set(
346            Drivetrain::NUMBER,
347            SpeedSignal::MEMBER.ordinal,
348            &400u16.to_le_bytes(),
349        )
350        .expect("the runtime owns speed");
351    runtime.commit();
352    let detected = read(&runtime);
353
354    // One byte where the encoding needs two.
355    runtime
356        .set(Drivetrain::NUMBER, SpeedSignal::MEMBER.ordinal, &[1])
357        .expect("the runtime owns speed");
358    runtime.commit();
359    let corrupt = read(&runtime);
360
361    [at_init, live, stale, declared, detected, corrupt]
362}
Source

pub fn bytes(&self) -> &'a [u8]

The checked or encoded bytes.

Examples found in repository?
examples/read_sample.rs (line 71)
70    fn decode(r: Ref<'_, Self, ReprC>) -> Self {
71        let b = r.bytes();
72        Speed(u16::from_le_bytes([b[0], b[1]]))
73    }
74}
75
76/// The catalog of the package `vehicle`.
77pub const VEHICLE: CatalogRef = CatalogRef {
78    name: "vehicle",
79    hash: CatalogHash([7; 32]),
80};
81
82/// `interface Drivetrain { signal speed : Speed @[20ms..500ms] }`
83pub struct Drivetrain;
84
85impl Interface for Drivetrain {
86    const CATALOG: &'static CatalogRef = &VEHICLE;
87    const NUMBER: InterfaceNo = InterfaceNo(1);
88    const PROVISIONAL: bool = false;
89    const NAME: &'static str = "Drivetrain";
90    const MEMBERS: &'static [Member] = &[Member {
91        ordinal: Ordinal(1),
92        kind: Kind::Signal,
93        name: "speed",
94        timing: Some(Timing {
95            mode: TimingMode::Range,
96            min: Some(Duration(20_000)),
97            max: Some(Duration(500_000)),
98        }),
99        // A generated descriptor fills in every encoding that can carry the
100        // payload. This program writes only the `repr(C)` codec, so it fills
101        // in only that size.
102        payloads: &[PayloadInfo {
103            type_name: "Speed",
104            max_size: EncodedSizes {
105                proto3: None,
106                flatbuffers: None,
107                repr_c: Some(2),
108            },
109        }],
110    }];
111}
112
113/// The descriptor of `Drivetrain.speed`.
114pub struct SpeedSignal;
115
116impl Interaction for SpeedSignal {
117    type Iface = Drivetrain;
118    const MEMBER: &'static Member = &Drivetrain::MEMBERS[0];
119}
120
121impl Signal for SpeedSignal {
122    type Payload = Speed;
123    fn init() -> Speed {
124        Speed(30)
125    }
126}
127
128/// The accessor a generated client writes for `speed`: read the bytes, check
129/// them, decode them. When the check fails, the accessor reports the detection
130/// as the provenance and substitutes the init value. A generated accessor
131/// would substitute its own last good value when it has one.
132pub fn read_speed(port: &dyn SignalReader) -> Result<Sample<Speed>, ReadError> {
133    let mut buf = [0u8; <Speed as Payload<ReprC>>::MAX_SIZE];
134    let raw = port.read(Drivetrain::NUMBER, SpeedSignal::MEMBER.ordinal, &mut buf)?;
135    let (value, provenance) = match Ref::<Speed, ReprC>::verify(&buf[..raw.len]) {
136        Ok(proof) => (proof.decode(), raw.provenance),
137        Err(VerifyError::Contract(violation)) => (
138            SpeedSignal::init(),
139            Provenance::Invalid(Cause::Detected(Detection::InvalidValue(violation))),
140        ),
141        Err(_) => (
142            SpeedSignal::init(),
143            Provenance::Invalid(Cause::Detected(Detection::Corrupt)),
144        ),
145    };
146    Ok(Sample {
147        value,
148        provenance,
149        freshness: raw.freshness,
150        envelope: raw.envelope,
151    })
152}
153
154// ---- What a runtime writes ----------------------------------------------------
155
156/// A runtime for one signal of at most 2 bytes: a manual clock, one slot, and
157/// one staged change.
158pub struct Memory {
159    now: Cell<i64>,
160    bytes: [u8; 2],
161    len: usize,
162    provenance: Provenance,
163    envelope: Envelope,
164    staged: Option<Staged>,
165}
166
167enum Staged {
168    Value([u8; 2], usize),
169    Invalid,
170    Touch,
171}
172
173impl Memory {
174    /// Creates the channel at `now`, holding the init value's bytes.
175    pub fn new(now: Timestamp, init: &[u8]) -> Memory {
176        let mut bytes = [0u8; 2];
177        bytes[..init.len()].copy_from_slice(init);
178        Memory {
179            now: Cell::new(now.0),
180            bytes,
181            len: init.len(),
182            provenance: Provenance::Init,
183            envelope: Envelope { stamp: now, seq: 0 },
184            staged: None,
185        }
186    }
187
188    /// Moves the clock forward.
189    pub fn advance(&self, by: Duration) {
190        self.now.set(self.now.get() + by.0);
191    }
192
193    fn member(iface: InterfaceNo, ord: Ordinal) -> Option<&'static Member> {
194        if iface != Drivetrain::NUMBER {
195            return None;
196        }
197        Drivetrain::MEMBERS
198            .iter()
199            .find(|m| m.ordinal == ord && m.kind == Kind::Signal)
200    }
201}
202
203impl Attached for Memory {
204    fn catalog(&self) -> &CatalogRef {
205        Drivetrain::CATALOG
206    }
207}
208
209impl Clock for Memory {
210    fn now(&self) -> Timestamp {
211        Timestamp(self.now.get())
212    }
213}
214
215impl SignalReader for Memory {
216    fn read(
217        &self,
218        iface: InterfaceNo,
219        ord: Ordinal,
220        out: &mut [u8],
221    ) -> Result<RawSample, ReadError> {
222        let member =
223            Memory::member(iface, ord).ok_or(ReadError::Contract(Contract::UnknownInteraction))?;
224        let Some(front) = out.get_mut(..self.len) else {
225            return Err(ReadError::Short { needed: self.len });
226        };
227        front.copy_from_slice(&self.bytes[..self.len]);
228        let freshness = match member.timing.and_then(|t| t.max) {
229            None => Freshness::Unbounded,
230            Some(max) => {
231                let age = self.now().0 - self.envelope.stamp.0;
232                if age > max.0 {
233                    Freshness::Stale {
234                        by: Duration(age - max.0),
235                    }
236                } else {
237                    Freshness::Fresh
238                }
239            }
240        };
241        Ok(RawSample {
242            provenance: self.provenance,
243            freshness,
244            envelope: self.envelope,
245            len: self.len,
246        })
247    }
248}
249
250impl SignalWriter for Memory {
251    fn set(&mut self, iface: InterfaceNo, ord: Ordinal, bytes: &[u8]) -> Result<(), WriteError> {
252        if Memory::member(iface, ord).is_none() {
253            return Err(WriteError::Contract(Contract::UnknownInteraction));
254        }
255        let mut value = [0u8; 2];
256        let Some(front) = value.get_mut(..bytes.len()) else {
257            return Err(WriteError::TooLarge { cap: 2 });
258        };
259        front.copy_from_slice(bytes);
260        self.staged = Some(Staged::Value(value, bytes.len()));
261        Ok(())
262    }
263
264    fn invalidate(&mut self, iface: InterfaceNo, ord: Ordinal) -> Result<(), WriteError> {
265        if Memory::member(iface, ord).is_none() {
266            return Err(WriteError::Contract(Contract::UnknownInteraction));
267        }
268        self.staged = Some(Staged::Invalid);
269        Ok(())
270    }
271
272    fn touch(&mut self, iface: InterfaceNo, ord: Ordinal) -> Result<(), WriteError> {
273        if Memory::member(iface, ord).is_none() {
274            return Err(WriteError::Contract(Contract::UnknownInteraction));
275        }
276        if self.staged.is_none() {
277            self.staged = Some(Staged::Touch);
278        }
279        Ok(())
280    }
281
282    fn commit(&mut self) {
283        let Some(staged) = self.staged.take() else {
284            return;
285        };
286        match staged {
287            Staged::Value(bytes, len) => {
288                self.bytes = bytes;
289                self.len = len;
290                self.provenance = Provenance::Live;
291            }
292            Staged::Invalid => self.provenance = Provenance::Invalid(Cause::Declared),
293            Staged::Touch => {}
294        }
295        self.envelope = Envelope {
296            stamp: self.now(),
297            seq: self.envelope.seq + 1,
298        };
299    }
300}
301
302// ---- The program --------------------------------------------------------------
303
304/// Publishes `speed` the way a generated publisher does: encode, stage, commit.
305fn publish(runtime: &mut Memory, speed: Speed) {
306    let mut buf = [0u8; <Speed as Payload<ReprC>>::MAX_SIZE];
307    let proof = Ref::<Speed, ReprC>::encode(&speed, &mut buf).expect("the buffer is MAX_SIZE");
308    runtime
309        .set(
310            Drivetrain::NUMBER,
311            SpeedSignal::MEMBER.ordinal,
312            proof.bytes(),
313        )
314        .expect("the runtime owns speed");
315    runtime.commit();
316}
317
318/// Moves `speed` through six states and returns the sample read after each:
319/// the init value; a live value; the same value once its staleness bound has
320/// passed; the invalid state the provider declares; a value the accessor's
321/// check rejects; and bytes the accessor cannot decode.
322pub fn walk() -> [Sample<Speed>; 6] {
323    let mut init = [0u8; <Speed as Payload<ReprC>>::MAX_SIZE];
324    let proof = Ref::<Speed, ReprC>::encode(&SpeedSignal::init(), &mut init)
325        .expect("the buffer is MAX_SIZE");
326    let mut runtime = Memory::new(Timestamp(1_000_000), proof.bytes());
327    let read = |runtime: &Memory| read_speed(runtime).expect("speed is in the catalog");
328
329    let at_init = read(&runtime);
330
331    runtime.advance(Duration(10_000));
332    publish(&mut runtime, Speed(88));
333    let live = read(&runtime);
334
335    runtime.advance(Duration(600_000));
336    let stale = read(&runtime);
337
338    runtime
339        .invalidate(Drivetrain::NUMBER, SpeedSignal::MEMBER.ordinal)
340        .expect("the runtime owns speed");
341    runtime.commit();
342    let declared = read(&runtime);
343
344    runtime
345        .set(
346            Drivetrain::NUMBER,
347            SpeedSignal::MEMBER.ordinal,
348            &400u16.to_le_bytes(),
349        )
350        .expect("the runtime owns speed");
351    runtime.commit();
352    let detected = read(&runtime);
353
354    // One byte where the encoding needs two.
355    runtime
356        .set(Drivetrain::NUMBER, SpeedSignal::MEMBER.ordinal, &[1])
357        .expect("the runtime owns speed");
358    runtime.commit();
359    let corrupt = read(&runtime);
360
361    [at_init, live, stale, declared, detected, corrupt]
362}
Source

pub fn view(&self) -> &T::View<'a>

Lends the view.

Source

pub fn into_view(self) -> T::View<'a>

Moves the view out.

Source

pub fn decode(self) -> T

Builds the value with T::decode.

Examples found in repository?
examples/read_sample.rs (line 136)
132pub fn read_speed(port: &dyn SignalReader) -> Result<Sample<Speed>, ReadError> {
133    let mut buf = [0u8; <Speed as Payload<ReprC>>::MAX_SIZE];
134    let raw = port.read(Drivetrain::NUMBER, SpeedSignal::MEMBER.ordinal, &mut buf)?;
135    let (value, provenance) = match Ref::<Speed, ReprC>::verify(&buf[..raw.len]) {
136        Ok(proof) => (proof.decode(), raw.provenance),
137        Err(VerifyError::Contract(violation)) => (
138            SpeedSignal::init(),
139            Provenance::Invalid(Cause::Detected(Detection::InvalidValue(violation))),
140        ),
141        Err(_) => (
142            SpeedSignal::init(),
143            Provenance::Invalid(Cause::Detected(Detection::Corrupt)),
144        ),
145    };
146    Ok(Sample {
147        value,
148        provenance,
149        freshness: raw.freshness,
150        envelope: raw.envelope,
151    })
152}

Auto Trait Implementations§

§

impl<'a, T, E> Freeze for Ref<'a, T, E>
where <T as Payload<E>>::View<'a>: Freeze, PhantomData<E>: Freeze,

§

impl<'a, T, E> RefUnwindSafe for Ref<'a, T, E>
where <T as Payload<E>>::View<'a>: RefUnwindSafe, PhantomData<E>: RefUnwindSafe,

§

impl<'a, T, E> Send for Ref<'a, T, E>
where <T as Payload<E>>::View<'a>: Send, PhantomData<E>: Send,

§

impl<'a, T, E> Sync for Ref<'a, T, E>
where <T as Payload<E>>::View<'a>: Sync, PhantomData<E>: Sync,

§

impl<'a, T, E> Unpin for Ref<'a, T, E>
where <T as Payload<E>>::View<'a>: Unpin, PhantomData<E>: Unpin,

§

impl<'a, T, E> UnsafeUnpin for Ref<'a, T, E>
where <T as Payload<E>>::View<'a>: UnsafeUnpin, PhantomData<E>: UnsafeUnpin,

§

impl<'a, T, E> UnwindSafe for Ref<'a, T, E>
where <T as Payload<E>>::View<'a>: UnwindSafe, PhantomData<E>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.