wire_rs/
writer.rs

1// Copyright (c) 2022 Nathaniel Bennett
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use crate::WireError;
10use core::{cmp, mem, str};
11
12#[cfg(feature = "ioslice")]
13use std::io;
14
15#[cfg(feature = "ioslice")]
16pub type VectoredBufMut<'a> = &'a mut [io::IoSliceMut<'a>];
17#[cfg(not(feature = "ioslice"))]
18pub type VectoredBufMut<'a> = &'a mut [&'a mut [u8]];
19
20/// Serialization from a data type to the wire.
21///
22/// A type that implements this trait guarantees that it can be serialized into a
23/// number of bytes that will be written to the provided [`WireCursorMut`]. If the
24/// bytes cannot be written to the wire, an error will be returned.
25pub trait WireWrite {
26    /// Serializes the data type into a number of bytes on the wire, or returns a [`WireError`] on failure.
27    ///
28    /// The generic boolean `E` designates the intended endianness of the data being written. If `E` is set to
29    /// `true`, then the data will be serialized in big endian format; if `false`, it will be serialized
30    /// in little endian.
31    ///
32    /// ## Errors
33    ///
34    /// [`WireError::InsufficientBytes`] - not enough bytes remained on the cursor to write the type to the wire.
35    ///
36    /// [`WireError::Internal`] - an internal error occurred in the `wire-rs` library
37    fn write_wire<const E: bool>(&self, curs: &mut WireCursorMut<'_>) -> Result<(), WireError>;
38}
39
40/// Serialization from a data type to a portion of the wire smaller than the full size of the data type.
41///
42/// A type that implements this trait guarantees that at least a subset of its values can be serialized
43/// into a specified number of bytes (greater than zero but less than the size of the type). The serialized
44/// bytes are written to the supplied [`WireCursorMut`]. For values that cannot be serialized into the number
45/// of bytes specified, the [`WireError::InvalidData`] error should be returned.
46///
47/// This trait is most useful for writing integer values to the wire that can be represented in fewer bytes
48/// than what the data type is capable of storing, such as writing out a `u32` to 3 bytes. The caller must ensure
49/// that the value stored in the data type can fit in the number of bytes specified for the operation to succeed.
50///
51/// Types implementing this trait should also implement [`WireWrite`] for the case where the specified number of bytes
52/// is equal to the size of the type.
53pub trait WireWritePart: Sized {
54    /// Serializes the data type into exactly `L` bytes on the wire. If the data's value exceeds the bounds of
55    /// what can be stored in `L` bytes, this function will return a [`WireError::InvalidData`] error.
56    ///
57    /// As an example, the following function would return an error because the value contained in the
58    /// `u16` can't be represented by a single byte:
59    ///
60    /// ```rust
61    /// use wire_rs::{WireError, WireWriter};
62    ///
63    /// fn decode_partial_out_of_range() -> Result<(), WireError> {
64    ///     let mut buf = [0u8; 4];
65    ///     let out_of_range = 0x0100u16;
66    ///     let mut writer: WireWriter = WireWriter::new(buf.as_mut_slice());
67    ///     writer.write_part::<u16, 1>(&out_of_range) // Returns Err(WireError::InvalidData)
68    /// }
69    /// ```
70    ///
71    /// If the `u16` were a value less than or equal to 0xFF, the above function would return an Ok() result.
72    ///
73    /// The generic boolean `E` designates the intended endianness of the data being written. If `E` is set to
74    /// `true`, then the data will be serialized in big endian format; if `false`, it will be serialized in little endian.
75    fn write_wire_part<const L: usize, const E: bool>(
76        &self,
77        curs: &mut WireCursorMut<'_>,
78    ) -> Result<(), WireError>;
79}
80
81/// Serialization from a data type to the vectored wire.
82///
83/// A type that implements this trait guarantees that it can be serialized into a
84/// number of bytes that will be written to the provided [`VectoredCursorMut`]. If the
85/// bytes cannot be written to the vectored wire, an error will be returned.
86pub trait VectoredWrite {
87    /// Serializes the data type into a number of bytes on the vectored wire, or returns a [`WireError`] on failure.
88    ///
89    /// The generic boolean `E` designates the intended endianness of the data being written. If `E` is set to
90    /// `true`, then the data will be serialized in big endian format; if `false`, it will be serialized
91    /// in little endian.
92    ///
93    /// ## Errors
94    ///
95    /// [`WireError::InsufficientBytes`] - not enough bytes remained on the cursor to write the type to the wire.
96    ///
97    /// [`WireError::Internal`] - an internal error occurred in the `wire-rs` library
98    fn write_vectored<const E: bool>(
99        &self,
100        curs: &mut VectoredCursorMut<'_>,
101    ) -> Result<(), WireError>;
102}
103
104/// Serialization from an owned data type to a portion of the vectored wire smaller than what the data type would
105/// normally produce.
106///
107/// This trait is most useful for writing integer values to the vectored wire that can be represented in fewer bytes
108/// than what the data type is capable of storing, such as writing out a `u32` to 3 bytes. The caller must ensure
109/// that the value stored in the data type can fit in the number of bytes specified.
110///
111/// A type implementing this trait must guarantee that any length `L` passed in that is greater than 0 and smaller
112/// than the size of the type can be converted into the type. Types implementing this trait should also implement
113/// [`WireWrite`] for the case where `L` is equal to the size of the type.
114pub trait VectoredWritePart: Sized {
115    /// Serializes the data type into `L` bytes on the vectored wire. If the data's value exceeds the bounds of
116    /// what can be stored in `L` bytes, this function will return a WireError::InvalidData error.
117    ///
118    /// As an example, the following function would return an error because the value contained in the
119    /// `u16` can't be represented by a single byte:
120    ///
121    /// ```rust
122    /// use wire_rs::{WireWriter, WireError};
123    ///
124    /// fn decode_partial_out_of_range() -> Result<(), WireError> {
125    ///     let mut buf = [0u8; 4];
126    ///     let out_of_range = 0x0100u16;
127    ///     let mut writer: WireWriter = WireWriter::new(buf.as_mut_slice());
128    ///     writer.write_part::<u16, 1>(&out_of_range) // Returns Err(WireError::InvalidData)
129    /// }
130    /// ```
131    ///
132    /// If the value were <= 0xFF instead, the above function would return an Ok() result.
133    ///
134    /// The generic boolean `E` designates the intended endianness of the data being written. If `E` is set to
135    /// `true`, then the data will be serialized in big endian format; if `false`, it will be serialized in little endian.
136    fn write_vectored_part<const L: usize, const E: bool>(
137        &self,
138        curs: &mut VectoredCursorMut<'_>,
139    ) -> Result<(), WireError>;
140}
141
142/// A cursor that acts as an index over a mutable slice and provides operations to sequentially
143/// write data to it.
144///
145/// When implementing the [`WireWrite`] trait or one of its variants, this cursor provides an
146/// interface for writing data to the wire. When an error is returned by the cursor, it
147/// should be returned by the trait method being implemented. This can be easily accomplished
148/// using the `?` operator.
149///
150/// NOTE: this is an internal structure, and is NOT meant to be used to write data from a wire
151/// in the same manner as a [`WireWriter`]. A `WireWriter` is guaranteed to maintain the index
152/// of its last succesful write if any of its methods return an error, while this cursor may move its
153/// internal index forward by some unspecified amount when an error is encountered.
154pub struct WireCursorMut<'a> {
155    wire: &'a mut [u8],
156    idx: usize,
157}
158
159impl<'a> WireCursorMut<'a> {
160    /// Create a `WireCursorMut` that writes to the given slice `wire`.
161    fn new(wire: &'a mut [u8]) -> Self {
162        WireCursorMut { wire, idx: 0 }
163    }
164
165    /// Advance the cursor's index by the given amount, returning an error if
166    /// there are insufficient bytes on the wire.
167    pub fn advance(&mut self, amount: usize) -> Result<(), WireError> {
168        self.idx = match self.idx.checked_add(amount) {
169            Some(new_idx) if new_idx > self.wire.len() => return Err(WireError::InsufficientBytes),
170            Some(new_idx) => new_idx,
171            None => return Err(WireError::InsufficientBytes),
172        };
173
174        Ok(())
175    }
176
177    /// Advance the cursor's index by the given amount, or to the end of the wire if
178    /// the amount exceeds the number of remaining bytes.
179    pub fn advance_up_to(&mut self, amount: usize) {
180        self.idx = match self.idx.checked_add(amount) {
181            Some(new_idx) => cmp::min(new_idx, self.wire.len()),
182            None => self.wire.len(),
183        };
184    }
185
186    /// Check whether the vectored wire has any remaining bytes that can be written
187    /// to by the cursor.
188    pub fn is_empty(&self) -> bool {
189        self.wire.is_empty()
190    }
191
192    /// Write a slice of bytes to the wire.
193    pub fn put_slice(&mut self, slice: &[u8]) -> Result<(), WireError> {
194        let tmp_slice = match self.wire.get_mut(self.idx..) {
195            Some(s) => s,
196            None => return Err(WireError::Internal), // Invariant: the index should never exceed the bound of the slice
197        };
198
199        if tmp_slice.len() < slice.len() {
200            return Err(WireError::InsufficientBytes);
201        }
202
203        for (a, b) in tmp_slice.iter_mut().zip(slice.iter()) {
204            *a = *b;
205        }
206
207        self.idx += slice.len(); // tmp_slice.len() >= slice.len, so self.idx + slice.len() <= self.wire.len()
208        Ok(())
209    }
210
211    /// Serialize a given type `T` that implements the [`WireWrite`] trait to the wire.
212    ///
213    /// The generic boolean `E` designates the intended endianness of the data being written. If `E` is set to
214    /// `true`, then the data will be serialized in big endian format; if `false`, it will be serialized
215    /// in little endian.
216    pub fn put_writable<T, const E: bool>(&mut self, writable: &T) -> Result<(), WireError>
217    where
218        T: WireWrite + ?Sized,
219    {
220        writable.write_wire::<E>(self)
221    }
222
223    /// Serialize `L` bytes to the wire from a given type `T` that implements the
224    /// [`WireWritePart`] trait.
225    ///
226    /// The generic boolean `E` designates the intended endianness of the data being written. If `E` is set to
227    /// `true`, then the data will be serialized in big endian format; if `false`, it will be serialized
228    /// in little endian.
229    pub fn put_writable_part<T, const L: usize, const E: bool>(
230        &mut self,
231        writable: &T,
232    ) -> Result<(), WireError>
233    where
234        T: WireWritePart,
235    {
236        writable.write_wire_part::<L, E>(self)
237    }
238
239    /// Get the number of bytes remaining on the wire for the given cursor.
240    pub fn remaining(&self) -> usize {
241        self.wire.len().saturating_sub(self.idx)
242    }
243}
244
245/// A cursor that acts as an index over a set of vectored mutable slices and provides
246/// operations to sequentially write data to the slices.
247///
248/// When implementing the [`VectoredWrite`] trait or one of its variants, this cursor provides an
249/// interface for writing data to the vectored wire. When an error is returned by the cursor, it
250/// should be returned by the trait method being implemented. This can be easily accomplished
251/// using the `?` operator.
252///
253/// NOTE: this is an internal structure, and is NOT meant to be used to write data from a wire
254/// in the same manner as a [`WireWriter`]. A `WireWriter` is guaranteed to maintain the index
255/// of its last succesful write if any of its methods return an error, while this cursor may move its
256/// internal index forward by some unspecified amount when an error is encountered.
257pub struct VectoredCursorMut<'a> {
258    wire: VectoredBufMut<'a>,
259    arr_idx: usize,
260    idx: usize,
261}
262
263impl<'a> VectoredCursorMut<'a> {
264    /// Create a `VectoredCursorMut` that writes to the given set of vectored slices `wire`.
265    fn new(wire: VectoredBufMut<'a>) -> Self {
266        VectoredCursorMut {
267            wire,
268            arr_idx: 0,
269            idx: 0,
270        }
271    }
272
273    /// Advance the cursor's index by the given amount, returning an error if there are insufficient bytes
274    /// on the vectored wire.
275    pub fn advance(&mut self, mut amount: usize) -> Result<(), WireError> {
276        while let Some(curr_slice) = self.wire.get(self.arr_idx) {
277            let remaining_slice_len = match curr_slice.len().checked_sub(self.idx) {
278                None => return Err(WireError::Internal), // Invariant: the index should never exceed the bound of the slice
279                Some(0) => {
280                    if self.wire.get(self.arr_idx + 1).is_none() {
281                        return Err(WireError::InsufficientBytes);
282                    }
283
284                    self.arr_idx += 1; // Checked above to ensure that self.wire[self.arr_idx + 1] exists
285                    self.idx = 0;
286                    continue;
287                }
288                Some(l) => l,
289            };
290
291            match amount.checked_sub(remaining_slice_len) {
292                None | Some(0) => {
293                    // Invariant: cannot overflow (as you cannot have a slice greater than `usize::MAX`)
294                    self.idx += amount; // amount <= curr_slice.len() - self.idx -> self.idx + amount <= curr_slice.len()
295                    return Ok(());
296                }
297                Some(new_amount) => {
298                    self.arr_idx += 1;
299                    self.idx = 0;
300                    amount = new_amount;
301                }
302            }
303        }
304
305        Err(WireError::InsufficientBytes)
306    }
307
308    /// Advance the cursor's index by the given amount, or to the end of the vectored wire if the amount
309    /// exceeds the number of remaining bytes.
310    pub fn advance_up_to(&mut self, mut amount: usize) {
311        while let Some(curr_slice) = self.wire.get(self.arr_idx) {
312            let remaining_slice_len = match curr_slice.len().checked_sub(self.idx) {
313                None | Some(0) => {
314                    // Invariant: None should never occur, as the index should never exceed the bound of the first slice
315                    if self.wire.get(self.arr_idx + 1).is_none() {
316                        return;
317                    }
318                    self.arr_idx += 1; // Checked above to ensure that self.wire[self.arr_idx + 1] exists
319                    self.idx = 0;
320                    continue;
321                }
322                Some(l) => l,
323            };
324
325            match amount.checked_sub(remaining_slice_len) {
326                Some(0) | None => {
327                    // Invariant: cannot overflow (as you cannot have a slice greater than `usize::MAX`)
328                    self.idx += amount; // amount < curr_slice.len() - self.idx -> self.idx + amount <= curr_slice.len()
329                    return;
330                }
331                Some(new_amount) => {
332                    if self.wire.get(self.arr_idx + 1).is_none() {
333                        self.idx = curr_slice.len();
334                        return;
335                    }
336                    self.arr_idx += 1; // Checked above to ensure that self.wire[self.arr_idx + 1] exists
337                    self.idx = 0;
338                    amount = new_amount;
339                }
340            }
341        }
342    }
343
344    /// Check whether the vectored wire has any remaining bytes that can be written to by the cursor.
345    pub fn is_empty(&self) -> bool {
346        let mut tmp_arr_idx = self.arr_idx;
347        let mut tmp_idx = self.idx;
348        while let Some(tmp_slice) = self.wire.get(tmp_arr_idx) {
349            if tmp_idx < tmp_slice.len() {
350                return false;
351            } else if self.wire.get(tmp_arr_idx).is_none() {
352                // tmp_idx == first.len() and we're at the last slice
353                return true;
354            } else {
355                tmp_idx = 0;
356                tmp_arr_idx += 1;
357            }
358        }
359
360        true
361    }
362
363    /// Write a slice of bytes to the wire.
364    pub fn put_slice(&mut self, mut slice: &[u8]) -> Result<(), WireError> {
365        while let Some(curr_slice) = self.wire.get_mut(self.arr_idx) {
366            let wire_remaining = match curr_slice.get_mut(self.idx..) {
367                Some(s) => s,
368                None => return Err(WireError::Internal), // Invariant: the index can never exceed the bound of the slice
369            };
370
371            for (a, b) in wire_remaining.iter_mut().zip(slice.iter()) {
372                *a = *b;
373            }
374
375            let num_read = cmp::min(wire_remaining.len(), slice.len());
376            match slice.get(num_read..) {
377                Some(&[]) => {
378                    self.idx += num_read;
379                    return Ok(());
380                }
381                Some(s) => {
382                    if self.wire.get(self.arr_idx + 1).is_none() {
383                        return Err(WireError::InsufficientBytes);
384                    }
385                    slice = s;
386                    self.arr_idx += 1; // Checked above to ensure that self.wire[self.arr_idx + 1] exists
387                    self.idx = 0;
388                }
389                None => return Err(WireError::Internal), // Invariant: num_read cannot exceed slice.len()
390            }
391        }
392
393        Err(WireError::InsufficientBytes)
394    }
395
396    /// Serialize a given type `T` that implements the [`WireWrite`] trait to the wire.
397    ///
398    /// The generic boolean `E` designates the intended endianness of the data being written. If `E` is set to
399    /// `true`, then the data will be serialized in big endian format; if `false`, it will be serialized
400    /// in little endian.
401    pub fn put_writable<T, const E: bool>(&mut self, writable: &T) -> Result<(), WireError>
402    where
403        T: VectoredWrite + ?Sized,
404    {
405        writable.write_vectored::<E>(self)
406    }
407
408    /// Serialize `L` bytes to the wire from a given type `T` that implements the [`WireWritePart`]
409    /// trait.
410    ///
411    /// The generic boolean `E` designates the intended endianness of the data being written. If `E` is set to
412    /// `true`, then the data will be serialized in big endian format; if `false`, it will be serialized
413    /// in little endian.
414    pub fn put_writable_part<T, const L: usize, const E: bool>(
415        &mut self,
416        writable: &T,
417    ) -> Result<(), WireError>
418    where
419        T: VectoredWritePart,
420    {
421        writable.write_vectored_part::<L, E>(self)
422    }
423
424    /// Get the number of bytes remaining on the wire for the given cursor.
425    pub fn remaining(&self) -> usize {
426        self.wire
427            .iter()
428            .map(|s| s.len())
429            .sum::<usize>()
430            .saturating_sub(self.idx)
431    }
432}
433
434pub struct WireWriter<'a, const E: bool = true> {
435    curs: WireCursorMut<'a>,
436    initial_len: usize,
437}
438
439impl<'a, const E: bool> WireWriter<'a, E> {
440    /// Create a `WireWriter` that can write data types sequentially to the `bytes` slice.
441    pub fn new(bytes: &'a mut [u8]) -> Self {
442        let initial_len = bytes.len();
443        WireWriter {
444            curs: WireCursorMut::new(bytes),
445            initial_len,
446        }
447    }
448
449    /// Advance the writer's index forward by the given amount of bytes, returning an error if there are insufficient
450    /// bytes on the wire to do so.
451    pub fn advance(&mut self, amount: usize) -> Result<(), WireError> {
452        let prev_idx = self.curs.idx;
453        let res = self.curs.advance(amount);
454        if res.is_err() {
455            self.curs.idx = prev_idx;
456        }
457        res
458    }
459
460    /// Advance the writer's index forward by the given number of bytes, or to the end of the wire if the amount
461    /// exceeds the number of remaining bytes.
462    pub fn advance_up_to(&mut self, amount: usize) {
463        self.curs.advance_up_to(amount);
464    }
465
466    /// Check if the writer has no more bytes left on the wire that can be written to. If any
467    /// bytes remain, return [`WireError::ExtraBytes`]; otherwise, return Ok().
468    pub fn finalize(&self) -> Result<(), WireError> {
469        if !self.is_empty() {
470            Err(WireError::ExtraBytes)
471        } else {
472            Ok(())
473        }
474    }
475
476    /// Check if the writer has no more bytes left on the wire that can be written to after
477    /// the given action. If any bytes remain, return [`WireError::ExtraBytes`]; otherwise,
478    /// return Ok().
479    pub fn finalize_after<T>(
480        action: Result<(), WireError>,
481        reader: &Self,
482    ) -> Result<(), WireError> {
483        if action.is_ok() {
484            reader.finalize()?;
485        }
486        action
487    }
488
489    /// Check whether the writer has any remaining bytes that can be written to.
490    pub fn is_empty(&self) -> bool {
491        self.curs.is_empty()
492    }
493
494    /// Write the given data type `writable` to the wire.
495    pub fn write<T>(&mut self, writable: &T) -> Result<(), WireError>
496    where
497        T: WireWrite + ?Sized,
498    {
499        let temp_idx = self.curs.idx;
500        let res = writable.write_wire::<E>(&mut self.curs);
501        if res.is_err() {
502            self.curs.idx = temp_idx;
503        }
504        res
505    }
506
507    /// Write the given data type `writable` to `L` bytes on the wire.
508    pub fn write_part<T, const L: usize>(&mut self, writable: &T) -> Result<(), WireError>
509    where
510        T: WireWritePart,
511    {
512        let temp_idx = self.curs.idx;
513        let res = writable.write_wire_part::<L, E>(&mut self.curs);
514        if res.is_err() {
515            self.curs.idx = temp_idx;
516        }
517        res
518    }
519}
520
521pub fn _internal_wirewriter_consumed(writer: &WireWriter<'_>) -> usize {
522    writer.initial_len - writer.curs.remaining()
523}
524
525pub struct VectoredWriter<'a, const E: bool = true> {
526    curs: VectoredCursorMut<'a>,
527}
528
529impl<'a, const E: bool> VectoredWriter<'a, E> {
530    /// Create a `VectoredWriter` that can write data types sequentially to the vectored `bytes` slice.
531    pub fn new(bytes: VectoredBufMut<'a>) -> Self {
532        VectoredWriter {
533            curs: VectoredCursorMut::new(bytes),
534        }
535    }
536
537    /// Advance the writer's index forward by the given amount of bytes, returning an error if there are insufficient
538    /// bytes on the wire to do so.
539    pub fn advance(&mut self, amount: usize) -> Result<(), WireError> {
540        let temp_arr_idx = self.curs.arr_idx;
541        let temp_idx = self.curs.idx;
542        let res = self.curs.advance(amount);
543        if res.is_err() {
544            self.curs.arr_idx = temp_arr_idx;
545            self.curs.idx = temp_idx;
546        }
547        res
548    }
549
550    /// Advance the writer's index forward by the given number of bytes, or to the end of the vectored
551    /// wire if the amount exceeds the number of remaining bytes.
552    pub fn advance_up_to(&mut self, index: usize) {
553        self.curs.advance_up_to(index);
554    }
555
556    /// Check if the writer has no more bytes left on the vectored wire that can be written
557    /// to. If any bytes remain, return [`WireError::ExtraBytes`]; otherwise, return Ok().
558    pub fn finalize(&self) -> Result<(), WireError> {
559        if self.is_empty() {
560            Ok(())
561        } else {
562            Err(WireError::ExtraBytes)
563        }
564    }
565
566    /// Check if the writer has no more bytes left on the vectored wire that can be written
567    /// to after the given action. If any bytes remain, return [`WireError::ExtraBytes`];
568    /// otherwise, return Ok().
569    pub fn finalize_after<T>(
570        action: Result<(), WireError>,
571        reader: &Self,
572    ) -> Result<(), WireError> {
573        if action.is_ok() {
574            reader.finalize()?;
575        }
576        action
577    }
578
579    /// Check whether the writer has any remaining bytes that can be written to.
580    pub fn is_empty(&self) -> bool {
581        self.curs.is_empty()
582    }
583
584    /// Write the given data type `writable` to the vectored wire.
585    pub fn write<T>(&mut self, writable: &T) -> Result<(), WireError>
586    where
587        T: VectoredWrite + ?Sized,
588    {
589        let temp_arr_idx = self.curs.arr_idx;
590        let temp_idx = self.curs.idx;
591        let res = writable.write_vectored::<E>(&mut self.curs);
592        if res.is_err() {
593            self.curs.arr_idx = temp_arr_idx;
594            self.curs.idx = temp_idx;
595        }
596        res
597    }
598
599    /// Write the given data type `writable` to `L` bytes on the vectored wire.
600    pub fn write_part<T, const L: usize>(&mut self, writable: &T) -> Result<(), WireError>
601    where
602        T: VectoredWritePart,
603    {
604        let temp_arr_idx = self.curs.arr_idx;
605        let temp_idx = self.curs.idx;
606        let res = writable.write_vectored_part::<L, E>(&mut self.curs);
607        if res.is_err() {
608            self.curs.arr_idx = temp_arr_idx;
609            self.curs.idx = temp_idx;
610        }
611        res
612    }
613}
614
615pub fn _internal_vectoredwriter_vec_index(writer: &VectoredWriter) -> usize {
616    writer.curs.wire.len().saturating_sub(writer.curs.arr_idx)
617}
618
619pub fn _internal_vectoredwriter_slice_index(writer: &VectoredWriter) -> usize {
620    writer.curs.idx
621}
622
623impl WireWrite for str {
624    fn write_wire<'a, const E: bool>(&self, curs: &mut WireCursorMut<'a>) -> Result<(), WireError> {
625        curs.put_slice(self.as_bytes())
626    }
627}
628
629impl VectoredWrite for str {
630    fn write_vectored<'a, const E: bool>(
631        &self,
632        curs: &mut VectoredCursorMut<'a>,
633    ) -> Result<(), WireError> {
634        curs.put_slice(self.as_bytes())
635    }
636}
637
638impl WireWrite for [u8] {
639    fn write_wire<'a, const E: bool>(&self, curs: &mut WireCursorMut<'a>) -> Result<(), WireError> {
640        curs.put_slice(self)
641    }
642}
643
644impl VectoredWrite for [u8] {
645    fn write_vectored<'a, const E: bool>(
646        &self,
647        curs: &mut VectoredCursorMut<'a>,
648    ) -> Result<(), WireError> {
649        curs.put_slice(self)
650    }
651}
652
653macro_rules! derive_wire_writable {
654    ($int:ty)=> {
655        impl WireWrite for $int {
656            fn write_wire<const E: bool>(&self, curs: &mut WireCursorMut<'_>) -> Result<(), WireError> {
657                if E {
658                    curs.put_slice(self.to_be_bytes().as_slice())
659                } else {
660                    curs.put_slice(self.to_le_bytes().as_slice())
661                }
662            }
663        }
664    };
665
666    ($i1:ty, $($i2:ty),+) => {
667        derive_wire_writable! { $i1 }
668        derive_wire_writable! { $($i2),+ }
669    };
670}
671
672macro_rules! derive_wire_partwritable {
673    ($int:ty)=> {
674        impl WireWritePart for $int {
675            fn write_wire_part<const L: usize, const E: bool>(&self, curs: &mut WireCursorMut<'_>) -> Result<(), WireError> {
676                assert!(L < mem::size_of::<$int>()); // TODO: once more powerful const generic expressions are in rust, use them
677                if E {
678                    curs.put_slice(&self.to_be_bytes().get(..L).unwrap_or(&[])) // TODO: downcast larger array to smaller one here for safety guarantees
679                } else {
680                    curs.put_slice(&self.to_le_bytes().get(..L).unwrap_or(&[]))
681                }
682            }
683        }
684    };
685
686    ($i1:ty, $($i2:ty),+) => {
687        derive_wire_partwritable! { $i1 }
688        derive_wire_partwritable! { $($i2),+ }
689    };
690}
691
692macro_rules! derive_vectored_writable {
693    ($int:ty)=> {
694        impl VectoredWrite for $int {
695            fn write_vectored<const E: bool>(&self, curs: &mut VectoredCursorMut<'_>) -> Result<(), WireError> {
696                if E {
697                    curs.put_slice(self.to_be_bytes().as_slice())
698                } else {
699                    curs.put_slice(self.to_le_bytes().as_slice())
700                }
701            }
702        }
703    };
704
705    ($i1:ty, $($i2:ty),+) => {
706        derive_vectored_writable! { $i1 }
707        derive_vectored_writable! { $($i2),+ }
708    };
709}
710
711macro_rules! derive_vectored_partwritable {
712    ($int:ty)=> {
713        impl VectoredWritePart for $int {
714            fn write_vectored_part<const L: usize, const E: bool>(&self, curs: &mut VectoredCursorMut<'_>) -> Result<(), WireError> {
715                assert!(L < mem::size_of::<$int>()); // TODO: once more powerful const generic expressions are in rust, use them
716                if E {
717                    curs.put_slice(&self.to_be_bytes().get(..L).unwrap_or(&[])) // TODO: downcast larger array to smaller one here for safety guarantees
718                } else {
719                    curs.put_slice(&self.to_le_bytes().get(..L).unwrap_or(&[]))
720                }
721            }
722        }
723    };
724
725    ($i1:ty, $($i2:ty),+) => {
726        derive_vectored_partwritable! { $i1 }
727        derive_vectored_partwritable! { $($i2),+ }
728    };
729}
730
731derive_wire_writable!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, f32, f64, isize, usize);
732derive_vectored_writable!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, f32, f64, isize, usize);
733
734// No floats or signed integers--their implementations aren't conducive to chopping off bytes at will
735derive_wire_partwritable!(u16, u32, u64, u128, usize);
736derive_vectored_partwritable!(u16, u32, u64, u128, usize);