parsely_impl/
parsely_write.rs

1use bits_io::prelude::*;
2
3use crate::error::ParselyResult;
4
5/// A trait for syncing a field with any required context.  In order to prevent accidental misses
6/// of this trait, it's required for all `ParselyWrite` implementors.  When generating the
7/// `ParselyWrite` implementation, `sync` will be called on every field.
8pub trait StateSync: Sized {
9    type SyncCtx;
10
11    fn sync(&mut self, _sync_ctx: Self::SyncCtx) -> ParselyResult<()> {
12        Ok(())
13    }
14}
15
16#[macro_export]
17macro_rules! impl_stateless_sync {
18    ($ty:ty) => {
19        impl StateSync for $ty {
20            type SyncCtx = ();
21        }
22    };
23}
24
25pub trait ParselyWrite<B>: StateSync + Sized {
26    type Ctx;
27    fn write<T: ByteOrder>(&self, buf: &mut B, ctx: Self::Ctx) -> ParselyResult<()>;
28}
29
30macro_rules! impl_parsely_write_builtin {
31    ($type:ty) => {
32        impl<B: BitBufMut> ParselyWrite<B> for $type {
33            type Ctx = ();
34
35            fn write<T: ByteOrder>(&self, buf: &mut B, _: Self::Ctx) -> ParselyResult<()> {
36                ::paste::paste! {
37                    Ok(buf.[<put_ $type>](*self)?)
38                }
39            }
40        }
41    };
42}
43
44macro_rules! impl_parsely_write_builtin_bo {
45    ($type:ty) => {
46        impl<B: BitBufMut> ParselyWrite<B> for $type {
47            type Ctx = ();
48            fn write<T: ByteOrder>(&self, buf: &mut B, _: Self::Ctx) -> ParselyResult<()> {
49                ::paste::paste! {
50                    Ok(buf.[<put_ $type>]::<T>(*self)?)
51                }
52            }
53        }
54    };
55}
56
57/// Accepts an array of types and calls the given macro on each of them
58/// Examples:
59/// for_all!({u1, u2, u3}, @some_macro);
60macro_rules! for_all {
61    ({$type:ty}, @$macro:ident) => {
62        $macro!($type);
63    };
64    ({$type:ty, $($tail:ty),*}, @$macro:ident) => {
65        $macro!($type);
66        for_all!({$($tail),*}, @$macro);
67    };
68}
69
70macro_rules! impl_state_sync_builtin {
71    ($type:ty) => {
72        impl StateSync for $type {
73            type SyncCtx = ();
74            fn sync(&mut self, _sync_ctx: ()) -> ParselyResult<()> {
75                Ok(())
76            }
77        }
78    };
79}
80
81for_all!({bool, u1, u2, u3, u4, u5, u6, u7, u8}, @impl_parsely_write_builtin);
82for_all!({u9, u10, u11, u12, u13, u14, u15, u16}, @impl_parsely_write_builtin_bo);
83for_all!({u17, u18, u19, u20, u21, u22, u23, u24}, @impl_parsely_write_builtin_bo);
84for_all!({u25, u26, u27, u28, u29, u30, u31, u32}, @impl_parsely_write_builtin_bo);
85
86for_all!({bool, u1, u2, u3, u4, u5, u6, u7, u8}, @impl_state_sync_builtin);
87for_all!({u9, u10, u11, u12, u13, u14, u15, u16}, @impl_state_sync_builtin);
88for_all!({u17, u18, u19, u20, u21, u22, u23, u24}, @impl_state_sync_builtin);
89for_all!({u25, u26, u27, u28, u29, u30, u31, u32}, @impl_state_sync_builtin);
90for_all!({String}, @impl_state_sync_builtin);