musli/int/
encoding.rs

1use crate::int::continuation as c;
2use crate::int::zigzag as zig;
3use crate::int::{Signed, Unsigned, UnsignedOps};
4use crate::{Context, Options, Reader, Writer};
5
6/// Governs how unsigned integers are encoded into a [`Writer`].
7#[inline]
8pub(crate) fn encode_unsigned<C, W, T, const OPT: Options>(
9    cx: &C,
10    writer: W,
11    value: T,
12) -> Result<(), C::Error>
13where
14    C: ?Sized + Context,
15    W: Writer,
16    T: Unsigned + UnsignedOps,
17{
18    match crate::options::integer::<OPT>() {
19        crate::options::Integer::Variable => c::encode(cx, writer, value),
20        crate::options::Integer::Fixed => {
21            let bo = crate::options::byteorder::<OPT>();
22            value.write_bytes(cx, writer, bo)
23        }
24    }
25}
26
27/// Decode an unsigned value from the specified reader using the configuration
28/// passed in through `F`.
29#[inline]
30pub(crate) fn decode_unsigned<'de, C, R, T, const OPT: Options>(
31    cx: &C,
32    reader: R,
33) -> Result<T, C::Error>
34where
35    C: ?Sized + Context,
36    R: Reader<'de>,
37    T: UnsignedOps,
38{
39    match crate::options::integer::<OPT>() {
40        crate::options::Integer::Variable => c::decode(cx, reader),
41        _ => {
42            let bo = crate::options::byteorder::<OPT>();
43            T::read_bytes(cx, reader, bo)
44        }
45    }
46}
47
48/// Governs how signed integers are encoded into a [`Writer`].
49#[inline]
50pub(crate) fn encode_signed<C, W, T, const OPT: Options>(
51    cx: &C,
52    writer: W,
53    value: T,
54) -> Result<(), C::Error>
55where
56    C: ?Sized + Context,
57    W: Writer,
58    T: Signed,
59    T::Unsigned: UnsignedOps,
60{
61    match crate::options::integer::<OPT>() {
62        crate::options::Integer::Variable => c::encode(cx, writer, zig::encode(value)),
63        crate::options::Integer::Fixed => {
64            let bo = crate::options::byteorder::<OPT>();
65            value.unsigned().write_bytes(cx, writer, bo)
66        }
67    }
68}
69
70/// Governs how signed integers are decoded from a [`Reader`].
71#[inline]
72pub(crate) fn decode_signed<'de, C, R, T, const OPT: Options>(
73    cx: &C,
74    reader: R,
75) -> Result<T, C::Error>
76where
77    C: ?Sized + Context,
78    R: Reader<'de>,
79    T: Signed,
80    T::Unsigned: UnsignedOps,
81{
82    match crate::options::integer::<OPT>() {
83        crate::options::Integer::Variable => {
84            let value: T::Unsigned = c::decode(cx, reader)?;
85            Ok(zig::decode(value))
86        }
87        crate::options::Integer::Fixed => {
88            let bo = crate::options::byteorder::<OPT>();
89            Ok(T::Unsigned::read_bytes(cx, reader, bo)?.signed())
90        }
91    }
92}
93
94/// Governs how usize lengths are encoded into a [`Writer`].
95#[inline]
96pub(crate) fn encode_usize<C, W, const OPT: Options>(
97    cx: &C,
98    writer: W,
99    value: usize,
100) -> Result<(), C::Error>
101where
102    C: ?Sized + Context,
103    W: Writer,
104{
105    match crate::options::length::<OPT>() {
106        crate::options::Integer::Variable => c::encode(cx, writer, value),
107        _ => {
108            let bo = crate::options::byteorder::<OPT>();
109
110            macro_rules! fixed {
111                ($ty:ty) => {{
112                    let Ok(value) = <$ty>::try_from(value) else {
113                        return Err(cx.message("Size type out of bounds for value type"));
114                    };
115
116                    <$ty as UnsignedOps>::write_bytes(value, cx, writer, bo)
117                }};
118            }
119
120            crate::options::width_arm!(crate::options::length_width::<OPT>(), fixed)
121        }
122    }
123}
124
125/// Governs how usize lengths are decoded from a [`Reader`].
126#[inline]
127pub(crate) fn decode_usize<'de, C, R, const OPT: Options>(
128    cx: &C,
129    reader: R,
130) -> Result<usize, C::Error>
131where
132    C: ?Sized + Context,
133    R: Reader<'de>,
134{
135    match crate::options::length::<OPT>() {
136        crate::options::Integer::Variable => c::decode(cx, reader),
137        _ => {
138            let bo = crate::options::byteorder::<OPT>();
139
140            macro_rules! fixed {
141                ($ty:ty) => {{
142                    #[allow(irrefutable_let_patterns)]
143                    let Ok(value) =
144                        usize::try_from(<$ty as UnsignedOps>::read_bytes(cx, reader, bo)?)
145                    else {
146                        return Err(cx.message("Value type out of bounds for usize"));
147                    };
148
149                    Ok(value)
150                }};
151            }
152
153            crate::options::width_arm!(crate::options::length_width::<OPT>(), fixed)
154        }
155    }
156}