Skip to main content

smol_bytes/
macros.rs

1macro_rules! method_forward {
2  ($repr:tt { $(
3    $(#[$meta:meta])*
4    fn $name:ident($( $arg:ident : $arg_ty:ty ),*) $(-> $ret:ty)?
5  );+$(;)? }) => {
6    $(
7      $(#[$meta])*
8      #[cfg_attr(not(coverage), inline(always))]
9      fn $name(&mut self, $( $arg : $arg_ty ),*) $(-> $ret)? {
10        match &mut self.$repr {
11          Repr::Inline(buffer) => buffer.$name($( $arg ),*),
12          Repr::Heap(bytes) => bytes.$name($( $arg ),*),
13        }
14      }
15    )*
16  };
17  ($(
18    $(#[$meta:meta])*
19    fn $name:ident($($arg:ident : $arg_ty:ty ),*) $(-> $ret:ty)?
20  );+$(;)?) => {
21    $(
22      $(#[$meta])*
23      #[cfg_attr(not(coverage), inline(always))]
24      fn $name(&mut self, $( $arg : $arg_ty ),*) $(-> $ret)? {
25        Self::$name(self, $( $arg ),*)
26      }
27    )*
28  };
29}
30
31macro_rules! forward_buf {
32  ($repr:tt { $($suffix:ident), +$(,)? }) => {
33    paste::paste! {
34      $(
35        $crate::macros::method_forward! { $repr {
36          fn [< get_ $suffix >]() -> $suffix;
37          fn [< get_ $suffix _le >]() -> $suffix;
38          fn [< get_ $suffix _ne >]() -> $suffix;
39          fn [< try_get_ $suffix >]() -> Result<$suffix, $crate::TryGetError>;
40          fn [< try_get_ $suffix _le >]() -> Result<$suffix, $crate::TryGetError>;
41          fn [< try_get_ $suffix _ne >]() -> Result<$suffix, $crate::TryGetError>;
42        }}
43      )*
44
45      $crate::macros::method_forward! {$repr {
46        fn get_i8() -> i8;
47        fn get_u8() -> u8;
48        fn try_get_i8() -> Result<i8, $crate::TryGetError>;
49        fn try_get_u8() -> Result<u8, $crate::TryGetError>;
50
51      }}
52
53      #[cfg_attr(not(coverage), inline(always))]
54      fn get_uint(&mut self, nbytes: usize) -> u64 {
55        $crate::buffer::assert_uint_width(nbytes);
56        match &mut self.$repr {
57          Repr::Inline(buffer) => buffer.get_uint(nbytes),
58          Repr::Heap(bytes) => bytes.get_uint(nbytes),
59        }
60      }
61
62      #[cfg_attr(not(coverage), inline(always))]
63      fn get_uint_le(&mut self, nbytes: usize) -> u64 {
64        $crate::buffer::assert_uint_width(nbytes);
65        match &mut self.$repr {
66          Repr::Inline(buffer) => buffer.get_uint_le(nbytes),
67          Repr::Heap(bytes) => bytes.get_uint_le(nbytes),
68        }
69      }
70
71      #[cfg_attr(not(coverage), inline(always))]
72      fn get_uint_ne(&mut self, nbytes: usize) -> u64 {
73        $crate::buffer::assert_uint_width(nbytes);
74        match &mut self.$repr {
75          Repr::Inline(buffer) => buffer.get_uint_ne(nbytes),
76          Repr::Heap(bytes) => bytes.get_uint_ne(nbytes),
77        }
78      }
79
80      #[cfg_attr(not(coverage), inline(always))]
81      fn try_get_uint(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
82        $crate::buffer::assert_uint_width(nbytes);
83        match &mut self.$repr {
84          Repr::Inline(buffer) => buffer.try_get_uint(nbytes),
85          Repr::Heap(bytes) => bytes.try_get_uint(nbytes),
86        }
87      }
88
89      #[cfg_attr(not(coverage), inline(always))]
90      fn try_get_uint_le(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
91        $crate::buffer::assert_uint_width(nbytes);
92        match &mut self.$repr {
93          Repr::Inline(buffer) => buffer.try_get_uint_le(nbytes),
94          Repr::Heap(bytes) => bytes.try_get_uint_le(nbytes),
95        }
96      }
97
98      #[cfg_attr(not(coverage), inline(always))]
99      fn try_get_uint_ne(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
100        $crate::buffer::assert_uint_width(nbytes);
101        match &mut self.$repr {
102          Repr::Inline(buffer) => buffer.try_get_uint_ne(nbytes),
103          Repr::Heap(bytes) => bytes.try_get_uint_ne(nbytes),
104        }
105      }
106
107      #[cfg_attr(not(coverage), inline(always))]
108      fn get_int(&mut self, nbytes: usize) -> i64 {
109        $crate::buffer::assert_uint_width(nbytes);
110        $crate::buffer::sign_extend(self.get_uint(nbytes), nbytes)
111      }
112
113      #[cfg_attr(not(coverage), inline(always))]
114      fn get_int_le(&mut self, nbytes: usize) -> i64 {
115        $crate::buffer::assert_uint_width(nbytes);
116        $crate::buffer::sign_extend(self.get_uint_le(nbytes), nbytes)
117      }
118
119      #[cfg_attr(not(coverage), inline(always))]
120      fn get_int_ne(&mut self, nbytes: usize) -> i64 {
121        $crate::buffer::assert_uint_width(nbytes);
122        if cfg!(target_endian = "big") {
123          self.get_int(nbytes)
124        } else {
125          self.get_int_le(nbytes)
126        }
127      }
128
129      #[cfg_attr(not(coverage), inline(always))]
130      fn try_get_int(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
131        $crate::buffer::assert_uint_width(nbytes);
132        self
133          .try_get_uint(nbytes)
134          .map(|value| $crate::buffer::sign_extend(value, nbytes))
135      }
136
137      #[cfg_attr(not(coverage), inline(always))]
138      fn try_get_int_le(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
139        $crate::buffer::assert_uint_width(nbytes);
140        self
141          .try_get_uint_le(nbytes)
142          .map(|value| $crate::buffer::sign_extend(value, nbytes))
143      }
144
145      #[cfg_attr(not(coverage), inline(always))]
146      fn try_get_int_ne(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
147        $crate::buffer::assert_uint_width(nbytes);
148        if cfg!(target_endian = "big") {
149          self.try_get_int(nbytes)
150        } else {
151          self.try_get_int_le(nbytes)
152        }
153      }
154    }
155  };
156  ($($suffix:ident), +$(,)?) => {
157    paste::paste! {
158      $(
159        $crate::macros::method_forward! {
160          fn [< get_ $suffix >]() -> $suffix;
161          fn [< get_ $suffix _le >]() -> $suffix;
162          fn [< get_ $suffix _ne >]() -> $suffix;
163          fn [< try_get_ $suffix >]() -> Result<$suffix, $crate::TryGetError>;
164          fn [< try_get_ $suffix _le >]() -> Result<$suffix, $crate::TryGetError>;
165          fn [< try_get_ $suffix _ne >]() -> Result<$suffix, $crate::TryGetError>;
166        }
167      )*
168
169      $crate::macros::method_forward! {
170        fn get_i8() -> i8;
171        fn get_u8() -> u8;
172        fn try_get_i8() -> Result<i8, $crate::TryGetError>;
173        fn try_get_u8() -> Result<u8, $crate::TryGetError>;
174
175      }
176
177      #[cfg_attr(not(coverage), inline(always))]
178      fn get_uint(&mut self, nbytes: usize) -> u64 {
179        $crate::buffer::assert_uint_width(nbytes);
180        Self::get_uint(self, nbytes)
181      }
182
183      #[cfg_attr(not(coverage), inline(always))]
184      fn get_uint_le(&mut self, nbytes: usize) -> u64 {
185        $crate::buffer::assert_uint_width(nbytes);
186        Self::get_uint_le(self, nbytes)
187      }
188
189      #[cfg_attr(not(coverage), inline(always))]
190      fn get_uint_ne(&mut self, nbytes: usize) -> u64 {
191        $crate::buffer::assert_uint_width(nbytes);
192        Self::get_uint_ne(self, nbytes)
193      }
194
195      #[cfg_attr(not(coverage), inline(always))]
196      fn try_get_uint(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
197        $crate::buffer::assert_uint_width(nbytes);
198        Self::try_get_uint(self, nbytes)
199      }
200
201      #[cfg_attr(not(coverage), inline(always))]
202      fn try_get_uint_le(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
203        $crate::buffer::assert_uint_width(nbytes);
204        Self::try_get_uint_le(self, nbytes)
205      }
206
207      #[cfg_attr(not(coverage), inline(always))]
208      fn try_get_uint_ne(&mut self, nbytes: usize) -> Result<u64, $crate::TryGetError> {
209        $crate::buffer::assert_uint_width(nbytes);
210        Self::try_get_uint_ne(self, nbytes)
211      }
212
213      #[cfg_attr(not(coverage), inline(always))]
214      fn get_int(&mut self, nbytes: usize) -> i64 {
215        $crate::buffer::assert_uint_width(nbytes);
216        $crate::buffer::sign_extend(self.get_uint(nbytes), nbytes)
217      }
218
219      #[cfg_attr(not(coverage), inline(always))]
220      fn get_int_le(&mut self, nbytes: usize) -> i64 {
221        $crate::buffer::assert_uint_width(nbytes);
222        $crate::buffer::sign_extend(self.get_uint_le(nbytes), nbytes)
223      }
224
225      #[cfg_attr(not(coverage), inline(always))]
226      fn get_int_ne(&mut self, nbytes: usize) -> i64 {
227        $crate::buffer::assert_uint_width(nbytes);
228        if cfg!(target_endian = "big") {
229          self.get_int(nbytes)
230        } else {
231          self.get_int_le(nbytes)
232        }
233      }
234
235      #[cfg_attr(not(coverage), inline(always))]
236      fn try_get_int(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
237        $crate::buffer::assert_uint_width(nbytes);
238        self
239          .try_get_uint(nbytes)
240          .map(|value| $crate::buffer::sign_extend(value, nbytes))
241      }
242
243      #[cfg_attr(not(coverage), inline(always))]
244      fn try_get_int_le(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
245        $crate::buffer::assert_uint_width(nbytes);
246        self
247          .try_get_uint_le(nbytes)
248          .map(|value| $crate::buffer::sign_extend(value, nbytes))
249      }
250
251      #[cfg_attr(not(coverage), inline(always))]
252      fn try_get_int_ne(&mut self, nbytes: usize) -> Result<i64, $crate::TryGetError> {
253        $crate::buffer::assert_uint_width(nbytes);
254        if cfg!(target_endian = "big") {
255          self.try_get_int(nbytes)
256        } else {
257          self.try_get_int_le(nbytes)
258        }
259      }
260    }
261  };
262}
263
264macro_rules! forward_buf_mut {
265  ($repr:tt { $($suffix:ident), +$(,)? }) => {
266    paste::paste! {
267      $(
268        $crate::macros::method_forward! { $repr {
269          fn [< put_ $suffix >](val: $suffix);
270          fn [< put_ $suffix _le >](val: $suffix);
271          fn [< put_ $suffix _ne >](val: $suffix);
272        }}
273      )*
274
275      $crate::macros::method_forward! {$repr {
276        fn put_i8(val: i8);
277        fn put_u8(val: u8);
278
279        fn put_uint(n: u64, nbytes: usize);
280        fn put_uint_le(n: u64, nbytes: usize);
281        fn put_uint_ne(n: u64, nbytes: usize);
282        fn put_int(n: i64, nbytes: usize);
283        fn put_int_le(n: i64, nbytes: usize);
284        fn put_int_ne(n: i64, nbytes: usize);
285      }}
286    }
287  };
288  ($($suffix:ident), +$(,)?) => {
289    paste::paste! {
290      $(
291        $crate::macros::method_forward! {
292          fn [< put_ $suffix >](val: $suffix);
293          fn [< put_ $suffix _le >](val: $suffix);
294          fn [< put_ $suffix _ne >](val: $suffix);
295        }
296      )*
297
298      $crate::macros::method_forward! {
299        fn put_i8(val: i8);
300        fn put_u8(val: u8);
301
302        fn put_uint(n: u64, nbytes: usize);
303        fn put_uint_le(n: u64, nbytes: usize);
304        fn put_uint_ne(n: u64, nbytes: usize);
305
306        fn put_int(n: i64, nbytes: usize);
307        fn put_int_le(n: i64, nbytes: usize);
308        fn put_int_ne(n: i64, nbytes: usize);
309      }
310    }
311  };
312}
313
314pub(super) use forward_buf;
315pub(super) use forward_buf_mut;
316pub(super) use method_forward;
317
318/// Formats arguments into the default shared [`Utf8Bytes`](crate::Utf8Bytes).
319///
320/// This is similar to `format!`, but returns a value that retains heap storage
321/// when later shortened. Use `format_compact_utf8bytes!` when short results
322/// should use inline storage.
323///
324/// # Examples
325///
326/// ```
327/// use smol_bytes::{format_utf8bytes, Utf8Bytes};
328///
329/// let name = "Ada";
330/// let greeting: Utf8Bytes = format_utf8bytes!("hello, {name}!");
331/// assert_eq!(greeting.as_str(), "hello, Ada!");
332/// ```
333#[macro_export]
334macro_rules! format_utf8bytes {
335  ($($tt:tt)*) => {{
336    let mut value = $crate::Utf8BytesMut::new();
337    ::core::fmt::Write::write_fmt(&mut value, ::core::format_args!($($tt)*))
338      .expect("a formatting trait implementation returned an error");
339    value.freeze_shared()
340  }};
341}
342
343/// Formats arguments into compact [`Utf8Bytes`](crate::compact::Utf8Bytes).
344///
345/// This is similar to `format!`, but returns a value that uses inline storage
346/// when its contents fit, including after a larger value is later shortened.
347/// Use `format_utf8bytes!` when retaining heap storage after shrinking is preferred.
348///
349/// # Examples
350///
351/// ```
352/// use smol_bytes::{compact, format_compact_utf8bytes};
353///
354/// let name = "Ada";
355/// let greeting: compact::Utf8Bytes = format_compact_utf8bytes!("hello, {name}!");
356/// assert_eq!(greeting.as_str(), "hello, Ada!");
357/// ```
358#[macro_export]
359macro_rules! format_compact_utf8bytes {
360  ($($tt:tt)*) => {{
361    let mut value = $crate::Utf8BytesMut::new();
362    ::core::fmt::Write::write_fmt(&mut value, ::core::format_args!($($tt)*))
363      .expect("a formatting trait implementation returned an error");
364    value.freeze_compact()
365  }};
366}