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: StateSync + Sized {
26    type Ctx;
27    fn write<B: BitBufMut, T: ByteOrder>(&self, buf: &mut B, ctx: Self::Ctx) -> ParselyResult<()>;
28}
29
30macro_rules! impl_parsely_write_builtin {
31    ($type:ty) => {
32        impl ParselyWrite for $type {
33            type Ctx = ();
34
35            fn write<B: BitBufMut, T: ByteOrder>(
36                &self,
37                buf: &mut B,
38                _: Self::Ctx,
39            ) -> ParselyResult<()> {
40                ::paste::paste! {
41                    Ok(buf.[<put_ $type>](*self)?)
42                }
43            }
44        }
45    };
46}
47
48macro_rules! impl_parsely_write_builtin_bo {
49    ($type:ty) => {
50        impl ParselyWrite for $type {
51            type Ctx = ();
52            fn write<B: BitBufMut, T: ByteOrder>(
53                &self,
54                buf: &mut B,
55                _: Self::Ctx,
56            ) -> ParselyResult<()> {
57                ::paste::paste! {
58                    Ok(buf.[<put_ $type>]::<T>(*self)?)
59                }
60            }
61        }
62    };
63}
64
65/// Accepts an array of types and calls the given macro on each of them
66/// Examples:
67/// for_all!({u1, u2, u3}, @some_macro);
68macro_rules! for_all {
69    ({$type:ty}, @$macro:ident) => {
70        $macro!($type);
71    };
72    ({$type:ty, $($tail:ty),*}, @$macro:ident) => {
73        $macro!($type);
74        for_all!({$($tail),*}, @$macro);
75    };
76}
77
78macro_rules! impl_state_sync_builtin {
79    ($type:ty) => {
80        impl StateSync for $type {
81            type SyncCtx = ();
82            fn sync(&mut self, _sync_ctx: ()) -> ParselyResult<()> {
83                Ok(())
84            }
85        }
86    };
87}
88
89for_all!({bool, u1, u2, u3, u4, u5, u6, u7, u8}, @impl_parsely_write_builtin);
90for_all!({u9, u10, u11, u12, u13, u14, u15, u16}, @impl_parsely_write_builtin_bo);
91for_all!({u17, u18, u19, u20, u21, u22, u23, u24}, @impl_parsely_write_builtin_bo);
92for_all!({u25, u26, u27, u28, u29, u30, u31, u32}, @impl_parsely_write_builtin_bo);
93
94for_all!({bool, u1, u2, u3, u4, u5, u6, u7, u8}, @impl_state_sync_builtin);
95for_all!({u9, u10, u11, u12, u13, u14, u15, u16}, @impl_state_sync_builtin);
96for_all!({u17, u18, u19, u20, u21, u22, u23, u24}, @impl_state_sync_builtin);
97for_all!({u25, u26, u27, u28, u29, u30, u31, u32}, @impl_state_sync_builtin);
98for_all!({String}, @impl_state_sync_builtin);