Skip to main content

bragi/
lib.rs

1use std::io::{Cursor, Read, Result, Seek, SeekFrom, Write};
2
3#[doc(hidden)]
4pub use array_init::array_init;
5
6#[doc(hidden)]
7pub trait Primitive: Sized {
8    fn write<W: Write>(self, writer: &mut Writer<W>) -> Result<()>;
9    fn read<R: Read + Seek>(reader: &mut Reader<R>) -> Result<Self>;
10}
11
12macro_rules! impl_primitive {
13    ($($ty:ty),*) => {
14        $(impl Primitive for $ty {
15            fn write<W: Write>(self, writer: &mut Writer<W>) -> Result<()> {
16                let bytes = self.to_le_bytes();
17                writer.write_all(&bytes)
18            }
19
20            fn read<R: Read + Seek>(reader: &mut Reader<R>) -> Result<Self> {
21                let mut bytes = [0; std::mem::size_of::<$ty>()];
22                reader.read_exact(&mut bytes)?;
23                Ok(Self::from_le_bytes(bytes))
24            }
25        })*
26    };
27}
28
29impl_primitive!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
30
31#[doc(hidden)]
32pub struct Writer<'a, W: Write> {
33    writer: &'a mut W,
34    offset: usize,
35}
36
37#[doc(hidden)]
38pub struct Reader<'a, R: Read + Seek> {
39    reader: &'a mut R,
40}
41
42impl<'a, W: Write> Writer<'a, W> {
43    pub fn new(writer: &'a mut W) -> Self {
44        Self { writer, offset: 0 }
45    }
46
47    pub fn offset(&self) -> usize {
48        self.offset
49    }
50
51    pub fn write_all(&mut self, buf: &[u8]) -> Result<()> {
52        self.writer.write_all(buf)?;
53        self.offset += buf.len();
54        Ok(())
55    }
56
57    pub fn write_integer<T: Primitive>(&mut self, value: T) -> Result<()> {
58        value.write(self)
59    }
60
61    pub fn write_string(&mut self, value: &str) -> Result<()> {
62        let bytes = value.as_bytes();
63        self.write_varint(bytes.len() as u64)?;
64        self.writer.write_all(bytes)?;
65        Ok(())
66    }
67
68    pub fn write_varint(&mut self, mut value: u64) -> Result<()> {
69        let mut buffer = [0u8; 9];
70        let mut length = 0;
71
72        let data_bits = 64 - (value | 1).leading_zeros();
73        let mut bytes = 1 + (data_bits.saturating_sub(1) / 7) as usize;
74
75        if data_bits > 56 {
76            buffer[length] = 0;
77            length += 1;
78            bytes = 8;
79        } else {
80            value = (2 * value + 1) << (bytes - 1);
81        }
82
83        for i in 0..bytes {
84            buffer[length] = ((value >> (i * 8)) & 0xFF) as u8;
85            length += 1;
86        }
87
88        self.writer.write_all(&buffer[..length])
89    }
90
91    pub fn write_struct<S: Struct>(&mut self, value: &S) -> Result<()> {
92        value.encode_body(self.writer)
93    }
94}
95
96impl<'a, R: Read + Seek> Reader<'a, R> {
97    pub fn new(reader: &'a mut R) -> Self {
98        Self { reader }
99    }
100
101    pub fn offset(&mut self) -> Result<u64> {
102        self.reader.stream_position()
103    }
104
105    pub fn seek(&mut self, offset: u64) -> Result<u64> {
106        self.reader.seek(SeekFrom::Start(offset))
107    }
108
109    pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
110        self.reader.read_exact(buf)
111    }
112
113    pub fn read_integer<T: Primitive>(&mut self) -> Result<T> {
114        T::read(self)
115    }
116
117    pub fn read_string(&mut self) -> Result<String> {
118        let length = self.read_varint()? as usize;
119        let mut buffer = vec![0u8; length];
120
121        self.reader.read_exact(&mut buffer)?;
122
123        match String::from_utf8(buffer) {
124            Ok(string) => Ok(string),
125            Err(_) => Err(std::io::Error::new(
126                std::io::ErrorKind::InvalidData,
127                "Invalid UTF-8 string",
128            )),
129        }
130    }
131
132    pub fn read_varint(&mut self) -> Result<u64> {
133        let mut bytes = [0u8; 9];
134
135        self.reader.read_exact(&mut bytes[..1])?;
136
137        let mut n_bytes = if bytes[0] != 0 {
138            bytes[0].trailing_zeros() as usize + 1
139        } else {
140            9
141        };
142
143        if n_bytes > 8 {
144            n_bytes = 9;
145        }
146
147        if n_bytes > 1 {
148            self.reader.read_exact(&mut bytes[1..n_bytes])?;
149        }
150
151        let mut value: u64 = 0;
152        let shift = if n_bytes < 9 { 8 - (n_bytes % 8) } else { 0 };
153
154        for (i, byte) in bytes.iter().enumerate().skip(1) {
155            value |= (*byte as u64) << ((i - 1) * 8);
156        }
157
158        value <<= shift;
159        value |= (bytes[0] as u64) >> n_bytes;
160
161        Ok(value)
162    }
163
164    pub fn read_struct<S: Struct>(&mut self, value: &mut S) -> Result<()> {
165        value.decode_body(self.reader)
166    }
167}
168
169#[doc(hidden)]
170pub trait Struct {
171    fn size_of_body(&self) -> usize;
172
173    fn encode_body<W: Write>(&self, writer: &mut W) -> Result<()>;
174    fn decode_body<R: Read + Seek>(&mut self, reader: &mut R) -> Result<()>;
175}
176
177#[doc(hidden)]
178pub trait Message {
179    const MESSAGE_ID: u32;
180    const HAS_TAIL: bool;
181    const HEAD_SIZE: usize;
182
183    fn size_of_head(&self) -> usize;
184    fn size_of_tail(&self) -> usize;
185
186    fn encode_head<W: Write>(&self, writer: &mut W) -> Result<()>;
187    fn encode_tail<W: Write>(&self, writer: &mut W) -> Result<()>;
188
189    fn decode_head<R: Read + Seek>(&mut self, reader: &mut R) -> Result<()>;
190    fn decode_tail<R: Read + Seek>(&mut self, reader: &mut R) -> Result<()>;
191}
192
193/// The preamble of a message. It consists of the message ID
194/// and the size of the encoded tail of the message.
195#[derive(Debug, Clone, Copy)]
196pub struct Preamble {
197    id: u32,
198    tail_size: u32,
199}
200
201impl Preamble {
202    /// Creates a new [`Preamble`] with the given message ID and tail size.
203    pub const fn new(id: u32, tail_size: u32) -> Self {
204        Self { id, tail_size }
205    }
206
207    /// Returns the message ID of the message.
208    pub const fn id(&self) -> u32 {
209        self.id
210    }
211
212    /// Returns the size of the tail of the message.
213    pub const fn tail_size(&self) -> u32 {
214        self.tail_size
215    }
216}
217
218#[doc(hidden)]
219pub fn size_of_varint(value: u64) -> usize {
220    let leading_zeroes = (value | 1).leading_zeros() as usize;
221    let data_bits = u64::BITS as usize - leading_zeroes;
222    let bytes = 1 + (data_bits - 1) / 7;
223
224    if data_bits > 56 { 9 } else { bytes }
225}
226
227/// Reads the preamble of a message from the given reader.
228pub fn read_preamble<R: Read + Seek>(reader: &mut R) -> Result<Preamble> {
229    let mut preamble = Preamble {
230        id: 0,
231        tail_size: 0,
232    };
233
234    let offset = reader.stream_position()?;
235
236    {
237        let mut reader = Reader::new(reader);
238
239        preamble.id = reader.read_integer::<u32>()?;
240        preamble.tail_size = reader.read_integer::<u32>()?;
241    }
242
243    reader.seek(SeekFrom::Start(offset))?;
244
245    Ok(preamble)
246}
247
248/// Reads only the message head from the given reader and returns the final message.
249/// The message is default initialized before decoding the head.
250pub fn read_head<M: Default + Message, H: Read + Seek>(head_reader: &mut H) -> Result<M> {
251    let mut message = M::default();
252
253    message.decode_head(head_reader)?;
254
255    Ok(message)
256}
257
258/// Reads the message head and tail from the given readers and returns the final message.
259/// The message is default initialized before decoding the head and tail.
260pub fn read_head_tail<M: Default + Message, H: Read + Seek, T: Read + Seek>(
261    head_reader: &mut H,
262    tail_reader: &mut T,
263) -> Result<M> {
264    let mut message = M::default();
265
266    message.decode_head(head_reader)?;
267    message.decode_tail(tail_reader)?;
268
269    Ok(message)
270}
271
272/// Reads the message preamble from the given buffer and returns the preamble.
273pub fn preamble_from_bytes(bytes: &[u8]) -> Result<Preamble> {
274    let mut cursor = Cursor::new(bytes);
275    read_preamble(&mut cursor)
276}
277
278/// Reads the message head from the given buffer and returns the final message.
279/// The message is default initialized before decoding the head.
280pub fn head_from_bytes<M: Default + Message>(bytes: &[u8]) -> Result<M> {
281    read_head(&mut Cursor::new(bytes))
282}
283
284/// Reads the message head and tail from the given buffers and returns the final message.
285/// The message is default initialized before decoding the head and tail.
286pub fn head_tail_from_bytes<M: Default + Message>(
287    head_bytes: &[u8],
288    tail_bytes: &[u8],
289) -> Result<M> {
290    let mut message = M::default();
291
292    message.decode_head(&mut Cursor::new(head_bytes))?;
293    message.decode_tail(&mut Cursor::new(tail_bytes))?;
294
295    Ok(message)
296}
297
298/// Writes the preamble of a message to the given writer.
299pub fn write_preamble<W: Write>(writer: &mut W, preamble: Preamble) -> Result<()> {
300    let mut writer = Writer::new(writer);
301
302    writer.write_integer(preamble.id())?;
303    writer.write_integer(preamble.tail_size())?;
304
305    Ok(())
306}
307
308/// Writes the message head to the given writer.
309pub fn write_head<M: Message, W: Write>(writer: &mut W, message: &M) -> Result<()> {
310    message.encode_head(writer)
311}
312
313/// Writes the message head and tail to the given writers.
314pub fn write_head_tail<M: Message, H: Write, T: Write>(
315    head_writer: &mut H,
316    tail_writer: &mut T,
317    message: &M,
318) -> Result<()> {
319    message.encode_head(head_writer)?;
320    message.encode_tail(tail_writer)?;
321
322    Ok(())
323}
324
325/// Write the message preamble to a temporary buffer and returns the written bytes.
326pub fn preamble_to_bytes(preamble: &Preamble) -> Result<Vec<u8>> {
327    let mut cursor = Cursor::new(Vec::with_capacity(8));
328
329    write_preamble(&mut cursor, *preamble).map(|_| cursor.into_inner())
330}
331
332/// Writes the message head to a temporary buffer and returns the written bytes.
333pub fn head_to_bytes<M: Message>(message: &M) -> Result<Vec<u8>> {
334    let mut cursor = Cursor::new(Vec::with_capacity(M::HEAD_SIZE));
335
336    write_head(&mut cursor, message).map(|_| cursor.into_inner())
337}
338
339/// Writes the message head and tail to temporary buffers and returns the written bytes
340/// as a tuple of byte vectors.
341pub fn head_tail_to_bytes<M: Message>(message: &M) -> Result<(Vec<u8>, Vec<u8>)> {
342    let mut head_cursor = Cursor::new(Vec::with_capacity(M::HEAD_SIZE));
343    let mut tail_cursor = Cursor::new(Vec::new());
344
345    write_head_tail(&mut head_cursor, &mut tail_cursor, message)
346        .map(|_| (head_cursor.into_inner(), tail_cursor.into_inner()))
347}
348
349#[macro_export]
350#[doc(hidden)]
351macro_rules! generate_enum {
352    (
353        $vis:vis enum $name:ident : $underlying:ty {
354            $(
355                $variant:ident = $value:expr
356            ),*
357            $(,)?
358        }
359    ) => {
360        #[repr($underlying)]
361        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
362        $vis enum $name {
363            $(
364                $variant = $value,
365            )*
366        }
367
368        impl ::core::convert::TryFrom<$underlying> for $name {
369            type Error = $underlying;
370
371            fn try_from(value: $underlying) -> ::core::result::Result<Self, Self::Error> {
372                match value {
373                    $(
374                        $value => Ok($name::$variant),
375                    )*
376                    _ => Err(value),
377                }
378            }
379        }
380    }
381}
382
383#[macro_export]
384#[doc(hidden)]
385macro_rules! generate_consts {
386    (
387        $vis:vis enum $name:ident : $underlying:ty {
388            $(
389                $variant:ident = $value:expr
390            ),*
391            $(,)?
392        }
393    ) => {
394        #[repr(transparent)]
395        #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
396        $vis struct $name($underlying);
397
398        impl $name {
399            $(
400                pub const $variant: Self = Self($value);
401            )*
402
403            /// Returns the underlying value of the constant.
404            pub const fn value(&self) -> $underlying {
405                self.0
406            }
407        }
408
409        impl ::core::convert::From<$underlying> for $name {
410            fn from(value: $underlying) -> Self {
411                Self(value)
412            }
413        }
414    }
415}
416
417#[macro_export]
418#[doc(hidden)]
419macro_rules! generate_bitfield_enum {
420    (
421        $vis:vis enum $name:ident : $underlying:ty {
422            $(
423                $variant:ident = $value:expr
424            ),*
425            $(,)?
426        }
427    ) => {
428        #[repr(transparent)]
429        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
430        $vis struct $name {
431            bits: $underlying,
432        }
433
434        impl $name {
435            $(
436                pub const $variant: Self = Self { bits: $value };
437            )*
438
439            #[doc = concat!("Creates a new [`", stringify!($name), "`] with no bits set.")]
440            pub const fn empty() -> Self {
441                Self { bits: 0 }
442            }
443
444            #[doc = concat!("Creates a new [`", stringify!($name), "`] with the given bits set.")]
445            #[doc = "# Safety"]
446            #[doc = "This function is unsafe because it allows creating a bitfield with arbitrary bits set."]
447            #[doc = "The caller must ensure that the bits are valid for the given bitfield."]
448            pub const unsafe fn new(bits: u32) -> Self {
449                Self { bits }
450            }
451
452            #[doc = concat!("Returns the bits of the [`", stringify!($name), "`].")]
453            pub const fn bits(&self) -> u32 {
454                self.bits
455            }
456
457            #[doc = concat!("Checks if the given bits are set in the [`", stringify!($name), "`].")]
458            pub const fn is_set(&self, other: Self) -> bool {
459                (self.bits & other.bits) == other.bits
460            }
461
462            #[doc = concat!("Returns a new [`", stringify!($name), "`] with the given bits set.")]
463            pub const fn set(&self, other: Self) -> Self {
464                Self { bits: self.bits | other.bits }
465            }
466
467            #[doc = concat!("Returns a new [`", stringify!($name), "`] with the given bits cleared.")]
468            pub const fn clear(&self, other: Self) -> Self {
469                Self { bits: self.bits & !other.bits }
470            }
471        }
472
473        impl ::core::ops::BitAnd for $name {
474            type Output = Self;
475
476            fn bitand(self, rhs: Self) -> Self::Output {
477                Self { bits: self.bits & rhs.bits }
478            }
479        }
480
481        impl ::core::ops::BitOr for $name {
482            type Output = Self;
483
484            fn bitor(self, rhs: Self) -> Self::Output {
485                Self { bits: self.bits | rhs.bits }
486            }
487        }
488
489        impl ::core::ops::BitXor for $name {
490            type Output = Self;
491
492            fn bitxor(self, rhs: Self) -> Self::Output {
493                Self { bits: self.bits ^ rhs.bits }
494            }
495        }
496
497        impl ::core::ops::Not for $name {
498            type Output = Self;
499
500            fn not(self) -> Self::Output {
501                Self { bits: !self.bits }
502            }
503        }
504
505        impl ::core::fmt::Display for $name {
506            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
507                let mut first = true;
508                for (bits, name) in [
509                    $(
510                        (Self::$variant, stringify!($variant))
511                    ),*
512                ] {
513                    if self.is_set(bits) {
514                        if !first {
515                            write!(f, " | ")?;
516                        }
517                        write!(f, "{}", name)?;
518                        first = false;
519                    }
520                }
521                if first {
522                    write!(f, "NONE")?;
523                }
524                Ok(())
525            }
526        }
527    };
528}
529
530/// A macro to include generated bindings from the `OUT_DIR`.
531///
532/// The module declared by this macro will contain the generated bindings
533/// and will be annotated with attributes to suppress warnings and lints.
534#[macro_export]
535macro_rules! include_binding {
536    ($($vis:vis mod $mod_name:ident = $name:literal),* $(,)?) => {
537        $(
538            #[allow(clippy::all)]
539            #[allow(dead_code)]
540            #[allow(unused_imports)]
541            #[allow(unused_mut)]
542            #[allow(unused_variables)]
543            $vis mod $mod_name {
544                include!(concat!(env!("OUT_DIR"), "/", $name));
545            }
546        )*
547    };
548}