Skip to main content

ridl_rt/
encoding.rs

1//! The payload encodings (ADR-0020 decisions 1 and 5).
2//!
3//! An encoding is a marker type. A payload type implements `Payload<E>` once
4//! for each encoding its package was built with, so one type can carry several
5//! codecs. The set of encodings is closed: [`Encoding`] is sealed, so a new
6//! encoding is a decision recorded in an ADR and not an `impl` in another
7//! crate.
8//!
9//! The marker types do not depend on a cargo feature. A runtime can name every
10//! encoding without linking a codec.
11
12mod sealed {
13    pub trait Sealed {}
14}
15
16/// A payload encoding. Only the three marker types of this module implement
17/// it.
18///
19/// The trait carries the encoding's name and nothing else. A payload's size
20/// in an encoding is `Payload<E>::MAX_SIZE` on the payload type, and an
21/// interface's sizes are its table, `Sizes<E>` in `contract`.
22///
23/// A crate outside `ridl-rt` names an encoding through this trait:
24///
25/// ```
26/// fn name<E: ridl_rt::encoding::Encoding>() -> &'static str {
27///     E::NAME
28/// }
29/// assert_eq!(name::<ridl_rt::encoding::ReprC>(), "repr-c");
30/// ```
31///
32/// and cannot add an encoding:
33///
34/// ```compile_fail,E0277
35/// struct Json;
36///
37/// impl ridl_rt::encoding::Encoding for Json {
38///     const NAME: &'static str = "json";
39/// }
40/// ```
41///
42/// and cannot implement the sealing trait, because its module is private:
43///
44/// ```compile_fail,E0603
45/// struct Json;
46///
47/// impl ridl_rt::encoding::sealed::Sealed for Json {}
48/// ```
49pub trait Encoding: sealed::Sealed + 'static {
50    /// The encoding's name, spelled as its cargo feature is spelled.
51    const NAME: &'static str;
52}
53
54/// FlatBuffers.
55#[derive(Clone, Copy, Debug, PartialEq, Eq)]
56pub struct FlatBuffers;
57
58/// proto3.
59#[derive(Clone, Copy, Debug, PartialEq, Eq)]
60pub struct Proto3;
61
62/// `repr(C)`, the fixed-layout encoding of ADR-0020 decision 1.
63#[derive(Clone, Copy, Debug, PartialEq, Eq)]
64pub struct ReprC;
65
66impl sealed::Sealed for FlatBuffers {}
67impl sealed::Sealed for Proto3 {}
68impl sealed::Sealed for ReprC {}
69
70impl Encoding for FlatBuffers {
71    const NAME: &'static str = "flatbuffers";
72}
73
74impl Encoding for Proto3 {
75    const NAME: &'static str = "proto3";
76}
77
78impl Encoding for ReprC {
79    const NAME: &'static str = "repr-c";
80}
81
82#[cfg(test)]
83mod tests {
84    use super::{sealed, Encoding, FlatBuffers, Proto3, ReprC};
85
86    /// A fourth encoding, for this test only. It implements every required
87    /// item of `Encoding`, so a required item added to the trait fails to
88    /// compile this module.
89    struct Fourth;
90
91    impl sealed::Sealed for Fourth {}
92
93    impl Encoding for Fourth {
94        const NAME: &'static str = "fourth";
95    }
96
97    #[test]
98    fn name_is_the_only_required_item() {
99        assert_eq!(Fourth::NAME, "fourth");
100    }
101
102    #[test]
103    fn each_name_is_the_cargo_feature_name() {
104        assert_eq!(FlatBuffers::NAME, "flatbuffers");
105        assert_eq!(Proto3::NAME, "proto3");
106        assert_eq!(ReprC::NAME, "repr-c");
107    }
108}