musli_common/int/
encoding.rs

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