lilliput_core/encoder/
int.rs1use num_traits::{Signed, Unsigned};
2
3use crate::{
4 binary::bits_if,
5 error::Result,
6 header::{CompactIntHeader, ExtendedIntHeader, IntHeader},
7 io::Write,
8 num::WithPackedBeBytes,
9 value::{IntValue, SignedIntValue, UnsignedIntValue},
10};
11
12use super::Encoder;
13
14impl<W> Encoder<W>
15where
16 W: Write,
17{
18 pub fn encode_i8(&mut self, value: i8) -> Result<()> {
22 self.encode_signed_int(value)
23 }
24
25 pub fn encode_i16(&mut self, value: i16) -> Result<()> {
27 self.encode_signed_int(value)
28 }
29
30 pub fn encode_i32(&mut self, value: i32) -> Result<()> {
32 self.encode_signed_int(value)
33 }
34
35 pub fn encode_i64(&mut self, value: i64) -> Result<()> {
37 self.encode_signed_int(value)
38 }
39
40 pub fn encode_u8(&mut self, value: u8) -> Result<()> {
42 self.encode_unsigned_int(value)
43 }
44
45 pub fn encode_u16(&mut self, value: u16) -> Result<()> {
47 self.encode_unsigned_int(value)
48 }
49
50 pub fn encode_u32(&mut self, value: u32) -> Result<()> {
52 self.encode_unsigned_int(value)
53 }
54
55 pub fn encode_u64(&mut self, value: u64) -> Result<()> {
57 self.encode_unsigned_int(value)
58 }
59
60 pub fn encode_signed_int_value(&mut self, value: &SignedIntValue) -> Result<()> {
62 match value {
63 SignedIntValue::I8(value) => self.encode_signed_int(*value),
64 SignedIntValue::I16(value) => self.encode_signed_int(*value),
65 SignedIntValue::I32(value) => self.encode_signed_int(*value),
66 SignedIntValue::I64(value) => self.encode_signed_int(*value),
67 }
68 }
69
70 pub fn encode_unsigned_int_value(&mut self, value: &UnsignedIntValue) -> Result<()> {
72 match value {
73 UnsignedIntValue::U8(value) => self.encode_unsigned_int(*value),
74 UnsignedIntValue::U16(value) => self.encode_unsigned_int(*value),
75 UnsignedIntValue::U32(value) => self.encode_unsigned_int(*value),
76 UnsignedIntValue::U64(value) => self.encode_unsigned_int(*value),
77 }
78 }
79
80 pub fn encode_int_value(&mut self, value: &IntValue) -> Result<()> {
82 match value {
83 IntValue::Signed(value) => self.encode_signed_int_value(value),
84 IntValue::Unsigned(value) => self.encode_unsigned_int_value(value),
85 }
86 }
87
88 pub fn encode_int_header(&mut self, header: &IntHeader) -> Result<()> {
92 let mut byte = IntHeader::TYPE_BITS;
93
94 match header {
95 IntHeader::Compact(CompactIntHeader { is_signed, bits }) => {
96 byte |= IntHeader::COMPACT_VARIANT_BIT;
97 byte |= bits_if(IntHeader::SIGNEDNESS_BIT, *is_signed);
98 byte |= bits & IntHeader::COMPACT_VALUE_BITS;
99
100 #[cfg(feature = "tracing")]
101 tracing::debug!(
102 byte = crate::binary::fmt_byte(byte),
103 is_compact = true,
104 is_signed = is_signed,
105 bits = bits
106 );
107 }
108 IntHeader::Extended(ExtendedIntHeader { is_signed, width }) => {
109 byte |= bits_if(IntHeader::SIGNEDNESS_BIT, *is_signed);
110 byte |= (width - 1) & IntHeader::EXTENDED_WIDTH_BITS;
111
112 #[cfg(feature = "tracing")]
113 tracing::debug!(
114 byte = crate::binary::fmt_byte(byte),
115 is_compact = false,
116 is_signed = is_signed,
117 width = width
118 );
119 }
120 }
121
122 self.push_byte(byte)
124 }
125
126 pub fn header_for_signed_int<T>(&self, value: T) -> IntHeader
128 where
129 T: Signed + WithPackedBeBytes,
130 {
131 IntHeader::for_signed(value, self.config.ints.packing)
132 }
133
134 pub fn header_for_unsigned_int<T>(&self, value: T) -> IntHeader
136 where
137 T: Unsigned + WithPackedBeBytes,
138 {
139 IntHeader::for_unsigned(value, self.config.ints.packing)
140 }
141
142 #[inline]
143 fn encode_signed_int<S>(&mut self, value: S) -> Result<()>
144 where
145 S: Signed + WithPackedBeBytes,
146 {
147 let packing_mode = self.config.ints.packing;
148 value.with_packed_be_bytes(packing_mode, |bytes| {
149 let header = IntHeader::for_int_be_bytes(true, bytes, packing_mode);
150
151 self.encode_int_header(&header)?;
152
153 #[cfg(feature = "tracing")]
154 tracing::debug!(bytes = bytes);
155
156 if matches!(header, IntHeader::Extended(_)) {
157 self.push_bytes(bytes)?;
158 }
159
160 Ok(())
161 })
162 }
163
164 #[inline]
165 fn encode_unsigned_int<U>(&mut self, value: U) -> Result<()>
166 where
167 U: Unsigned + WithPackedBeBytes,
168 {
169 let packing_mode = self.config.ints.packing;
170 value.with_packed_be_bytes(packing_mode, |bytes| {
171 let header = IntHeader::for_int_be_bytes(false, bytes, packing_mode);
172
173 self.encode_int_header(&header)?;
174
175 #[cfg(feature = "tracing")]
176 tracing::debug!(bytes = bytes);
177
178 if matches!(header, IntHeader::Extended(_)) {
179 self.push_bytes(bytes)?;
180 }
181
182 Ok(())
183 })
184 }
185}