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. The error codes on the `compile_fail` blocks
33/// below document the expected failure, and rustdoc does not check them:
34/// `crates/ridl-rt/tests/seal.rs` compiles each snippet and asserts its code.
35///
36/// ```compile_fail,E0277
37/// struct Json;
38///
39/// impl ridl_rt::encoding::Encoding for Json {
40///     const NAME: &'static str = "json";
41/// }
42/// ```
43///
44/// and cannot implement the sealing trait, because its module is private:
45///
46/// ```compile_fail,E0603
47/// struct Json;
48///
49/// impl ridl_rt::encoding::sealed::Sealed for Json {}
50/// ```
51pub trait Encoding: sealed::Sealed + 'static {
52    /// The encoding's name, spelled as its cargo feature is spelled.
53    const NAME: &'static str;
54}
55
56/// FlatBuffers.
57#[derive(Clone, Copy, Debug, PartialEq, Eq)]
58pub struct FlatBuffers;
59
60/// proto3.
61#[derive(Clone, Copy, Debug, PartialEq, Eq)]
62pub struct Proto3;
63
64/// `repr(C)`, the fixed-layout encoding of ADR-0020 decision 1.
65#[derive(Clone, Copy, Debug, PartialEq, Eq)]
66pub struct ReprC;
67
68impl sealed::Sealed for FlatBuffers {}
69impl sealed::Sealed for Proto3 {}
70impl sealed::Sealed for ReprC {}
71
72impl Encoding for FlatBuffers {
73    const NAME: &'static str = "flatbuffers";
74}
75
76impl Encoding for Proto3 {
77    const NAME: &'static str = "proto3";
78}
79
80impl Encoding for ReprC {
81    const NAME: &'static str = "repr-c";
82}
83
84#[cfg(test)]
85mod tests {
86    use super::{sealed, Encoding, FlatBuffers, Proto3, ReprC};
87
88    /// A fourth encoding, for this test only. It implements every required
89    /// item of `Encoding`, so a required item added to the trait fails to
90    /// compile this module.
91    struct Fourth;
92
93    impl sealed::Sealed for Fourth {}
94
95    impl Encoding for Fourth {
96        const NAME: &'static str = "fourth";
97    }
98
99    #[test]
100    fn name_is_the_only_required_item() {
101        assert_eq!(Fourth::NAME, "fourth");
102    }
103
104    #[test]
105    fn each_name_is_the_cargo_feature_name() {
106        assert_eq!(FlatBuffers::NAME, "flatbuffers");
107        assert_eq!(Proto3::NAME, "proto3");
108        assert_eq!(ReprC::NAME, "repr-c");
109    }
110}