kacrab_protocol/
bytes_io.rs1pub mod error;
7
8use bytes::{BufMut, Bytes, BytesMut};
9
10pub use self::error::{BytesError, BytesErrorKind};
11use crate::primitives::{
12 check_remaining, read_i32, read_unsigned_varint, unsigned_varint_len, write_unsigned_varint,
13};
14
15pub type Result<T> = core::result::Result<T, BytesError>;
17
18fn i32_max_len() -> usize {
19 usize::try_from(i32::MAX).unwrap_or(usize::MAX)
20}
21
22fn compact_max_len() -> usize {
23 usize::try_from(u32::MAX)
24 .unwrap_or(usize::MAX)
25 .saturating_sub(1)
26}
27
28fn i32_len_to_usize(len: i32) -> Result<usize> {
29 usize::try_from(len).map_err(|_| {
30 BytesErrorKind::TooLong {
31 length: usize::MAX,
32 max: i32_max_len(),
33 }
34 .into()
35 })
36}
37
38fn compact_len_to_usize(raw: u32) -> Result<usize> {
39 let raw_len = raw.checked_sub(1).ok_or(BytesErrorKind::UnexpectedNull)?;
40 usize::try_from(raw_len).map_err(|_| {
41 BytesErrorKind::TooLong {
42 length: usize::MAX,
43 max: compact_max_len(),
44 }
45 .into()
46 })
47}
48
49fn read_i32_len(buf: &mut Bytes) -> Result<usize> {
50 let len = read_i32(buf)?;
51 if len < 0 {
52 return Err(BytesErrorKind::NegativeLength { length: len }.into());
53 }
54 i32_len_to_usize(len)
55}
56
57fn read_nullable_i32_len(buf: &mut Bytes) -> Result<Option<usize>> {
58 let len = read_i32(buf)?;
59 if len < 0 {
60 return Ok(None);
61 }
62 i32_len_to_usize(len).map(Some)
63}
64
65fn read_compact_len(buf: &mut Bytes) -> Result<usize> {
66 let raw = read_unsigned_varint(buf)?;
67 if raw == 0 {
68 return Err(BytesErrorKind::UnexpectedNull.into());
69 }
70 compact_len_to_usize(raw)
71}
72
73fn read_nullable_compact_len(buf: &mut Bytes) -> Result<Option<usize>> {
74 let raw = read_unsigned_varint(buf)?;
75 if raw == 0 {
76 return Ok(None);
77 }
78 compact_len_to_usize(raw).map(Some)
79}
80
81fn split_bytes(buf: &mut Bytes, len: usize) -> Result<Bytes> {
82 check_remaining(buf, len)?;
83 Ok(buf.split_to(len))
84}
85
86fn compact_len_plus_one(len: usize) -> Result<u32> {
87 len.checked_add(1)
88 .and_then(|len| u32::try_from(len).ok())
89 .ok_or_else(|| {
90 BytesError::new(BytesErrorKind::TooLong {
91 length: len,
92 max: compact_max_len(),
93 })
94 })
95}
96
97pub fn read_bytes(buf: &mut Bytes) -> Result<Bytes> {
99 let len = read_i32_len(buf)?;
100 split_bytes(buf, len)
101}
102
103pub fn write_bytes(buf: &mut BytesMut, value: &[u8]) -> Result<()> {
105 let len = i32::try_from(value.len()).map_err(|_| {
106 BytesError::new(BytesErrorKind::TooLong {
107 length: value.len(),
108 max: i32_max_len(),
109 })
110 })?;
111 buf.put_i32(len);
112 buf.extend_from_slice(value);
113 Ok(())
114}
115
116pub fn bytes_len(value: &[u8]) -> Result<usize> {
118 let _len = i32::try_from(value.len()).map_err(|_| {
119 BytesError::new(BytesErrorKind::TooLong {
120 length: value.len(),
121 max: i32_max_len(),
122 })
123 })?;
124 value.len().checked_add(4).ok_or_else(|| {
125 BytesError::new(BytesErrorKind::TooLong {
126 length: value.len(),
127 max: i32_max_len(),
128 })
129 })
130}
131
132pub fn read_compact_bytes(buf: &mut Bytes) -> Result<Bytes> {
134 let len = read_compact_len(buf)?;
135 split_bytes(buf, len)
136}
137
138pub fn write_compact_bytes(buf: &mut BytesMut, value: &[u8]) -> Result<()> {
140 let len_plus_one = compact_len_plus_one(value.len())?;
141 write_unsigned_varint(buf, len_plus_one);
142 buf.extend_from_slice(value);
143 Ok(())
144}
145
146pub fn compact_bytes_len(value: &[u8]) -> Result<usize> {
148 let len_plus_one = compact_len_plus_one(value.len())?;
149 value
150 .len()
151 .checked_add(unsigned_varint_len(len_plus_one))
152 .ok_or_else(|| {
153 BytesError::new(BytesErrorKind::TooLong {
154 length: value.len(),
155 max: compact_max_len(),
156 })
157 })
158}
159
160pub fn read_nullable_bytes(buf: &mut Bytes) -> Result<Option<Bytes>> {
162 let Some(len) = read_nullable_i32_len(buf)? else {
163 return Ok(None);
164 };
165 split_bytes(buf, len).map(Some)
166}
167
168pub fn write_nullable_bytes(buf: &mut BytesMut, value: Option<&[u8]>) -> Result<()> {
170 match value {
171 None => {
172 buf.put_i32(-1);
173 Ok(())
174 },
175 Some(bytes) => write_bytes(buf, bytes),
176 }
177}
178
179pub fn nullable_bytes_len(value: Option<&[u8]>) -> Result<usize> {
181 value.map_or(Ok(4), bytes_len)
182}
183
184pub fn read_compact_nullable_bytes(buf: &mut Bytes) -> Result<Option<Bytes>> {
186 let Some(len) = read_nullable_compact_len(buf)? else {
187 return Ok(None);
188 };
189 split_bytes(buf, len).map(Some)
190}
191
192pub fn write_compact_nullable_bytes(buf: &mut BytesMut, value: Option<&[u8]>) -> Result<()> {
194 match value {
195 None => {
196 write_unsigned_varint(buf, 0);
197 Ok(())
198 },
199 Some(bytes) => write_compact_bytes(buf, bytes),
200 }
201}
202
203pub fn compact_nullable_bytes_len(value: Option<&[u8]>) -> Result<usize> {
205 value.map_or(Ok(1), compact_bytes_len)
206}