1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! The traits a codec implements, and the two helpers that use them.
//!
//! The runtime knows nothing about how an implementation of these traits comes
//! to exist. `#[derive(Network)]` writes one, the Cyclone CLI writes one into a
//! `*.codec.rs` file, and writing one by hand is equally valid. All three are
//! the same to this module.
use crateDecodeError;
use crateReader;
use crateWriter;
/// A type that can be written as Cyclone bytes.
///
/// The implementation is the schema: it decides which fields are written, in
/// which order, and with which Cyclone type. Nothing here inspects the Rust
/// type to work that out.
///
/// ```
/// use cyclone_runtime::{Encode, Writer};
///
/// struct Item { id: u32, name: String }
///
/// impl Encode for Item {
/// fn encode(&self, writer: &mut Writer) {
/// writer.write_u32(self.id);
/// writer.write_string(&self.name);
/// }
/// }
///
/// let mut writer = Writer::new();
/// Item { id: 42, name: "Sword".to_owned() }.encode(&mut writer);
/// assert_eq!(writer.len(), 13);
/// ```
/// A type that can be read back from Cyclone bytes.
///
/// The counterpart of [`Encode`], and the two must agree field for field: the
/// byte stream carries no metadata to fall back on.
/// Encodes `value` into a fresh `Vec<u8>`.
///
/// ```
/// # use cyclone_runtime::{Encode, Writer};
/// # struct Item { id: u32 }
/// # impl Encode for Item { fn encode(&self, w: &mut Writer) { w.write_u32(self.id); } }
/// let bytes = cyclone_runtime::to_bytes(&Item { id: 42 });
/// assert_eq!(bytes, [0x2A, 0x00, 0x00, 0x00]);
/// ```
///
/// Use [`Writer`] directly when several values share one buffer, or when a
/// pre-sized buffer avoids reallocation.
/// Decodes a `T` from `bytes`.
///
/// ```
/// # use cyclone_runtime::{DecodeError, Decode, Reader};
/// # struct Item { id: u32 }
/// # impl Decode for Item {
/// # fn decode(r: &mut Reader<'_>) -> Result<Self, DecodeError> { Ok(Item { id: r.read_u32()? }) }
/// # }
/// let item = cyclone_runtime::from_bytes::<Item>(&[0x2A, 0x00, 0x00, 0x00])?;
/// assert_eq!(item.id, 42);
/// # Ok::<(), DecodeError>(())
/// ```
///
/// # Errors
///
/// Any [`DecodeError`] the decode produces.
///
/// # Trailing bytes
///
/// Bytes left over after the value are **not** an error here - this helper
/// decodes one value and returns it. A stream that should end exactly at the
/// value (RFC-0002 §9) needs the check made explicitly:
///
/// ```
/// # use cyclone_runtime::{DecodeError, Decode, Reader};
/// # struct Item { id: u32 }
/// # impl Decode for Item {
/// # fn decode(r: &mut Reader<'_>) -> Result<Self, DecodeError> { Ok(Item { id: r.read_u32()? }) }
/// # }
/// # let bytes = [0x2A, 0x00, 0x00, 0x00];
/// let mut reader = Reader::new(&bytes);
/// let item = Item::decode(&mut reader)?;
/// assert!(reader.is_empty(), "trailing bytes: the two ends disagree about the schema");
/// # Ok::<(), DecodeError>(())
/// ```
///
/// The same route applies when decoding untrusted input, which wants
/// [`Reader::with_limits`] rather than the permissive default this helper uses.