Skip to main content

tango/
buf.rs

1//! Typed buffers, octets being a `Buf<u8, 1>`, which is what a backend receives a message
2//! into.
3//!
4//! A [`Buf`] is a typed, N-dimensional array of values, whose dimensions are fixed once it
5//! is built. It has no lifetime: it holds a reference to a counted storage that every clone
6//! and every slice shares, so that the buffer a message is received into can be handed out
7//! in pieces, cast to the types of the values it holds, all the way up to the user, without
8//! copying any of it.
9//!
10//! A [`BufMut`] is a buffer that is statically the only reference to its storage, which is
11//! what allows writing to it, and growing it along one dimension, like a `Vec`, without ever
12//! checking whether its storage is shared. A [`Buf`] turns into one with copy-on-write, see
13//! [`Buf::make_mut`] and [`Buf::into_mut`], copying only its own values when its storage is
14//! shared, or without, see [`Buf::get_mut`] and [`Buf::try_into_mut`], and a [`BufMut`]
15//! turns back into a [`Buf`] to be shared, see [`BufMut::freeze`].
16//!
17//! # Alignment
18//!
19//! Storages are currently aligned on 8 octets, so that a buffer starting where its storage
20//! starts, such as one that was just allocated, is aligned for every [`PackedElement`] and
21//! casts to any of them without copying. This is an implementation detail, which is not
22//! guaranteed to stay the same across versions: what depends on the alignment of some
23//! values checks it, like [`Buf::cast`], which copies the values when they are not aligned
24//! for their new type.
25
26use std::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
27use std::mem::{self, ManuallyDrop, MaybeUninit};
28use std::fmt::{self, Debug, LowerHex, UpperHex};
29use std::ops::{Bound, Range, RangeBounds};
30use std::alloc::{self, Layout};
31use std::ptr::{self, NonNull};
32use std::marker::PhantomData;
33use std::{slice, str};
34
35use crate::error::{Error, ErrorKind};
36use crate::value::DevEnum;
37use crate::dev::DevState;
38
39
40// =========================== //
41//           Storage           //
42// =========================== //
43
44/// The header of a storage, directly followed by its data, in units of 8 octets so that
45/// the data is aligned for every [`PackedElement`].
46#[repr(C)]
47struct HeapHeader {
48    /// Number of handles on this storage, the storage being freed when it drops to zero.
49    count: AtomicUsize,
50    /// Capacity of the data, in units of 8 octets.
51    cap: usize,
52    /// The side allocations freed together with this storage, see [`SideHeader`].
53    side: AtomicPtr<SideHeader>,
54}
55
56/// The header of a side allocation, directly followed by its payload: something a [`Buf`]
57/// needs beside its values, such as the spans of its strings, which lives exactly as long
58/// as the storage it is attached to, and therefore needs no count of its own.
59#[repr(C)]
60struct SideHeader {
61    /// The next side allocation of the same storage.
62    next: *mut SideHeader,
63    /// Size of the payload, in octets.
64    size: usize,
65}
66
67/// The alignment of the data of a storage and of the payload of a side allocation, which
68/// is not part of the API, see the [module](self) documentation.
69const ALIGN: usize = 8;
70
71/// What an allocation fails with: no layout at all for a capacity that large, or the layout
72/// the allocator failed on.
73type AllocResult<T> = Result<T, Option<Layout>>;
74
75/// Unwrap an allocation the way the standard collections do: a panic when the capacity
76/// overflows, the allocation error handler when the allocator fails.
77fn infallible<T>(res: AllocResult<T>) -> T {
78    match res {
79        Ok(value) => value,
80        Err(Some(layout)) => alloc::handle_alloc_error(layout),
81        Err(None) => panic!("capacity overflow"),
82    }
83}
84
85/// A raw handle on a storage, which does not count as a reference by itself: this is what
86/// the [`HeapRef`] holding it acquires and releases.
87#[derive(Clone, Copy)]
88#[repr(transparent)]
89struct Heap(NonNull<HeapHeader>);
90
91/// A header aligned like the storages that are allocated, so that its (empty) data is too.
92#[repr(C, align(8))]
93struct EmptyHeapHeader(HeapHeader);
94
95/// The storage of whatever holds no values at all, which is never allocated nor freed: it
96/// is not counted, see [`Heap::is_immortal`], and is never written since it has no
97/// octets, and nothing is ever attached to it.
98static EMPTY_HEAP_HEADER: EmptyHeapHeader = EmptyHeapHeader(HeapHeader {
99    count: AtomicUsize::new(usize::MAX),
100    cap: 0,
101    side: AtomicPtr::new(ptr::null_mut()),
102});
103
104impl Heap {
105
106    /// A handle on the storage of whatever holds no values at all.
107    // SAFETY: A static is never null.
108    const EMPTY: Self = Self(unsafe { NonNull::new_unchecked((&raw const EMPTY_HEAP_HEADER.0).cast_mut()) });
109
110    /// Whether this is the storage of whatever holds no values at all, which is not counted.
111    #[inline]
112    fn is_immortal(self) -> bool {
113        self.0 == Self::EMPTY.0
114    }
115
116    /// The layout of a storage of that capacity, in units of 8 octets, absent if it
117    /// overflows.
118    fn layout(cap: usize) -> Option<Layout> {
119        cap.checked_mul(ALIGN)
120            .and_then(|size| size.checked_add(mem::size_of::<HeapHeader>()))
121            .and_then(|size| Layout::from_size_align(size, ALIGN).ok())
122    }
123
124    /// Allocate a storage holding at least that many octets, all zeroes, its only reference
125    /// being the returned handle. A storage is always zeroed when allocated, and so is what
126    /// it grows by, see [`Self::grow`]: its whole capacity is always initialized, and
127    /// zeroes need not be written where it was never written.
128    fn alloc(len: usize) -> AllocResult<Self> {
129        let cap = len.div_ceil(ALIGN);
130        let layout = Self::layout(cap).ok_or(None)?;
131        // SAFETY: The layout is never zero-sized, it always holds the header.
132        let ptr = unsafe { alloc::alloc_zeroed(layout) };
133        let ptr = NonNull::new(ptr.cast::<HeapHeader>()).ok_or(Some(layout))?;
134        // SAFETY: The allocation is valid for the header.
135        unsafe { ptr.write(HeapHeader { count: AtomicUsize::new(1), cap, side: AtomicPtr::new(ptr::null_mut()) }) };
136        Ok(Self(ptr))
137    }
138
139    /// The data of this storage.
140    #[inline]
141    fn data(self) -> *mut u8 {
142        // SAFETY: The data directly follows the header, in the same allocation.
143        unsafe { self.0.as_ptr().add(1).cast::<u8>() }
144    }
145
146    /// The capacity of the data of this storage, in octets.
147    #[inline]
148    fn capacity(self) -> usize {
149        // SAFETY: The handle points to a live storage.
150        unsafe { (*self.0.as_ptr()).cap * ALIGN }
151    }
152
153    #[inline]
154    fn header(&self) -> &HeapHeader {
155        // SAFETY: The handle points to a live storage.
156        unsafe { self.0.as_ref() }
157    }
158
159    /// Whether this is the only reference to the storage, which is what allows writing to
160    /// it, the acquire ordering making the writes of the released references visible.
161    #[inline]
162    fn is_unique(self) -> bool {
163        self.header().count.load(Ordering::Acquire) == 1
164    }
165
166    /// Add a reference to this storage.
167    #[inline]
168    fn acquire(self) {
169        if self.is_immortal() {
170            return;
171        }
172        let old = self.header().count.fetch_add(1, Ordering::Relaxed);
173        // Like `Arc`, never let the count overflow, which would free a live storage.
174        if old > isize::MAX as usize {
175            std::process::abort();
176        }
177    }
178
179    /// Release a reference to this storage, freeing it with its side allocations if it
180    /// was the last one.
181    ///
182    /// # Safety
183    ///
184    /// The caller has to own the reference it releases, and not use the handle anymore.
185    #[inline]
186    unsafe fn release(self) {
187        if self.is_immortal() || self.header().count.fetch_sub(1, Ordering::Release) != 1 {
188            return;
189        }
190        atomic::fence(Ordering::Acquire);
191        // SAFETY: This was the last reference, nothing else can reach the storage.
192        unsafe { self.free() }
193    }
194
195    #[cold]
196    unsafe fn free(self) {
197        let header = self.0.as_ptr();
198        // SAFETY: The storage is ours alone, allocated with that layout.
199        unsafe {
200            self.free_sides();
201            alloc::dealloc(header.cast(), Self::layout((*header).cap).unwrap_unchecked());
202        }
203    }
204
205    /// The layout of a side allocation of that payload size, absent if it overflows.
206    fn side_layout(size: usize) -> Option<Layout> {
207        size.checked_add(mem::size_of::<SideHeader>())
208            .and_then(|size| Layout::from_size_align(size, ALIGN).ok())
209    }
210
211    /// Attach that side allocation to this storage, which frees it with itself.
212    ///
213    /// The storage may already be shared, hence the lock-free push, but nothing reads the
214    /// list of side allocations before the last reference frees it.
215    fn push_side(self, side: DetachedSide) {
216        debug_assert!(!self.is_immortal(), "nothing is attached to the empty storage");
217        let side = ManuallyDrop::new(side).0;
218        let head = &self.header().side;
219        let mut next = head.load(Ordering::Relaxed);
220        loop {
221            // SAFETY: The side allocation is ours until it is pushed.
222            unsafe { (*side.as_ptr()).next = next };
223            match head.compare_exchange_weak(next, side.as_ptr(), Ordering::Release, Ordering::Relaxed) {
224                Ok(_) => break,
225                Err(current) => next = current,
226            }
227        }
228    }
229
230    /// Free the side allocations of this storage, which nothing uses anymore once it is
231    /// the only reference to the storage.
232    ///
233    /// # Safety
234    ///
235    /// The caller has to own the only reference to the storage.
236    unsafe fn free_sides(self) {
237        let mut side = self.header().side.swap(ptr::null_mut(), Ordering::Relaxed);
238        while !side.is_null() {
239            // SAFETY: The side allocations are ours alone, and were allocated with the
240            // layout their header gives back.
241            unsafe {
242                let next = (*side).next;
243                alloc::dealloc(side.cast(), Self::side_layout((*side).size).unwrap_unchecked());
244                side = next;
245            }
246        }
247    }
248
249    /// Grow this storage to a capacity of at least that many octets, at least doubling it,
250    /// the octets it adds being zeroed. This may move the storage, hence the handle being
251    /// updated, and its side allocations with it.
252    ///
253    /// # Safety
254    ///
255    /// The caller has to own the only reference to the storage.
256    ///
257    /// When the allocation fails, the storage is left as it was.
258    #[cold]
259    unsafe fn grow(&mut self, capacity: usize) -> AllocResult<()> {
260        let old_cap = self.header().cap;
261        let cap = capacity.div_ceil(ALIGN).max(old_cap * 2);
262        // SAFETY: The layout of a live storage is valid.
263        let old_layout = unsafe { Self::layout(old_cap).unwrap_unchecked() };
264        let new_layout = Self::layout(cap).ok_or(None)?;
265        // SAFETY: The storage is ours alone, allocated with that layout.
266        let ptr = unsafe { alloc::realloc(self.0.as_ptr().cast(), old_layout, new_layout.size()) };
267        self.0 = NonNull::new(ptr.cast::<HeapHeader>()).ok_or(Some(new_layout))?;
268        // SAFETY: The new allocation holds the header, followed by that many units.
269        unsafe {
270            (*self.0.as_ptr()).cap = cap;
271            self.data().add(old_cap * ALIGN).write_bytes(0, (cap - old_cap) * ALIGN);
272        }
273        Ok(())
274    }
275
276}
277
278/// A side allocation that is not attached to a storage yet, see [`Heap::push_side`],
279/// which is freed if it never is: its payload is filled before the allocation is attached,
280/// so that nothing is left attached to a shared storage when filling it fails.
281struct DetachedSide(NonNull<SideHeader>);
282
283impl DetachedSide {
284
285    /// Allocate a side allocation of that payload size, whose payload is left
286    /// uninitialized and aligned on 8 octets.
287    fn new(size: usize) -> AllocResult<Self> {
288        let layout = Heap::side_layout(size).ok_or(None)?;
289        // SAFETY: The layout is never zero-sized, it always holds the side header.
290        let side = NonNull::new(unsafe { alloc::alloc(layout) }.cast::<SideHeader>()).ok_or(Some(layout))?;
291        // SAFETY: The allocation is valid for the side header.
292        unsafe { side.write(SideHeader { next: ptr::null_mut(), size }) };
293        Ok(Self(side))
294    }
295
296    /// The payload of this side allocation.
297    #[inline]
298    fn payload(&self) -> NonNull<u8> {
299        // SAFETY: The payload directly follows the side header, in the same allocation.
300        unsafe { self.0.add(1).cast::<u8>() }
301    }
302
303}
304
305impl Drop for DetachedSide {
306    fn drop(&mut self) {
307        // SAFETY: The side allocation was never attached, and was allocated with the layout
308        // its header gives back.
309        unsafe { alloc::dealloc(self.0.as_ptr().cast(), Heap::side_layout((*self.0.as_ptr()).size).unwrap_unchecked()) }
310    }
311}
312
313/// A reference to a storage, and where in it: what a [`Buf`] is made of, unless it is held
314/// in place.
315struct HeapRef {
316    /// Inner pointer to the heap.
317    inner: Heap,
318    /// Offset in the storage, in octets.
319    offset: usize,
320}
321
322impl HeapRef {
323
324    /// A reference to the storage of whatever holds no values at all.
325    const EMPTY: Self = Self {
326        inner: Heap::EMPTY,
327        offset: 0,
328    };
329
330    /// A reference to a new storage of a copy of these octets, of at least that capacity.
331    fn copy(bytes: &[u8], capacity: usize) -> AllocResult<Self> {
332        let storage = Heap::alloc(bytes.len().max(capacity))?;
333        // SAFETY: The storage holds at least that many octets.
334        unsafe { ptr::copy_nonoverlapping(bytes.as_ptr(), storage.data(), bytes.len()) };
335        Ok(Self { inner: storage, offset: 0 })
336    }
337
338    /// Where these octets start in the storage.
339    #[inline]
340    fn ptr(&self) -> *mut u8 {
341        // SAFETY: The offset is within the storage.
342        unsafe { self.inner.data().add(self.offset) }
343    }
344
345    /// Another reference to the same storage, that many octets further.
346    #[inline]
347    fn clone_at(&self, count: usize) -> Self {
348        self.inner.acquire();
349        Self { inner: self.inner, offset: self.offset + count }
350    }
351
352    #[inline]
353    fn is_unique(&self) -> bool {
354        self.inner.is_unique()
355    }
356
357    /// Whether what holds this reference can be a [`BufMut`]: when it is the only reference
358    /// to its storage, or when this is the empty storage, which a buffer never writes but
359    /// grows out of, see [`BufMut::reserve`].
360    #[inline]
361    fn is_writable(&self) -> bool {
362        self.inner.is_immortal() || self.inner.is_unique()
363    }
364
365}
366
367impl Clone for HeapRef {
368    #[inline]
369    fn clone(&self) -> Self {
370        self.clone_at(0)
371    }
372}
373
374impl Drop for HeapRef {
375    #[inline]
376    fn drop(&mut self) {
377        // SAFETY: This owns its reference, and is not used anymore.
378        unsafe { self.inner.release() }
379    }
380}
381
382
383// =========================== //
384//            Spans            //
385// =========================== //
386
387/// Where the values of a [`Buf`] are in its storage: the range of octets of each of them,
388/// either computed, see [`PackedSpans`], or given by a table, see [`TableSpans`].
389///
390/// # Safety
391///
392/// The ranges must be those the buffer was built with.
393pub unsafe trait Spans: Copy + Send + Sync + 'static {
394
395    /// The spans of no values at all.
396    const EMPTY: Self;
397
398    /// The offset and the length, in octets, of the value at that index, relative to where
399    /// the buffer starts in its storage.
400    ///
401    /// # Safety
402    ///
403    /// The buffer these are the spans of must hold a value at that index.
404    unsafe fn span(self, index: usize) -> (usize, usize);
405
406    /// How many octets further the buffer starts, and the spans, of the buffer starting
407    /// that many values further, which is what slicing is made of.
408    ///
409    /// # Safety
410    ///
411    /// The buffer these are the spans of must hold at least that many values.
412    unsafe fn advance(self, count: usize) -> (usize, Self);
413
414}
415
416/// The spans of values packed one after the other, each as many octets as their type:
417/// nothing is stored, the range of a value is computed from its index.
418pub struct PackedSpans<T>(PhantomData<fn() -> T>);
419
420impl<T> PackedSpans<T> {
421    #[inline]
422    const fn new() -> Self {
423        Self(PhantomData)
424    }
425}
426
427impl<T> Clone for PackedSpans<T> {
428    #[inline]
429    fn clone(&self) -> Self {
430        *self
431    }
432}
433
434impl<T> Copy for PackedSpans<T> {}
435
436// SAFETY: The ranges are those of packed values of that type.
437unsafe impl<T: 'static> Spans for PackedSpans<T> {
438
439    const EMPTY: Self = Self::new();
440
441    #[inline]
442    unsafe fn span(self, index: usize) -> (usize, usize) {
443        (index * mem::size_of::<T>(), mem::size_of::<T>())
444    }
445
446    #[inline]
447    unsafe fn advance(self, count: usize) -> (usize, Self) {
448        (count * mem::size_of::<T>(), self)
449    }
450
451}
452
453/// The spans of values anywhere in the storage, each given by a table of ranges of octets,
454/// relative to where the buffer starts: the table is a side allocation of the storage, so
455/// it lives as long as the storage without being counted, and slicing the values only
456/// moves the pointer to their ranges.
457#[derive(Clone, Copy)]
458pub struct TableSpans(NonNull<Range<u32>>);
459
460// SAFETY: The table is never written once it is shared.
461unsafe impl Send for TableSpans {}
462unsafe impl Sync for TableSpans {}
463
464// SAFETY: The ranges are those of the table, checked when it was built.
465unsafe impl Spans for TableSpans {
466
467    const EMPTY: Self = Self(NonNull::dangling());
468
469    #[inline]
470    unsafe fn span(self, index: usize) -> (usize, usize) {
471        // SAFETY: The caller guarantees the range is there, and it was checked not to be
472        // inverted when the table was built.
473        let Range { start, end } = unsafe { self.0.add(index).read() };
474        (start as usize, (end - start) as usize)
475    }
476
477    #[inline]
478    unsafe fn advance(self, count: usize) -> (usize, Self) {
479        // SAFETY: The caller guarantees there are that many spans.
480        (0, Self(unsafe { self.0.add(count) }))
481    }
482
483}
484
485
486// =========================== //
487//           Elements          //
488// =========================== //
489
490/// A type of the values a [`Buf`] holds: where they are in its storage, see [`Spans`], and
491/// what octets are one of them.
492///
493/// This is implemented for every [`PackedElement`], and for [`str`](prim@str), whose values are at
494/// the spans of a table.
495///
496/// # Safety
497///
498/// [`Self::read`] must be sound for any octets [`Self::validate`] accepts.
499pub unsafe trait Element: Send + Sync + 'static {
500
501    /// How one value is given out: by value for a packed type, borrowed for a string.
502    type Ref<'a>: Copy + Debug;
503
504    /// Where the values are in the storage.
505    type Spans: Spans;
506
507    /// Whether a scalar of this type is held in place of a storage, which only a packed
508    /// type small enough can be.
509    const INLINE_FIXED: bool;
510
511    /// Whether these octets are one valid value.
512    fn validate(bytes: &[u8]) -> bool;
513
514    /// The value in these octets.
515    ///
516    /// # Safety
517    ///
518    /// The octets must have been accepted by [`Self::validate`], and be aligned for a
519    /// packed type.
520    unsafe fn read<'a>(ptr: *const u8, len: usize) -> Self::Ref<'a>
521    where
522        Self: 'a;
523
524    /// Format the values of one row of a buffer for [`Debug`], along its first dimension,
525    /// within the brackets of that row: separated by commas unless a type has a better way.
526    fn fmt_row<'a, I>(values: I, f: &mut fmt::Formatter<'_>) -> fmt::Result
527    where
528        I: Iterator<Item = Self::Ref<'a>>,
529        Self: 'a,
530    {
531        for (index, value) in values.enumerate() {
532            if index != 0 {
533                f.write_str(", ")?;
534            }
535            Debug::fmt(&value, f)?;
536        }
537        Ok(())
538    }
539
540}
541
542/// An element whose values are packed as their octets, one after the other, which is what
543/// allows a [`Buf`] of them to be seen as a slice, see [`Buf::as_slice`], and written, see
544/// [`BufMut`].
545///
546/// # Safety
547///
548/// The type must have no padding and not be zero-sized, its values must be exactly the
549/// octets [`Self::validate_all`] accepts, read as they are, and octets that are all zeroes
550/// must be a valid value, which is what new room in a storage holds.
551pub unsafe trait PackedElement: Element<Spans = PackedSpans<Self>> + Copy {
552
553    /// Whether the octets of a whole number of consecutive values are all valid values,
554    /// in a single pass: what octets are checked with when they are cast, and what
555    /// [`Element::validate`] is for one value.
556    fn validate_all(bytes: &[u8]) -> bool;
557
558}
559
560/// What [`Element::INLINE_FIXED`] is for a packed type, checking it can be held in place.
561const fn inline_fixed<T>() -> bool {
562    assert!(mem::size_of::<T>() > 0, "a packed type is not zero-sized");
563    assert!(mem::size_of::<T>() <= mem::size_of::<Repr>(), "a packed type fits in place of a storage");
564    assert!(mem::align_of::<T>() <= ALIGN, "a packed type is aligned on at most 8 octets");
565    true
566}
567
568/// Implement [`PackedElement`] for these types, all of whose octet patterns are valid
569/// values unless a check of each octet is given.
570macro_rules! impl_packed_element {
571    ($($ty:ty $(where |$octet:ident| $valid:expr)? $(, debug $debug:path)?);* $(;)?) => { $(
572        // SAFETY: The type has no padding, and is read from the octets validated.
573        unsafe impl Element for $ty {
574
575            type Ref<'a> = $ty;
576            type Spans = PackedSpans<$ty>;
577
578            const INLINE_FIXED: bool = inline_fixed::<$ty>();
579
580            #[inline]
581            fn validate(bytes: &[u8]) -> bool {
582                bytes.len() == mem::size_of::<$ty>() && Self::validate_all(bytes)
583            }
584
585            #[inline]
586            unsafe fn read<'a>(ptr: *const u8, _len: usize) -> $ty
587            where
588                $ty: 'a,
589            {
590                // SAFETY: The caller guarantees the value is there, and aligned.
591                unsafe { ptr.cast::<$ty>().read() }
592            }
593
594            $(
595            #[inline]
596            fn fmt_row<'a, I>(values: I, f: &mut fmt::Formatter<'_>) -> fmt::Result
597            where
598                I: Iterator<Item = $ty>,
599                $ty: 'a,
600            {
601                $debug(values, f)
602            }
603            )?
604
605        }
606
607        // SAFETY: Same as above, and zero is a valid value of each of these types.
608        unsafe impl PackedElement for $ty {
609            #[inline]
610            fn validate_all(_bytes: &[u8]) -> bool {
611                true $(&& _bytes.iter().all(|&$octet| $valid))?
612            }
613        }
614    )* };
615}
616
617impl_packed_element!(
618    u8, debug fmt_octets;
619    i8; u16; i16; u32; i32; u64; i64; f32; f64; DevEnum;
620    bool where |octet| octet <= 1;
621    DevState where |octet| octet <= DevState::Unknown as u8;
622);
623
624/// Format octets as hexadecimal for [`Debug`], with runs of readable ASCII quoted, which is
625/// how the octets of a stream are best told apart.
626fn fmt_octets(octets: impl Iterator<Item = u8>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
627
628    let mut ascii = false;
629
630    for (index, byte) in octets.enumerate() {
631
632        if index != 0 && !ascii {
633            f.write_str(" ")?;
634        }
635
636        if byte.is_ascii_alphanumeric() || matches!(byte, b' ' | b':' | b'/' | b'.' | b'-' | b'_') {
637            if !ascii {
638                f.write_str("'")?;
639                ascii = true;
640            }
641            write!(f, "{}", byte as char)?;
642        } else {
643            if ascii {
644                f.write_str("' ")?;
645                ascii = false;
646            }
647            write!(f, "{byte:02X}")?;
648        }
649
650    }
651
652    if ascii {
653        f.write_str("'")?;
654    }
655
656    Ok(())
657
658}
659
660/// Format the octets of packed values as hexadecimal, two digits each, in the order they
661/// are stored. The octets of each value are grouped together, groups being separated by a
662/// space, except for octets, which are a single run that [`BufMut::from_hex`] parses back.
663fn fmt_hex<T: PackedElement>(octets: &[u8], f: &mut fmt::Formatter<'_>, upper: bool) -> fmt::Result {
664    let size = mem::size_of::<T>();
665    for (index, &byte) in octets.iter().enumerate() {
666        if size > 1 && index != 0 && index % size == 0 {
667            f.write_str(" ")?;
668        }
669        if upper { write!(f, "{byte:02X}")? } else { write!(f, "{byte:02x}")? }
670    }
671    Ok(())
672}
673
674// SAFETY: A string is read from octets that are valid UTF-8.
675unsafe impl Element for str {
676
677    type Ref<'a> = &'a str;
678    type Spans = TableSpans;
679
680    const INLINE_FIXED: bool = false;
681
682    #[inline]
683    fn validate(bytes: &[u8]) -> bool {
684        str::from_utf8(bytes).is_ok()
685    }
686
687    #[inline]
688    unsafe fn read<'a>(ptr: *const u8, len: usize) -> &'a str
689    where
690        str: 'a,
691    {
692        // SAFETY: The caller guarantees the octets are there, and valid UTF-8.
693        unsafe { str::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) }
694    }
695
696}
697
698
699// =========================== //
700//           Buffers           //
701// =========================== //
702
703/// Either a reference to the storage of a buffer, or a scalar held in place, which of the
704/// two being known from the type of the buffer, see [`Buf::INLINE`].
705#[repr(C)]
706union Repr {
707    raw: ManuallyDrop<HeapRef>,
708    inline: [MaybeUninit<u64>; mem::size_of::<HeapRef>() / 8],
709}
710
711/// A shared, typed, N-dimensional array of values, in column-major order, a scalar for
712/// `DIM == 0`. Its dimensions are fixed once it is built. Octets are a `Buf<u8, 1>`, cast to other packed types with [`Self::cast`], and
713/// turned into strings with [`Buf::from_spans`].
714///
715/// Cloning a buffer only counts one more reference to its storage, and so does slicing it,
716/// which is what allows the buffer of a received message to be handed out in pieces without
717/// copying any of it. A packed scalar is held in place and has no storage.
718pub struct Buf<T: Element + ?Sized, const DIM: usize> {
719    repr: Repr,
720    spans: T::Spans,
721    dim: [usize; DIM],
722    _t: PhantomData<*const T>,
723}
724
725// SAFETY: The storage is only written through a unique reference, see `BufMut`, and the
726// side allocations are never written once shared; the elements are `Send + Sync`.
727unsafe impl<T: Element + ?Sized, const DIM: usize> Send for Buf<T, DIM> {}
728unsafe impl<T: Element + ?Sized, const DIM: usize> Sync for Buf<T, DIM> {}
729
730/// The number of values of an array of those dimensions, absent if it overflows.
731#[inline]
732fn checked_len(dim: &[usize]) -> Option<usize> {
733    dim.iter().try_fold(1usize, |len, &d| len.checked_mul(d))
734}
735
736/// The bounds of that range over a length, panicking like slice indexing does.
737#[track_caller]
738fn range_bounds<R: RangeBounds<usize>>(range: R, len: usize) -> Range<usize> {
739    let start = match range.start_bound() {
740        Bound::Included(&start) => start,
741        Bound::Excluded(&start) => start.checked_add(1).expect("range start overflow"),
742        Bound::Unbounded => 0,
743    };
744    let end = match range.end_bound() {
745        Bound::Included(&end) => end.checked_add(1).expect("range end overflow"),
746        Bound::Excluded(&end) => end,
747        Bound::Unbounded => len,
748    };
749    assert!(start <= end, "slice index starts at {start} but ends at {end}");
750    assert!(end <= len, "range end index {end} out of range for length {len}");
751    start..end
752}
753
754
755impl<T: Element + ?Sized, const DIM: usize> Buf<T, DIM> {
756
757    /// Whether the buffer is held in place rather than in a storage, which only a scalar of
758    /// a packed type is, and which is known from its type alone.
759    const INLINE: bool = DIM == 0 && T::INLINE_FIXED;
760
761    /// A buffer of no values, all its dimensions being zero, which allocates nothing: every
762    /// empty buffer shares the same static storage.
763    #[inline]
764    pub const fn new() -> Self {
765        const { assert!(DIM >= 1, "a scalar always holds one value") };
766        let raw = ManuallyDrop::new(HeapRef::EMPTY);
767        Self {
768            repr: Repr { raw },
769            spans: T::Spans::EMPTY,
770            dim: [0; DIM],
771            _t: PhantomData,
772        }
773    }
774
775    /// A buffer of the values at that reference to a storage.
776    ///
777    /// # Safety
778    ///
779    /// The buffer must not be inline, and the storage must hold its values there, with
780    /// those spans, aligned for a packed type.
781    #[inline]
782    unsafe fn from_raw(raw: HeapRef, spans: T::Spans, dim: [usize; DIM]) -> Self {
783        debug_assert!(!Self::INLINE);
784        Self {
785            repr: Repr { raw: ManuallyDrop::new(raw) },
786            spans,
787            dim,
788            _t: PhantomData,
789        }
790    }
791
792    /// The reference to the storage of this buffer, which must not be inline.
793    #[inline]
794    fn raw(&self) -> &HeapRef {
795        debug_assert!(!Self::INLINE);
796        // SAFETY: A buffer that is not inline always holds a reference to its storage.
797        unsafe { &self.repr.raw }
798    }
799
800    /// [`Self::raw`], writable, for a buffer that changes its storage or where in it it is.
801    #[inline]
802    fn raw_mut(&mut self) -> &mut HeapRef {
803        debug_assert!(!Self::INLINE);
804        // SAFETY: A buffer that is not inline always holds a reference to its storage.
805        unsafe { &mut self.repr.raw }
806    }
807
808    /// The reference to the storage of this buffer, which must not be inline, moved out of
809    /// it.
810    #[inline]
811    fn into_raw(self) -> HeapRef {
812        let this = ManuallyDrop::new(self);
813        // SAFETY: The reference is moved out of a buffer that is never dropped.
814        unsafe { ptr::read(this.raw()) }
815    }
816
817    /// Where the values of this buffer start, which its spans are relative to.
818    #[inline]
819    fn base(&self) -> *const u8 {
820        if Self::INLINE {
821            ptr::addr_of!(self.repr).cast::<u8>()
822        } else {
823            self.raw().ptr()
824        }
825    }
826
827    /// [`Self::base`], writable: a scalar held in place is only writable through a pointer
828    /// taken from an exclusive reference.
829    #[inline]
830    fn base_mut(&mut self) -> *mut u8 {
831        if Self::INLINE {
832            ptr::addr_of_mut!(self.repr).cast::<u8>()
833        } else {
834            self.raw().ptr()
835        }
836    }
837
838    /// The value at that index.
839    ///
840    /// # Safety
841    ///
842    /// The index must be below the length.
843    #[inline]
844    unsafe fn read(&self, index: usize) -> T::Ref<'_> {
845        // SAFETY: The spans give the range of a value this buffer holds, validated.
846        unsafe {
847            let (offset, len) = self.spans.span(index);
848            T::read(self.base().add(offset), len)
849        }
850    }
851
852    /// The dimensions of this buffer, the first one varying the fastest.
853    #[inline]
854    pub fn dim(&self) -> [usize; DIM] {
855        self.dim
856    }
857
858    /// The number of values of this buffer, 1 for a scalar.
859    #[inline]
860    pub fn len(&self) -> usize {
861        self.dim.iter().product()
862    }
863
864    #[inline]
865    pub fn is_empty(&self) -> bool {
866        self.len() == 0
867    }
868
869    /// The index among the values of this buffer of the value at that position, one
870    /// coordinate per dimension, in column-major order: the first coordinate is the one
871    /// varying the fastest. Absent if a coordinate is out of its dimension.
872    #[inline]
873    pub fn raw_index(&self, pos: [usize; DIM]) -> Option<usize> {
874        let mut index = 0;
875        let mut stride = 1;
876        for (&coord, &dim) in pos.iter().zip(&self.dim) {
877            if coord >= dim {
878                return None;
879            }
880            index += coord * stride;
881            stride *= dim;
882        }
883        Some(index)
884    }
885
886    /// The value at that position, one coordinate per dimension, `[x]` for one and `[x, y]`
887    /// for two, `[]` giving the value of a scalar. Absent if a coordinate is
888    /// out of its dimension.
889    #[inline]
890    pub fn get(&self, pos: [usize; DIM]) -> Option<T::Ref<'_>> {
891        let index = self.raw_index(pos)?;
892        // SAFETY: The index of a position within the dimensions is below the length.
893        Some(unsafe { self.read(index) })
894    }
895
896    /// The value at that position as a scalar of its own, see [`Self::get`]: copied in
897    /// place for a packed type, sharing the storage for a string. Absent if a coordinate
898    /// is out of its dimension.
899    pub fn get_scalar(&self, pos: [usize; DIM]) -> Option<Buf<T, 0>> {
900
901        let index = self.raw_index(pos)?;
902
903        if Buf::<T, 0>::INLINE {
904            let mut repr = Repr { inline: [MaybeUninit::uninit(); _] };
905            // SAFETY: The index is within the buffer, and a packed value fits in place, see
906            // `inline_fixed`; the spans of packed values are the same wherever they are.
907            unsafe {
908                let (offset, len) = self.spans.span(index);
909                ptr::copy_nonoverlapping(self.base().add(offset), ptr::addr_of_mut!(repr).cast::<u8>(), len);
910            }
911            Some(Buf { repr, spans: self.spans, dim: [], _t: PhantomData })
912        } else {
913            // SAFETY: The index is within the buffer, and a type that is not held in place
914            // as a scalar is not held in place here either; the value starts whole values
915            // further, so it is aligned.
916            unsafe {
917                let (octets, spans) = self.spans.advance(index);
918                Some(Buf::from_raw(self.raw().clone_at(octets), spans, []))
919            }
920        }
921
922    }
923
924    /// The value at that index among the values of this buffer, in column-major order, see
925    /// [`Self::raw_index`]. Absent if the index is out of the length.
926    #[inline]
927    pub fn get_raw(&self, index: usize) -> Option<T::Ref<'_>> {
928        // SAFETY: The index is checked against the length.
929        (index < self.len()).then(|| unsafe { self.read(index) })
930    }
931
932    /// The values of this buffer, in column-major order.
933    #[inline]
934    pub fn iter(&self) -> impl ExactSizeIterator<Item = T::Ref<'_>> + '_ {
935        // SAFETY: The indices are all below the length.
936        (0..self.len()).map(move |index| unsafe { self.read(index) })
937    }
938
939    /// The part of this buffer within that range of its last dimension, which is the
940    /// slowest varying one, so that the part shares the same storage: a range of values for
941    /// one dimension, a range of rows for two.
942    ///
943    /// # Panics
944    ///
945    /// If the range is out of the last dimension, like slice indexing.
946    #[track_caller]
947    pub fn slice<R: RangeBounds<usize>>(&self, range: R) -> Self {
948
949        const { assert!(DIM >= 1, "a scalar cannot be sliced") };
950        let Range { start, end } = range_bounds(range, self.dim[DIM - 1]);
951
952        let stride: usize = self.dim[..DIM - 1].iter().product();
953        
954        // SAFETY: The range is within the buffer.
955        let (octets, spans) = unsafe { self.spans.advance(start * stride) };
956        let mut dim = self.dim;
957        dim[DIM - 1] = end - start;
958
959        // SAFETY: The storage holds the values of the part there, aligned since they are
960        // whole values further.
961        unsafe { Self::from_raw(self.raw().clone_at(octets), spans, dim) }
962
963    }
964
965    /// Take the part of this buffer before `at` along its last dimension out as a buffer
966    /// of its own, this one keeping the part from `at` on, both sharing the storage: how a
967    /// message is framed out of the octets that arrived, the ones behind it being the
968    /// front of the next ones.
969    ///
970    /// # Panics
971    ///
972    /// If `at` is past the last dimension.
973    #[track_caller]
974    pub fn split_to(&mut self, at: usize) -> Self {
975        let front = self.slice(..at);
976        *self = self.slice(at..);
977        front
978    }
979
980    /// Take the part of this buffer from `at` on along its last dimension out as a buffer
981    /// of its own, this one keeping the part before `at`, both sharing the storage.
982    ///
983    /// # Panics
984    ///
985    /// If `at` is past the last dimension.
986    #[track_caller]
987    pub fn split_off(&mut self, at: usize) -> Self {
988        let back = self.slice(at..);
989        *self = self.slice(..at);
990        back
991    }
992
993    /// The same values with other dimensions, as long as they are as many: typically values
994    /// decoded in one dimension and given the two dimensions they actually have. A scalar is
995    /// one value, so it is reshaped to and from any dimensions of one value, being copied
996    /// in or out of place for a packed type, see [`Buf`].
997    pub fn reshape<const D: usize>(self, dim: [usize; D]) -> Option<Buf<T, D>> {
998        if checked_len(&dim)? != self.len() {
999            return None;
1000        }
1001        let spans = self.spans;
1002        // SAFETY: In every case, the values are kept with their spans, and are as many.
1003        Some(match (Self::INLINE, Buf::<T, D>::INLINE) {
1004            (false, false) => unsafe { Buf::from_raw(self.into_raw(), spans, dim) },
1005            // SAFETY: A buffer held in place always holds its inline octets.
1006            (true, true) => Buf { repr: Repr { inline: unsafe { self.repr.inline } }, spans, dim, _t: PhantomData },
1007            (true, false) => unsafe {
1008                let (offset, len) = spans.span(0);
1009                let bytes = slice::from_raw_parts(self.base().add(offset), len);
1010                Buf::from_raw(infallible(HeapRef::copy(bytes, len)), spans, dim)
1011            },
1012            (false, true) => {
1013                let raw = self.into_raw();
1014                let mut repr = Repr { inline: [MaybeUninit::uninit(); _] };
1015                // SAFETY: The value is copied in place, which is large enough, see
1016                // `inline_fixed`, before the reference is released.
1017                unsafe {
1018                    let (offset, len) = spans.span(0);
1019                    ptr::copy_nonoverlapping(raw.ptr().add(offset), ptr::addr_of_mut!(repr).cast::<u8>(), len);
1020                }
1021                Buf { repr, spans, dim, _t: PhantomData }
1022            }
1023        })
1024    }
1025
1026    /// The single value of this buffer as a scalar, absent if it does not hold exactly one:
1027    /// typically a scalar decoded as one dimension of one, see [`Self::reshape`].
1028    #[inline]
1029    pub fn into_scalar(self) -> Option<Buf<T, 0>> {
1030        self.reshape([])
1031    }
1032
1033    /// Whether this buffer is the only reference to its storage, which a buffer held in
1034    /// place always is.
1035    #[inline]
1036    pub fn is_unique(&self) -> bool {
1037        Self::INLINE || self.raw().is_unique()
1038    }
1039
1040    /// Whether this buffer can be a [`BufMut`], see [`HeapRef::is_writable`].
1041    #[inline]
1042    fn is_writable(&self) -> bool {
1043        Self::INLINE || self.raw().is_writable()
1044    }
1045
1046}
1047
1048impl<T: Element + ?Sized> Buf<T, 1> {
1049
1050    /// Keep only the first values, no more than that many.
1051    #[inline]
1052    pub fn truncate(&mut self, len: usize) {
1053        self.dim[0] = self.dim[0].min(len);
1054    }
1055
1056}
1057
1058impl<T: Element + ?Sized> Buf<T, 0> {
1059
1060    /// The value of this scalar.
1061    #[inline]
1062    pub fn value(&self) -> T::Ref<'_> {
1063        // SAFETY: A scalar always holds one value.
1064        unsafe { self.read(0) }
1065    }
1066
1067}
1068
1069// --- Standard traits impl --- //
1070
1071impl<T: Element + ?Sized, const DIM: usize> Clone for Buf<T, DIM> {
1072    #[inline]
1073    fn clone(&self) -> Self {
1074        let repr = if Self::INLINE {
1075            // SAFETY: A buffer held in place always holds its inline octets.
1076            Repr { inline: unsafe { self.repr.inline } }
1077        } else {
1078            Repr { raw: ManuallyDrop::new(self.raw().clone()) }
1079        };
1080        Self { repr, spans: self.spans, dim: self.dim, _t: PhantomData }
1081    }
1082}
1083
1084impl<T: Element + ?Sized, const DIM: usize> Drop for Buf<T, DIM> {
1085    #[inline]
1086    fn drop(&mut self) {
1087        if !Self::INLINE {
1088            // SAFETY: A buffer that is not inline always holds a reference, not used anymore.
1089            unsafe { ManuallyDrop::drop(&mut self.repr.raw) }
1090        }
1091    }
1092}
1093
1094impl<T: Element + ?Sized, const DIM: usize> Default for Buf<T, DIM> {
1095    /// An empty buffer, see [`Self::new`].
1096    #[inline]
1097    fn default() -> Self {
1098        Self::new()
1099    }
1100}
1101
1102impl<T: Element + ?Sized, const DIM: usize> PartialEq for Buf<T, DIM>
1103where
1104    for<'a> T::Ref<'a>: PartialEq,
1105{
1106    /// Two buffers are equal if they have the same dimensions and values, wherever these
1107    /// are.
1108    fn eq(&self, other: &Self) -> bool {
1109        self.dim == other.dim && self.iter().eq(other.iter())
1110    }
1111}
1112
1113impl<T: Element + ?Sized, const DIM: usize> Eq for Buf<T, DIM>
1114where
1115    for<'a> T::Ref<'a>: Eq,
1116{}
1117
1118// --- Formatters --- //
1119
1120/// Format a buffer for [`Debug`]: its name and dimensions, and its values with one pair of
1121/// brackets per dimension, the first one innermost, `Buf<3, 2>[[1, 2, 3], [4, 5, 6]]`, or
1122/// one row per line in the alternate form. A scalar is its value in parentheses.
1123fn fmt_buf<'a, T, I>(f: &mut fmt::Formatter<'_>, name: &str, dim: &[usize], mut values: I) -> fmt::Result
1124where
1125    T: Element + ?Sized + 'a,
1126    I: Iterator<Item = T::Ref<'a>>,
1127{
1128    f.write_str(name)?;
1129    if dim.is_empty() {
1130        f.write_str("(")?;
1131        T::fmt_row(values, f)?;
1132        return f.write_str(")");
1133    }
1134    f.write_str("<")?;
1135    for (index, d) in dim.iter().enumerate() {
1136        if index != 0 {
1137            f.write_str(", ")?;
1138        }
1139        write!(f, "{d}")?;
1140    }
1141    f.write_str(">")?;
1142    fmt_level::<T, I>(f, dim, 0, &mut values)
1143}
1144
1145/// Format the values within the last of these dimensions, at that depth of nesting.
1146fn fmt_level<'a, T, I>(f: &mut fmt::Formatter<'_>, dim: &[usize], depth: usize, values: &mut I) -> fmt::Result
1147where
1148    T: Element + ?Sized + 'a,
1149    I: Iterator<Item = T::Ref<'a>>,
1150{
1151    const INDENT: usize = 4;
1152    let (&len, inner) = dim.split_last().expect("at least one dimension");
1153    f.write_str("[")?;
1154    if inner.is_empty() {
1155        T::fmt_row(values.by_ref().take(len), f)?;
1156    } else {
1157        let pretty = f.alternate();
1158        for index in 0..len {
1159            if pretty {
1160                write!(f, "\n{:1$}", "", (depth + 1) * INDENT)?;
1161            } else if index != 0 {
1162                f.write_str(", ")?;
1163            }
1164            fmt_level::<T, I>(f, inner, depth + 1, values)?;
1165            if pretty {
1166                f.write_str(",")?;
1167            }
1168        }
1169        if pretty && len != 0 {
1170            write!(f, "\n{:1$}", "", depth * INDENT)?;
1171        }
1172    }
1173    f.write_str("]")
1174}
1175
1176impl<T: Element + ?Sized, const DIM: usize> Debug for Buf<T, DIM> {
1177    /// Its dimensions and values, row by row, see [`Element::fmt_row`].
1178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1179        fmt_buf::<T, _>(f, "Buf", &self.dim, self.iter())
1180    }
1181}
1182
1183impl<T: PackedElement> UpperHex for Buf<T, 1> {
1184    /// The octets of the values as hexadecimal, in the order they are stored, each value's
1185    /// grouped and separated by a space, octets being a single run that
1186    /// [`BufMut::from_hex`] parses back.
1187    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1188        fmt_hex::<T>(self.as_bytes(), f, true)
1189    }
1190}
1191
1192impl<T: PackedElement> LowerHex for Buf<T, 1> {
1193    /// The octets of the values as hexadecimal, in the order they are stored, each value's
1194    /// grouped and separated by a space, octets being a single run that
1195    /// [`BufMut::from_hex`] parses back.
1196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1197        fmt_hex::<T>(self.as_bytes(), f, false)
1198    }
1199}
1200
1201// --- Packed --- //
1202
1203impl<T: PackedElement, const DIM: usize> Buf<T, DIM> {
1204
1205    /// Whether these octets are valid values, as many as the dimensions say, absent if
1206    /// not, and then whether a buffer of them can share their storage, being aligned and
1207    /// not held in place.
1208    #[inline]
1209    fn check_packed(bytes: &[u8], dim: [usize; DIM]) -> Option<bool> {
1210        let size = checked_len(&dim)?.checked_mul(mem::size_of::<T>())?;
1211        if bytes.len() != size || !T::validate_all(bytes) {
1212            return None;
1213        }
1214        Some(!Self::INLINE && bytes.as_ptr().addr() % mem::align_of::<T>() == 0)
1215    }
1216
1217    /// A buffer of a copy of these octets, held in place for a scalar, and allocating
1218    /// nothing if there are none.
1219    ///
1220    /// # Safety
1221    ///
1222    /// The octets must be valid values, as many as the dimensions say.
1223    unsafe fn copy_from_bytes(bytes: &[u8], dim: [usize; DIM]) -> Self {
1224        if Self::INLINE {
1225            let mut repr = Repr { inline: [MaybeUninit::uninit(); _] };
1226            // SAFETY: The inline octets are large enough, see `inline_fixed`.
1227            unsafe { ptr::copy_nonoverlapping(bytes.as_ptr(), ptr::addr_of_mut!(repr).cast::<u8>(), bytes.len()) };
1228            Self { repr, spans: PackedSpans::new(), dim, _t: PhantomData }
1229        } else if bytes.is_empty() {
1230            // SAFETY: The empty storage holds no values, as many as the dimensions say.
1231            unsafe { Self::from_raw(HeapRef::EMPTY, PackedSpans::new(), dim) }
1232        } else {
1233            // SAFETY: A new storage is aligned for any packed type.
1234            unsafe { Self::from_raw(infallible(HeapRef::copy(bytes, bytes.len())), PackedSpans::new(), dim) }
1235        }
1236    }
1237
1238    /// A buffer of these values, with those dimensions, copied into a new storage unless it
1239    /// is a scalar, which is held in place. Absent if the values are not as many as the
1240    /// dimensions say.
1241    pub fn from_slice(values: &[T], dim: [usize; DIM]) -> Option<Self> {
1242        if checked_len(&dim)? != values.len() {
1243            return None;
1244        }
1245        // SAFETY: A packed type has no padding, so its values are all initialized octets.
1246        let bytes = unsafe { slice::from_raw_parts(values.as_ptr().cast::<u8>(), mem::size_of_val(values)) };
1247        // SAFETY: The octets are those of valid values, as many as the dimensions say.
1248        Some(unsafe { Self::copy_from_bytes(bytes, dim) })
1249    }
1250
1251    /// A buffer of zeroes with those dimensions, see [`BufMut::zeroed`].
1252    #[inline]
1253    pub fn zeroed(dim: [usize; DIM]) -> Self {
1254        BufMut::zeroed(dim).freeze()
1255    }
1256
1257    /// Where the values of this buffer start.
1258    #[inline]
1259    pub fn as_ptr(&self) -> *const T {
1260        self.base().cast::<T>()
1261    }
1262
1263    /// The values of this buffer, in column-major order.
1264    #[inline]
1265    pub fn as_slice(&self) -> &[T] {
1266        // SAFETY: The buffer holds that many initialized and aligned values.
1267        unsafe { slice::from_raw_parts(self.as_ptr(), self.len()) }
1268    }
1269
1270    /// The octets of the values of this buffer, what a backend encodes them from.
1271    #[inline]
1272    pub fn as_bytes(&self) -> &[u8] {
1273        // SAFETY: A packed type has no padding, so its values are all initialized octets.
1274        unsafe { slice::from_raw_parts(self.base(), self.len() * mem::size_of::<T>()) }
1275    }
1276
1277    /// The octets of this buffer as packed values of another type, with those dimensions,
1278    /// sharing its storage if they are aligned for that type, and copied otherwise, or
1279    /// held in place for a scalar. The buffer is given back if it does not hold as many
1280    /// octets as the dimensions say, or holds an invalid value.
1281    ///
1282    /// This is how a backend decodes an array out of the message it received, in native
1283    /// byte order, typically out of a slice of it.
1284    pub fn cast<U: PackedElement, const D: usize>(self, dim: [usize; D]) -> Result<Buf<U, D>, Self> {
1285
1286        let Some(share) = Buf::<U, D>::check_packed(self.as_bytes(), dim) else { 
1287            return Err(self);
1288        };
1289
1290        // SAFETY: Checked above, the storage being shared only if this one has one.
1291        Ok(unsafe {
1292            if share && !Self::INLINE {
1293                Buf::from_raw(self.into_raw(), PackedSpans::new(), dim)
1294            } else {
1295                Buf::copy_from_bytes(self.as_bytes(), dim)
1296            }
1297        })
1298
1299    }
1300
1301    /// The octets of the values of this buffer, a new buffer for a scalar held in place.
1302    pub fn into_bytes(self) -> Buf<u8, 1> {
1303        let len = self.as_bytes().len();
1304        match self.cast([len]) {
1305            Ok(bytes) => bytes,
1306            Err(_) => unreachable!("every octet is a valid one"),
1307        }
1308    }
1309
1310    /// This buffer as a writable one, for as long as it is borrowed, absent if its storage
1311    /// is shared, like `Arc::get_mut`.
1312    #[inline]
1313    pub fn get_mut(&mut self) -> Option<&mut BufMut<T, DIM>> {
1314        // SAFETY: The buffer is the only reference to its storage, and nothing can share
1315        // it while it is exclusively borrowed.
1316        self.is_writable().then(|| unsafe { &mut *(self as *mut Self).cast::<BufMut<T, DIM>>() })
1317    }
1318
1319    /// This buffer as a writable one, for as long as it is borrowed, which first copies its
1320    /// values into a storage of their own if its storage is shared: only these values are
1321    /// copied, not the whole storage.
1322    #[inline]
1323    pub fn make_mut(&mut self) -> &mut BufMut<T, DIM> {
1324        if !self.is_writable() {
1325            // SAFETY: The octets are those of the values of this buffer.
1326            *self = unsafe { Self::copy_from_bytes(self.as_bytes(), self.dim) };
1327        }
1328        // SAFETY: The buffer is the only reference to its storage, and borrowed as such.
1329        unsafe { &mut *(self as *mut Self).cast::<BufMut<T, DIM>>() }
1330    }
1331
1332    /// This buffer as one that is statically the only reference to its storage, given
1333    /// back if its storage is shared, which the empty storage never is.
1334    #[inline]
1335    pub fn try_into_mut(self) -> Result<BufMut<T, DIM>, Self> {
1336        if self.is_writable() {
1337            Ok(BufMut(self))
1338        } else {
1339            Err(self)
1340        }
1341    }
1342
1343    /// This buffer as one that is statically the only reference to its storage, which
1344    /// copies its values into a storage of their own if its storage is shared, see
1345    /// [`Self::make_mut`].
1346    #[inline]
1347    pub fn into_mut(mut self) -> BufMut<T, DIM> {
1348        self.make_mut();
1349        BufMut(self)
1350    }
1351
1352    /// The part of this buffer that these values are, sharing its storage, see
1353    /// [`Self::slice`]: what values taken out of [`Self::as_slice`] turn back into, such as
1354    /// the octets a decoder that only handles slices has read.
1355    ///
1356    /// # Panics
1357    ///
1358    /// If the values are not within this buffer, or are not a range of its last dimension:
1359    /// any range of values for one dimension, but only whole rows for two.
1360    #[track_caller]
1361    pub fn slice_ref(&self, subset: &[T]) -> Self {
1362
1363        const { assert!(DIM >= 1, "a scalar cannot be sliced") };
1364        
1365        let size = mem::size_of::<T>();
1366        let offset = subset.as_ptr().addr().wrapping_sub(self.base().addr());
1367        let (start, len) = (offset / size, self.len());
1368        
1369        assert!(offset % size == 0 && start <= len && subset.len() <= len - start,
1370            "the values at {:p} are not within the buffer at {:p}, of {len} values", 
1371            subset.as_ptr(), 
1372            self.base());
1373
1374        let stride: usize = self.dim[..DIM - 1].iter().product();
1375        if stride == 0 {
1376            return self.slice(..0);
1377        }
1378
1379        assert!(start % stride == 0 && subset.len() % stride == 0,
1380            "the values {start}..{} are not whole rows of {stride} values", 
1381            start + subset.len());
1382        
1383        self.slice(start / stride..(start + subset.len()) / stride)
1384
1385    }
1386
1387}
1388
1389impl<T: PackedElement> From<T> for Buf<T, 0> {
1390    /// A scalar of that value, held in place.
1391    #[inline]
1392    fn from(value: T) -> Self {
1393        Self::from_slice(slice::from_ref(&value), []).expect("a scalar holds one value")
1394    }
1395}
1396
1397impl<T: PackedElement> From<&[T]> for Buf<T, 1> {
1398    #[inline]
1399    fn from(values: &[T]) -> Self {
1400        Self::from_slice(values, [values.len()]).expect("same length")
1401    }
1402}
1403
1404impl<T: PackedElement> From<Vec<T>> for Buf<T, 1> {
1405    #[inline]
1406    fn from(values: Vec<T>) -> Self {
1407        Self::from(values.as_slice())
1408    }
1409}
1410
1411impl<T: PackedElement> From<Box<[T]>> for Buf<T, 1> {
1412    #[inline]
1413    fn from(values: Box<[T]>) -> Self {
1414        Self::from(&*values)
1415    }
1416}
1417
1418impl<T: PackedElement, const N: usize> From<[T; N]> for Buf<T, 1> {
1419    #[inline]
1420    fn from(values: [T; N]) -> Self {
1421        Self::from(values.as_slice())
1422    }
1423}
1424
1425impl<T: PackedElement, const DIM: usize> From<BufMut<T, DIM>> for Buf<T, DIM> {
1426    #[inline]
1427    fn from(buf: BufMut<T, DIM>) -> Self {
1428        buf.freeze()
1429    }
1430}
1431
1432// --- Table --- //
1433
1434impl<T: Element<Spans = TableSpans> + ?Sized, const DIM: usize> Buf<T, DIM> {
1435
1436    /// The values at these spans of these octets, with those dimensions, sharing their
1437    /// storage, each span being accepted by that check. The octets are given back if the
1438    /// spans are not as many as the dimensions say, if one of them is not accepted, or if
1439    /// their table cannot be allocated, as many spans as the dimensions say being allocated
1440    /// before any is checked, and the dimensions possibly coming off the wire.
1441    fn with_spans<I, F>(bytes: Buf<u8, 1>, spans: I, dim: [usize; DIM], mut check: F) -> Result<Self, Buf<u8, 1>>
1442    where
1443        I: IntoIterator<Item = Range<u32>>,
1444        F: FnMut(&[u8], &Range<u32>) -> bool,
1445    {
1446
1447        let Some(len) = checked_len(&dim) else { 
1448            return Err(bytes);
1449        };
1450
1451        let mut spans = spans.into_iter();
1452
1453        if len == 0 {
1454            if spans.next().is_some() {
1455                return Err(bytes);
1456            }
1457            // SAFETY: The storage holds no values, as many as the dimensions say.
1458            return Ok(unsafe { Self::from_raw(bytes.into_raw(), TableSpans::EMPTY, dim) });
1459        }
1460        
1461        let Some(size) = len.checked_mul(mem::size_of::<Range<u32>>()) else { 
1462            return Err(bytes);
1463        };
1464
1465        let Ok(side) = DetachedSide::new(size) else { 
1466            return Err(bytes);
1467        };
1468
1469        let table = side.payload().cast::<Range<u32>>();
1470        for index in 0..len {
1471            let Some(span) = spans.next().filter(|span| check(bytes.as_slice(), span)) else { 
1472                return Err(bytes);
1473            };
1474            // SAFETY: The table holds that many spans, and is aligned for them.
1475            unsafe { table.add(index).write(span) };
1476        }
1477
1478        if spans.next().is_some() {
1479            return Err(bytes);
1480        }
1481
1482        let mut raw = bytes.into_raw();
1483        // Nothing is attached to the empty storage: empty values within it are given a
1484        // storage of their own, which they need no octets of.
1485        if raw.inner.is_immortal() {
1486            raw = HeapRef { inner: infallible(Heap::alloc(0)), offset: 0 };
1487        }
1488        raw.inner.push_side(side);
1489
1490        // SAFETY: The spans were all accepted, as many as the dimensions say.
1491        Ok(unsafe { Self::from_raw(raw, TableSpans(table), dim) })
1492        
1493    }
1494
1495}
1496
1497impl<const DIM: usize> Buf<str, DIM> {
1498
1499    /// The strings at these spans of these octets, relative to them, with those
1500    /// dimensions, sharing their storage. The octets are given back if the spans are not as
1501    /// many as the dimensions say, are out of the octets, or are not valid UTF-8.
1502    ///
1503    /// This is how a backend decodes strings out of the message it received, the spans
1504    /// being typically given as it reads them.
1505    pub fn from_spans<I>(bytes: Buf<u8, 1>, spans: I, dim: [usize; DIM]) -> Result<Self, Buf<u8, 1>>
1506    where
1507        I: IntoIterator<Item = Range<u32>>,
1508    {
1509        Self::with_spans(bytes, spans, dim, |bytes, span| {
1510            bytes.get(span.start as usize..span.end as usize).is_some_and(str::validate)
1511        })
1512    }
1513
1514    /// The unchecked form of [`Self::from_spans`], for a backend that already validated
1515    /// the strings: only their number is checked.
1516    ///
1517    /// # Safety
1518    ///
1519    /// The spans must be within the octets, and valid UTF-8 there.
1520    ///
1521    /// # Panics
1522    ///
1523    /// If the spans are not as many as the dimensions say, or if their table cannot be
1524    /// allocated.
1525    #[inline]
1526    #[track_caller]
1527    pub unsafe fn from_spans_unchecked<I>(bytes: Buf<u8, 1>, spans: I, dim: [usize; DIM]) -> Self
1528    where
1529        I: IntoIterator<Item = Range<u32>>,
1530    {
1531        Self::with_spans(bytes, spans, dim, |_, _| true)
1532            .unwrap_or_else(|_| panic!("no table of as many spans as the dimensions {dim:?} say"))
1533    }
1534
1535}
1536
1537impl Buf<str, 1> {
1538
1539    /// A buffer of copies of these strings, as many as there are. Absent if they do not fit
1540    /// spans of 32 bits.
1541    pub fn from_strs<I>(values: I) -> Option<Self>
1542    where
1543        I: IntoIterator,
1544        I::Item: AsRef<str>,
1545    {
1546
1547        let mut buf = BufMut::<u8, 1>::new();
1548        let mut spans = Vec::new();
1549
1550        // The size hint only tells how many spans to make room for: the strings are copied
1551        // as they come, whatever it said.
1552        let values = values.into_iter();
1553        spans.reserve(values.size_hint().0);
1554
1555        for value in values {
1556            let start = u32::try_from(buf.len()).ok()?;
1557            buf.extend_from_slice(value.as_ref().as_bytes());
1558            spans.push(start..u32::try_from(buf.len()).ok()?);
1559        }
1560
1561        let len = spans.len();
1562        if len == 0 {
1563            // SAFETY: The empty storage holds no values, as many as the dimensions say.
1564            return Some(unsafe { Self::from_raw(HeapRef::EMPTY, TableSpans::EMPTY, [0]) });
1565        }
1566
1567        // SAFETY: The spans are those of the strings just written, as many as the
1568        // dimensions say.
1569        Some(unsafe { Self::from_spans_unchecked(buf.freeze(), spans, [len]) })
1570
1571    }
1572
1573}
1574
1575impl From<&str> for Buf<str, 0> {
1576    /// A scalar of a copy of that string.
1577    #[inline]
1578    fn from(value: &str) -> Self {
1579        Buf::<str, 1>::from_strs([value])
1580            .and_then(Buf::into_scalar)
1581            .expect("a string of more than 4 GiB")
1582    }
1583}
1584
1585impl<S: AsRef<str>> From<&[S]> for Buf<str, 1> {
1586    #[inline]
1587    fn from(values: &[S]) -> Self {
1588        Self::from_strs(values).expect("strings of more than 4 GiB")
1589    }
1590}
1591
1592
1593// =========================== //
1594//       Writable buffers      //
1595// =========================== //
1596
1597/// A buffer of packed values that is statically the only reference to its storage, like a
1598/// `Vec`: it is written without ever checking whether its storage is shared, it grows
1599/// along one dimension, and it turns into a [`Buf`] to be shared, see [`Self::freeze`]. A [`Buf`] turns
1600/// into one with copy-on-write, see [`Buf::make_mut`] and [`Buf::into_mut`].
1601///
1602/// It cannot be sliced, which would share its storage, and cloning it copies its values
1603/// into a storage of their own, like a `Vec`. An empty one may have no storage of its own,
1604/// see [`Self::new`], until it first grows.
1605#[repr(transparent)]
1606pub struct BufMut<T: PackedElement, const DIM: usize>(Buf<T, DIM>);
1607
1608impl<T: PackedElement, const DIM: usize> BufMut<T, DIM> {
1609
1610    /// A buffer of zeroes with those dimensions, held in place for a scalar.
1611    ///
1612    /// # Panics
1613    ///
1614    /// If the dimensions are too large for a storage.
1615    pub fn zeroed(dim: [usize; DIM]) -> Self {
1616
1617        let size = checked_len(&dim)
1618            .and_then(|len| len.checked_mul(mem::size_of::<T>()))
1619            .expect("capacity overflow");
1620
1621        if Buf::<T, DIM>::INLINE || size == 0 {
1622            // SAFETY: Zeroes are valid values of a packed type, as many as the dimensions say.
1623            return Self(unsafe { Buf::copy_from_bytes(&[0; mem::size_of::<Repr>()][..size], dim) });
1624        }
1625
1626        let raw = HeapRef { inner: infallible(Heap::alloc(size)), offset: 0 };
1627
1628        // SAFETY: A new storage is aligned for any packed type, and holds zeroes.
1629        Self(unsafe { Buf::from_raw(raw, PackedSpans::new(), dim) })
1630        
1631    }
1632
1633    /// A buffer of these values, see [`Buf::from_slice`].
1634    #[inline]
1635    pub fn from_slice(values: &[T], dim: [usize; DIM]) -> Option<Self> {
1636        Buf::from_slice(values, dim).map(Self)
1637    }
1638
1639    /// The dimensions of this buffer, see [`Buf::dim`].
1640    #[inline]
1641    pub fn dim(&self) -> [usize; DIM] {
1642        self.0.dim
1643    }
1644
1645    /// The number of values of this buffer, 1 for a scalar.
1646    #[inline]
1647    pub fn len(&self) -> usize {
1648        self.0.len()
1649    }
1650
1651    #[inline]
1652    pub fn is_empty(&self) -> bool {
1653        self.0.is_empty()
1654    }
1655
1656    /// Where the values of this buffer start.
1657    #[inline]
1658    pub fn as_ptr(&self) -> *const T {
1659        self.0.as_ptr()
1660    }
1661
1662    #[inline]
1663    pub fn as_slice(&self) -> &[T] {
1664        self.0.as_slice()
1665    }
1666
1667    #[inline]
1668    pub fn as_mut_slice(&mut self) -> &mut [T] {
1669        let len = self.len();
1670        // SAFETY: The buffer holds that many aligned values, in a storage it alone references.
1671        unsafe { slice::from_raw_parts_mut(self.0.base_mut().cast::<T>(), len) }
1672    }
1673
1674    #[inline]
1675    pub fn as_bytes(&self) -> &[u8] {
1676        self.0.as_bytes()
1677    }
1678
1679    /// Share this buffer, which cannot be written anymore unless it is the only reference
1680    /// to its storage again, see [`Buf::try_into_mut`].
1681    #[inline]
1682    pub fn freeze(self) -> Buf<T, DIM> {
1683        self.0
1684    }
1685
1686}
1687
1688impl<T: PackedElement> BufMut<T, 1> {
1689
1690    /// An empty buffer, which allocates nothing until it grows, see [`Buf::new`].
1691    #[inline]
1692    pub const fn new() -> Self {
1693        Self(Buf::new())
1694    }
1695
1696    /// An empty buffer that can grow to at least that many values without reallocating.
1697    #[inline]
1698    pub fn with_capacity(capacity: usize) -> Self {
1699        let mut buf = Self::new();
1700        buf.reserve(capacity);
1701        buf
1702    }
1703
1704    /// How many values this buffer can hold without reallocating.
1705    #[inline]
1706    pub fn capacity(&self) -> usize {
1707        let raw = self.0.raw();
1708        (raw.inner.capacity() - raw.offset) / mem::size_of::<T>()
1709    }
1710
1711    /// Where the value at that index is, which may be past the length but not past the
1712    /// capacity.
1713    #[inline]
1714    fn ptr_at(&self, index: usize) -> *mut T {
1715        debug_assert!(index <= self.capacity());
1716        // SAFETY: The index is within the capacity.
1717        unsafe { self.0.raw().ptr().cast::<T>().add(index) }
1718    }
1719
1720    /// Make room for at least that many more values, growing the storage if it lacks room.
1721    #[inline]
1722    pub fn reserve(&mut self, additional: usize) {
1723        infallible(self.alloc_reserve(additional))
1724    }
1725
1726    /// [`Self::reserve`], failing rather than aborting when the allocation does, which
1727    /// leaves the buffer as it was: for a length that comes off the wire.
1728    pub fn try_reserve(&mut self, additional: usize) -> Result<(), Error> {
1729        self.alloc_reserve(additional).map_err(|_| Error::new(ErrorKind::Internal)
1730            .with_description(format!("Could not allocate room for {additional} more values behind {}", self.len())))
1731    }
1732
1733    fn alloc_reserve(&mut self, additional: usize) -> AllocResult<()> {
1734        let len = self.len();
1735        let raw = self.0.raw_mut();
1736        let end = len.checked_add(additional)
1737            .and_then(|len| len.checked_mul(mem::size_of::<T>()))
1738            .and_then(|size| raw.offset.checked_add(size))
1739            .ok_or(None)?;
1740        if end <= raw.inner.capacity() {
1741            return Ok(());
1742        }
1743        if raw.inner.is_immortal() {
1744            // The empty storage is never written, a buffer grows out of it into a storage
1745            // of its own, which it starts at, its offset in the empty storage being zero.
1746            raw.inner = Heap::alloc(end)?;
1747        } else {
1748            // SAFETY: The buffer is the only reference to its storage.
1749            unsafe { raw.inner.grow(end)? };
1750        }
1751        Ok(())
1752    }
1753
1754    /// Append that value.
1755    #[inline]
1756    pub fn push(&mut self, value: T) {
1757        self.reserve(1);
1758        // SAFETY: There is room for it, in a storage this buffer alone references.
1759        unsafe { self.ptr_at(self.len()).write(value) };
1760        self.0.dim[0] += 1;
1761    }
1762
1763    /// Append these values.
1764    pub fn extend_from_slice(&mut self, values: &[T]) {
1765        self.reserve(values.len());
1766        // SAFETY: There is room for them, in a storage this buffer alone references.
1767        unsafe { ptr::copy_nonoverlapping(values.as_ptr(), self.ptr_at(self.len()), values.len()) };
1768        self.0.dim[0] += values.len();
1769    }
1770
1771    /// Grow or shrink to that many values, the added ones being that value.
1772    ///
1773    /// Zeroes are only written up to the capacity this buffer had before growing: what a
1774    /// storage grows by is already zeroed.
1775    pub fn resize(&mut self, len: usize, value: T) {
1776        let old_len = self.len();
1777        if len > old_len {
1778            // SAFETY: A packed type has no padding, so its value is all initialized octets.
1779            let bytes = unsafe { slice::from_raw_parts(ptr::from_ref(&value).cast::<u8>(), mem::size_of::<T>()) };
1780            let end = if bytes.iter().all(|&octet| octet == 0) {
1781                // Values that are partly within the old capacity are written.
1782                let raw = self.0.raw();
1783                len.min((raw.inner.capacity() - raw.offset).div_ceil(mem::size_of::<T>()))
1784            } else {
1785                len
1786            };
1787            self.reserve(len - old_len);
1788            for index in old_len..end {
1789                // SAFETY: There is room for it, in a storage this buffer alone references.
1790                unsafe { self.ptr_at(index).write(value) };
1791            }
1792        }
1793        self.0.dim[0] = len;
1794    }
1795
1796    /// Keep only the first values, no more than that many.
1797    #[inline]
1798    pub fn truncate(&mut self, len: usize) {
1799        self.0.truncate(len);
1800    }
1801
1802    /// Empty this buffer, keeping its storage, and so its capacity, and freeing what the
1803    /// buffers cast from it had attached to it.
1804    pub fn clear(&mut self) {
1805        let raw = self.0.raw_mut();
1806        if !raw.inner.is_immortal() {
1807            // SAFETY: The buffer is the only reference to its storage.
1808            unsafe { raw.inner.free_sides() };
1809        }
1810        raw.offset = 0;
1811        self.0.dim[0] = 0;
1812    }
1813
1814}
1815
1816impl BufMut<u8, 1> {
1817
1818    /// Parse plain hexadecimal octets, in either case, which is what [`UpperHex`] and
1819    /// [`LowerHex`] give, absent if they are not.
1820    pub fn from_hex(s: &str) -> Option<Self> {
1821        if s.len() % 2 != 0 {
1822            return None;
1823        }
1824        let mut buf = Self::with_capacity(s.len() / 2);
1825        for hex in s.as_bytes().chunks_exact(2) {
1826            let hex = str::from_utf8(hex).ok()?;
1827            buf.push(u8::from_str_radix(hex, 16).ok()?);
1828        }
1829        Some(buf)
1830    }
1831
1832    /// Grow or shrink to that many octets, the added ones being left as they are, which
1833    /// saves zeroing octets that are about to be written: they are zeroes, unless this
1834    /// buffer held something there before it was shrunk or cleared.
1835    ///
1836    /// This is only for octets, every one of which is valid, unlike what was left there
1837    /// for other types.
1838    pub fn set_len(&mut self, len: usize) {
1839        self.reserve(len.saturating_sub(self.len()));
1840        self.0.dim[0] = len;
1841    }
1842
1843}
1844
1845// --- Standard traits impl --- //
1846
1847impl<T: PackedElement, const DIM: usize> Clone for BufMut<T, DIM> {
1848    /// A copy of the values of this buffer, in a storage of their own, the capacity past
1849    /// them not being kept.
1850    #[inline]
1851    fn clone(&self) -> Self {
1852        // SAFETY: The octets are those of the values of this buffer.
1853        Self(unsafe { Buf::copy_from_bytes(self.as_bytes(), self.dim()) })
1854    }
1855}
1856
1857impl<T: PackedElement> Default for BufMut<T, 1> {
1858    #[inline]
1859    fn default() -> Self {
1860        Self::new()
1861    }
1862}
1863
1864impl<T: PackedElement + PartialEq, const DIM: usize> PartialEq for BufMut<T, DIM> {
1865    #[inline]
1866    fn eq(&self, other: &Self) -> bool {
1867        self.dim() == other.dim() && self.as_slice() == other.as_slice()
1868    }
1869}
1870
1871impl<T: PackedElement + Eq, const DIM: usize> Eq for BufMut<T, DIM> {}
1872
1873impl<T: PackedElement> From<&[T]> for BufMut<T, 1> {
1874    #[inline]
1875    fn from(values: &[T]) -> Self {
1876        Self(Buf::from(values))
1877    }
1878}
1879
1880impl<T: PackedElement> From<Vec<T>> for BufMut<T, 1> {
1881    #[inline]
1882    fn from(values: Vec<T>) -> Self {
1883        Self::from(values.as_slice())
1884    }
1885}
1886
1887// --- Formatters --- //
1888
1889impl<T: PackedElement, const DIM: usize> Debug for BufMut<T, DIM> {
1890    /// Its dimensions and values, row by row, see [`Element::fmt_row`].
1891    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1892        fmt_buf::<T, _>(f, "BufMut", &self.0.dim, self.0.iter())
1893    }
1894}
1895
1896impl<T: PackedElement> UpperHex for BufMut<T, 1> {
1897    /// The octets of the values as hexadecimal, in the order they are stored, each value's
1898    /// grouped and separated by a space, octets being a single run that
1899    /// [`BufMut::from_hex`] parses back.
1900    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1901        fmt_hex::<T>(self.as_bytes(), f, true)
1902    }
1903}
1904
1905impl<T: PackedElement> LowerHex for BufMut<T, 1> {
1906    /// The octets of the values as hexadecimal, in the order they are stored, each value's
1907    /// grouped and separated by a space, octets being a single run that
1908    /// [`BufMut::from_hex`] parses back.
1909    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1910        fmt_hex::<T>(self.as_bytes(), f, false)
1911    }
1912}
1913
1914#[cfg(test)]
1915#[allow(clippy::single_range_in_vec_init)]
1916mod tests {
1917
1918    use super::*;
1919
1920    /// A scalar of a packed type is held in place: it has no storage to share, so it is
1921    /// always unique, and its only value is at the empty position.
1922    #[test]
1923    fn scalar() {
1924        let scalar = Buf::<f64, 0>::from(1.5);
1925        assert_eq!(scalar.value(), 1.5);
1926        assert_eq!(scalar.get([]), Some(1.5));
1927        assert_eq!(scalar.len(), 1);
1928        let clone = scalar.clone();
1929        assert!(scalar.is_unique() && clone.is_unique());
1930    }
1931
1932    #[test]
1933    fn one_dim() {
1934        let buf = Buf::<i32, 1>::from(vec![1, 2, 3]);
1935        assert_eq!(buf.dim(), [3]);
1936        assert_eq!(buf.get([1]), Some(2));
1937        assert_eq!(buf.get([3]), None);
1938        assert_eq!(buf.as_slice(), &[1, 2, 3]);
1939        assert_eq!(buf.iter().sum::<i32>(), 6);
1940    }
1941
1942    /// Two dimensions are in column-major order: `[x, y]`, with `x` varying the fastest, so
1943    /// a 3×2 buffer is its two rows one after the other.
1944    #[test]
1945    fn two_dim() {
1946        let buf = Buf::<u8, 2>::from_slice(&[1, 2, 3, 4, 5, 6], [3, 2]).unwrap();
1947        assert_eq!(buf.get([0, 1]), Some(4));
1948        assert_eq!(buf.get([2, 1]), Some(6));
1949        assert_eq!(buf.get([3, 0]), None);
1950        assert_eq!(buf.raw_index([1, 1]), Some(4));
1951        assert_eq!(buf.get_raw(4), Some(5));
1952        // The dimensions have to account for every value.
1953        assert!(Buf::<u8, 2>::from_slice(&[1, 2, 3], [2, 2]).is_none());
1954        // And can be changed afterwards, as long as they still do.
1955        let flat = buf.reshape([6]).unwrap();
1956        assert_eq!(flat.as_slice(), &[1, 2, 3, 4, 5, 6]);
1957    }
1958
1959    /// Empty buffers allocate nothing, all sharing the same static storage, which is never
1960    /// written: growing one first gives it a storage of its own.
1961    #[test]
1962    fn empty() {
1963        const EMPTY: Buf<u32, 2> = Buf::new();
1964        const EMPTY_MUT: BufMut<u8, 1> = BufMut::new();
1965        assert_eq!(EMPTY.dim(), [0, 0]);
1966        assert!(!EMPTY.is_unique());
1967        let mut values = Buf::<u32, 1>::from(vec![]);
1968        assert_eq!(values.as_ptr().cast::<u8>(), EMPTY_MUT.as_ptr());
1969        assert_eq!(values.make_mut().as_mut_slice(), &mut []);
1970        assert!(Buf::<str, 1>::from(&[] as &[&str]).iter().next().is_none());
1971        // Empty strings within an empty buffer have their spans attached elsewhere.
1972        let strings = Buf::<str, 1>::from_spans(values.into_bytes(), [0..0, 0..0], [2]).unwrap();
1973        assert_eq!(strings.iter().collect::<Vec<_>>(), ["", ""]);
1974        let mut buf = EMPTY_MUT;
1975        assert_eq!(buf.capacity(), 0);
1976        buf.clear();
1977        buf.extend_from_slice(&[]);
1978        assert_eq!(buf.as_ptr(), EMPTY_MUT.as_ptr());
1979        buf.extend_from_slice(&[1, 2]);
1980        assert_ne!(buf.as_ptr(), EMPTY_MUT.as_ptr());
1981        let mut shared = EMPTY.reshape::<1>([0]).unwrap();
1982        shared.get_mut().unwrap().resize(3, 7);
1983        assert_eq!(shared.as_slice(), [7; 3]);
1984    }
1985
1986    /// Cloning a writable buffer copies its values, both copies staying unique.
1987    #[test]
1988    fn writable_clone() {
1989        let mut buf = BufMut::from(&[1u16, 2][..]);
1990        let mut copy = buf.clone();
1991        assert_ne!(copy.as_ptr(), buf.as_ptr());
1992        copy.as_mut_slice()[0] = 0;
1993        buf.push(3);
1994        assert_eq!((buf.as_slice(), copy.as_slice()), (&[1, 2, 3][..], &[0, 2][..]));
1995        assert!(buf.freeze().is_unique() && copy.freeze().is_unique());
1996    }
1997
1998    /// Values taken out of a buffer turn back into the part of it they are, as long as they
1999    /// are a range of its last dimension.
2000    #[test]
2001    fn slicing_by_ref() {
2002        let values = Buf::<u16, 1>::from(vec![1, 2, 3, 4]);
2003        let part = values.slice_ref(&values.as_slice()[1..3]);
2004        assert_eq!(part.as_slice(), &[2, 3]);
2005        assert_eq!(part.as_ptr(), values.as_slice()[1..].as_ptr());
2006        let rows = values.reshape([2, 2]).unwrap();
2007        assert_eq!(rows.slice_ref(&rows.as_slice()[2..]).dim(), [2, 1]);
2008        let res = std::panic::catch_unwind(|| rows.slice_ref(&rows.as_slice()[1..3]));
2009        assert!(res.is_err());
2010        let other = [3, 4];
2011        let res = std::panic::catch_unwind(|| rows.slice_ref(&other));
2012        assert!(res.is_err());
2013    }
2014
2015    /// A decoder's slice of octets turns back into the part of the buffer it is.
2016    #[test]
2017    fn octets_by_ref() {
2018        let buf = Buf::from(&b"hello world"[..]);
2019        let part = buf.slice_ref(&buf.as_slice()[6..]);
2020        assert_eq!(part.as_slice(), b"world");
2021        assert!(buf.slice_ref(&buf.as_slice()[11..]).is_empty());
2022    }
2023
2024    /// Slicing cuts along the last dimension, values for one dimension or rows for two,
2025    /// and shares the storage rather than copying.
2026    #[test]
2027    fn slicing() {
2028        let buf = Buf::<u8, 2>::from_slice(&[1, 2, 3, 4, 5, 6], [2, 3]).unwrap();
2029        let rows = buf.slice(1..);
2030        assert_eq!(rows.dim(), [2, 2]);
2031        assert_eq!(rows.as_slice(), &[3, 4, 5, 6]);
2032        assert!(!buf.is_unique());
2033        assert_eq!(rows.slice(..1).as_slice(), &[3, 4]);
2034    }
2035
2036    /// A scalar is one value: it is reshaped to and from anything of one value, a packed one
2037    /// moving in and out of place.
2038    #[test]
2039    fn scalar_shapes() {
2040        let scalar = Buf::<u16, 0>::from(7);
2041        let square = scalar.clone().reshape([1, 1]).unwrap();
2042        assert_eq!(square.as_slice(), &[7]);
2043        assert!(scalar.clone().reshape([2]).is_none());
2044        assert_eq!(square.into_scalar().unwrap(), scalar);
2045        assert_eq!(scalar.clone().into_scalar().unwrap(), scalar);
2046        let string = Buf::<str, 0>::from("ab");
2047        let strings = string.clone().reshape([1]).unwrap();
2048        assert!(!string.is_unique());
2049        assert_eq!(strings.into_scalar().unwrap().value(), "ab");
2050    }
2051
2052    /// Splitting shares the storage, each side keeping its part.
2053    #[test]
2054    fn splitting() {
2055        let mut buf = Buf::from(&b"headtail"[..]);
2056        let head = buf.split_to(4);
2057        assert_eq!((head.as_slice(), buf.as_slice()), (&b"head"[..], &b"tail"[..]));
2058        let tail = buf.split_off(2);
2059        assert_eq!((buf.as_slice(), tail.as_slice()), (&b"ta"[..], &b"il"[..]));
2060        assert!(!head.is_unique());
2061        let mut rows = Buf::<u8, 2>::from_slice(&[1, 2, 3, 4, 5, 6], [2, 3]).unwrap();
2062        assert_eq!(rows.split_to(1).as_slice(), &[1, 2]);
2063        assert_eq!(rows.dim(), [2, 2]);
2064    }
2065
2066    #[test]
2067    #[should_panic(expected = "out of range")]
2068    fn slice_out_of_range() {
2069        Buf::<u8, 1>::from(vec![1, 2]).slice(1..3);
2070    }
2071
2072    /// A scalar held in place is written in place.
2073    #[test]
2074    fn scalar_mutation() {
2075        let mut scalar = Buf::<i32, 0>::from(1);
2076        scalar.make_mut().as_mut_slice()[0] = 2;
2077        assert_eq!(scalar.value(), 2);
2078        assert_eq!(BufMut::<i32, 0>::zeroed([]).freeze().value(), 0);
2079    }
2080
2081    /// A single value is taken out as a scalar: in place for a packed one, sharing the
2082    /// storage for a string.
2083    #[test]
2084    fn scalar_extraction() {
2085        let values = Buf::<f64, 1>::from(vec![1.5, 2.5]);
2086        assert_eq!(values.slice(1..).into_scalar().unwrap().value(), 2.5);
2087        assert!(values.is_unique());
2088        assert!(values.clone().into_scalar().is_none());
2089        let strings = Buf::<str, 1>::from(&["ab", "cd"][..]);
2090        let scalar = strings.slice(1..).into_scalar().unwrap();
2091        assert_eq!(scalar.value(), "cd");
2092        assert!(!strings.is_unique());
2093        assert_eq!(strings.get_scalar([0]).unwrap().value(), "ab");
2094        assert!(strings.get_scalar([2]).is_none());
2095        let image = Buf::<u8, 2>::from_slice(&[1, 2, 3, 4, 5, 6], [2, 3]).unwrap();
2096        assert_eq!(image.get_scalar([1, 2]).unwrap().value(), 6);
2097        assert_eq!(Buf::<u16, 0>::from(7).get_scalar([]).unwrap().value(), 7);
2098    }
2099
2100    /// Writing to a shared buffer first copies it, only its own values and not the whole
2101    /// storage, so that what shares the storage is never affected.
2102    #[test]
2103    fn copy_on_write() {
2104        let mut values = Buf::<u16, 1>::from(vec![1, 2, 3, 4]);
2105        let part = values.slice(1..3);
2106        values.make_mut().as_mut_slice()[1] = 9;
2107        assert_eq!(values.as_slice(), &[1, 9, 3, 4]);
2108        assert_eq!(part.as_slice(), &[2, 3]);
2109        assert!(values.is_unique());
2110        // A unique buffer is written in place.
2111        let ptr = values.as_ptr();
2112        values.make_mut().as_mut_slice()[0] = 0;
2113        assert_eq!(values.as_ptr(), ptr);
2114        // And a shared one turned into a writable one only takes its own values.
2115        let rest = Buf::from(vec![0u16; 64]).slice(1..);
2116        let part = rest.slice(..2).into_mut();
2117        assert_ne!(part.as_ptr(), rest.as_ptr());
2118        assert!(part.capacity() < rest.len());
2119    }
2120
2121    /// A shared buffer grows through copy-on-write, what was sharing its storage keeping
2122    /// the octets it had.
2123    #[test]
2124    fn copy_on_write_growth() {
2125        let mut buf = Buf::from(&b"head"[..]);
2126        let head = buf.clone();
2127        buf.make_mut().extend_from_slice(b" tail");
2128        assert_eq!((buf.as_slice(), head.as_slice()), (&b"head tail"[..], &b"head"[..]));
2129    }
2130
2131    /// A buffer of one dimension grows like a `Vec`, whatever its type.
2132    #[test]
2133    fn growth() {
2134        let mut buf = BufMut::<u32, 1>::with_capacity(4);
2135        buf.extend_from_slice(&[1, 2]);
2136        buf.resize(5, 0);
2137        buf.extend_from_slice(&[7; 100]);
2138        buf.push(8);
2139        assert_eq!(buf.len(), 106);
2140        assert_eq!(buf.as_slice()[..6], [1, 2, 0, 0, 0, 7]);
2141        assert_eq!(buf.as_slice()[105], 8);
2142        buf.truncate(2);
2143        assert_eq!(buf.as_slice(), &[1, 2]);
2144    }
2145
2146    /// Setting the length of octets grows without zeroing: what the buffer held there
2147    /// before it shrank is still there, and octets it never held are zeroes.
2148    #[test]
2149    fn length() {
2150        let mut buf = BufMut::from(&[0xAA; 8][..]);
2151        buf.truncate(4);
2152        buf.set_len(12);
2153        assert_eq!(buf.as_slice(), [&[0xAA; 8][..], &[0; 4]].concat());
2154        buf.truncate(4);
2155        buf.resize(8, 0);
2156        assert_eq!(buf.as_slice(), [0xAA, 0xAA, 0xAA, 0xAA, 0, 0, 0, 0]);
2157    }
2158
2159    /// Resizing with zeroes zeroes what the buffer held within its capacity, and relies on
2160    /// what it grows by being zeroed already.
2161    #[test]
2162    fn zero_resize() {
2163        let mut buf = BufMut::from(&[0xAAAAu16; 4][..]);
2164        buf.clear();
2165        buf.resize(100, 0);
2166        assert_eq!(buf.as_slice(), [0; 100]);
2167        buf.clear();
2168        buf.resize(2, 0xBBBB);
2169        buf.resize(3, 0);
2170        assert_eq!(buf.as_slice(), [0xBBBB, 0xBBBB, 0]);
2171    }
2172
2173    /// A reservation that cannot be allocated fails and leaves the buffer as it was.
2174    #[test]
2175    fn reservation() {
2176        let mut buf = BufMut::from(&[1u16, 2][..]);
2177        assert!(buf.try_reserve(usize::MAX).is_err());
2178        assert!(buf.try_reserve(isize::MAX as usize).is_err());
2179        assert_eq!(buf.as_slice(), [1, 2]);
2180        buf.reserve(64);
2181        assert!(buf.capacity() >= 66);
2182    }
2183
2184    /// Clearing a buffer keeps its storage for the next message, and so does freezing it
2185    /// once what was shared out of it is gone.
2186    #[test]
2187    fn recycling() {
2188        let mut buf = BufMut::from(&b"first"[..]);
2189        let ptr = buf.as_ptr();
2190        buf.clear();
2191        buf.extend_from_slice(b"second");
2192        assert_eq!(buf.as_ptr(), ptr);
2193
2194        let buf = buf.freeze();
2195        let first = Buf::<str, 0>::from_spans(buf.slice(..3), [0..3], []).unwrap();
2196        let buf = buf.try_into_mut().unwrap_err();
2197        drop(first);
2198        let mut buf = buf.try_into_mut().unwrap();
2199        buf.clear();
2200        assert_eq!(buf.as_ptr(), ptr);
2201    }
2202
2203    /// A shared buffer only turns back into a writable one, without copying, once nothing
2204    /// else references its storage.
2205    #[test]
2206    fn unique_buffer() {
2207        let buf = Buf::from(&[1u8, 2, 3][..]);
2208        let ptr = buf.as_ptr();
2209        let part = buf.slice(1..);
2210        let mut buf = buf.try_into_mut().unwrap_err();
2211        assert!(buf.get_mut().is_none());
2212        drop(part);
2213        buf.get_mut().unwrap().truncate(1);
2214        let buf = buf.try_into_mut().unwrap();
2215        assert_eq!(buf.as_ptr(), ptr);
2216        assert_eq!(buf.as_slice(), [1]);
2217    }
2218
2219    /// Casting octets to packed values shares the storage when they are aligned for the
2220    /// type, and copies them otherwise, which is always correct and only slower.
2221    #[test]
2222    fn packed_cast() {
2223        let buf = Buf::<u32, 1>::from(vec![1, 2, 3, 4]).into_bytes();
2224        let aligned = buf.slice(8..).cast::<u32, 1>([2]).unwrap();
2225        assert_eq!(aligned.as_slice(), &[3, 4]);
2226        assert!(!aligned.is_unique());
2227        let unaligned = buf.slice(1..9).cast::<u32, 1>([2]).unwrap();
2228        assert!(unaligned.is_unique());
2229        // The octets must be exactly those of the dimensions, the buffer being given back
2230        // if they are not.
2231        let buf = buf.cast::<u32, 1>([3]).unwrap_err();
2232        // A scalar is always copied in place.
2233        assert!(buf.slice(..2).cast::<u16, 0>([]).unwrap().is_unique());
2234        // And any packed type casts to any other.
2235        let halves = aligned.cast::<u16, 2>([2, 2]).unwrap();
2236        assert_eq!(halves.cast::<u64, 0>([]).unwrap().value(), 3 | 4 << 32);
2237    }
2238
2239    /// A buffer starting where its storage starts is currently aligned for every packed
2240    /// type, which is not part of the API.
2241    #[test]
2242    fn storage_alignment() {
2243        let buf = Buf::from(&[0u8; 16][..]);
2244        assert_eq!(buf.as_ptr().addr() % ALIGN, 0);
2245        assert!(!buf.clone().cast::<f64, 1>([2]).unwrap().is_unique());
2246    }
2247
2248    /// Not every octet pattern is a value: a boolean is only 0 or 1.
2249    #[test]
2250    fn invalid_values() {
2251        let buf = Buf::from(&[0u8, 1, 2][..]);
2252        assert!(buf.slice(..2).cast::<bool, 1>([2]).is_ok());
2253        assert!(buf.cast::<bool, 1>([3]).is_err());
2254    }
2255
2256    /// A buffer gives its octets back, which is what it is encoded from.
2257    #[test]
2258    fn octets_round_trip() {
2259        let values = Buf::<u16, 1>::from(vec![1, 2]);
2260        assert_eq!(values.as_bytes(), [1u16.to_ne_bytes(), 2u16.to_ne_bytes()].concat());
2261        let buf = values.into_bytes();
2262        assert_eq!(buf.cast::<u16, 1>([2]).unwrap().as_slice(), &[1, 2]);
2263    }
2264
2265    #[test]
2266    fn strings() {
2267        let strings = Buf::<str, 1>::from(&["ab", "", "cde"][..]);
2268        assert_eq!(strings.get([2]), Some("cde"));
2269        assert_eq!(strings.iter().collect::<Vec<_>>(), ["ab", "", "cde"]);
2270        assert_eq!(strings.slice(1..).get([1]), Some("cde"));
2271        assert_eq!(Buf::<str, 0>::from("scalar").value(), "scalar");
2272    }
2273
2274    /// Strings copied out of an iterator, as many as it gives whatever its size hint says,
2275    /// empty ones and no string at all included.
2276    #[test]
2277    fn strings_from_iter() {
2278        let strings = Buf::<str, 1>::from_strs(["ab", "", "cde"].into_iter().filter(|_| true)).unwrap();
2279        assert_eq!(strings.dim(), [3]);
2280        assert_eq!(strings.iter().collect::<Vec<_>>(), ["ab", "", "cde"]);
2281        let empty = Buf::<str, 1>::from_strs(std::iter::empty::<&str>()).unwrap();
2282        assert!(empty.is_empty());
2283    }
2284
2285    /// Strings decoded from octets are found at the spans the decoder gives, relative to
2286    /// the octets, and share their storage: they outlive the buffer of octets.
2287    #[test]
2288    fn string_spans() {
2289        let msg = Buf::from(&b"..hello world"[..]);
2290        let strings = Buf::<str, 1>::from_spans(msg.slice(2..), [0..5, 6..11], [2]).unwrap();
2291        drop(msg);
2292        assert_eq!(strings.iter().collect::<Vec<_>>(), ["hello", "world"]);
2293        // Every span is checked: within the octets, not inverted, and valid UTF-8.
2294        let buf = Buf::from(&[b'a', 0xff][..]);
2295        let buf = Buf::<str, 1>::from_spans(buf, [0..3], [1]).unwrap_err();
2296        let buf = Buf::<str, 1>::from_spans(buf, [1..2], [1]).unwrap_err();
2297        #[allow(clippy::reversed_empty_ranges)]
2298        let buf = Buf::<str, 1>::from_spans(buf, [1..0], [1]).unwrap_err();
2299        assert!(Buf::<str, 0>::from_spans(buf, [0..1], []).is_ok());
2300    }
2301
2302    /// Spans are given as the decoder reads them, and must be exactly as many as the
2303    /// dimensions say, which nothing is attached to the storage for when they are not.
2304    #[test]
2305    fn span_iterator() {
2306        let msg = Buf::from(&b"a,bc,def"[..]);
2307        let spans = msg.as_slice().split(|&b| b == b',').scan(0, |start, part| {
2308            let span = *start..*start + part.len() as u32;
2309            *start = span.end + 1;
2310            Some(span)
2311        }).collect::<Vec<_>>();
2312        let strings = Buf::<str, 1>::from_spans(msg.clone(), spans.clone(), [3]).unwrap();
2313        assert_eq!(strings.iter().collect::<Vec<_>>(), ["a", "bc", "def"]);
2314        let msg = Buf::<str, 1>::from_spans(msg, spans.clone(), [2]).unwrap_err();
2315        let msg = Buf::<str, 1>::from_spans(msg, spans.clone(), [4]).unwrap_err();
2316        let msg = Buf::<str, 1>::from_spans(msg, spans.clone(), [usize::MAX]).unwrap_err();
2317        assert!(Buf::<str, 1>::from_spans(msg, [], [0]).is_ok());
2318    }
2319
2320    #[test]
2321    fn thread_sharing() {
2322        let values = Buf::<f64, 1>::from(vec![1.0, 2.0]);
2323        let sum = std::thread::spawn({
2324            let values = values.clone();
2325            move || values.iter().sum::<f64>()
2326        });
2327        assert_eq!(sum.join().unwrap(), 3.0);
2328    }
2329
2330    /// A state is packed like a number, only its known values being valid ones.
2331    #[test]
2332    fn states() {
2333        let buf = Buf::from(&[DevState::Moving as u8, 200][..]);
2334        let buf = buf.cast::<DevState, 1>([2]).unwrap_err();
2335        assert_eq!(buf.slice(..1).cast::<DevState, 0>([]).unwrap().value(), DevState::Moving);
2336    }
2337
2338    /// Buffers are equal when their dimensions and values are, wherever they are stored.
2339    #[test]
2340    fn equality() {
2341        let values = Buf::<i32, 1>::from([1, 2, 3, 4]);
2342        assert_eq!(values.slice(2..), Buf::from([3, 4]));
2343        assert_ne!(values.clone().reshape([2, 2]).unwrap(), Buf::from_slice(&[1, 2, 3, 4], [4, 1]).unwrap());
2344    }
2345
2346    /// Only the first values of a buffer are shown.
2347    #[test]
2348    fn debug() {
2349        assert_eq!(format!("{:?}", Buf::<u16, 1>::from([7; 3])), "Buf<3>[7, 7, 7]");
2350        assert_eq!(format!("{:?}", Buf::<u16, 0>::from(7)), "Buf(7)");
2351        let rows = Buf::<i32, 2>::from_slice(&[1, 2, 3, 4, 5, 6], [3, 2]).unwrap();
2352        assert_eq!(format!("{rows:?}"), "Buf<3, 2>[[1, 2, 3], [4, 5, 6]]");
2353        assert_eq!(format!("{rows:#?}"), "Buf<3, 2>[\n    [1, 2, 3],\n    [4, 5, 6],\n]");
2354        assert_eq!(format!("{:?}", BufMut::<u8, 2>::zeroed([2, 0])), "BufMut<2, 0>[]");
2355        assert_eq!(format!("{:?}", Buf::<u8, 2>::new().reshape([0, 2]).unwrap()), "Buf<0, 2>[[], []]");
2356        assert_eq!(format!("{:?}", Buf::<str, 1>::from(&["a", "b"][..])), r#"Buf<2>["a", "b"]"#);
2357    }
2358
2359    /// Octets are shown in hexadecimal, all of them, with runs of readable ASCII quoted.
2360    #[test]
2361    fn octets_debug() {
2362        assert_eq!(format!("{:?}", Buf::from(&b"\x01\x02GIOP\x00"[..])), "Buf<7>[01 02 'GIOP' 00]");
2363        assert_eq!(format!("{:?}", BufMut::<u8, 1>::from(vec![0xAB; 20])), format!("BufMut<20>[{}AB]", "AB ".repeat(19)));
2364        let rows = Buf::<u8, 2>::from_slice(b"ab\x01\x02", [2, 2]).unwrap();
2365        assert_eq!(format!("{rows:?}"), "Buf<2, 2>[['ab'], [01 02]]");
2366    }
2367
2368    /// Octets are formatted as plain hexadecimal, which is parsed back, and other packed
2369    /// values as the groups of their octets.
2370    #[test]
2371    fn hex() {
2372        let buf = Buf::from(&[0x01, 0xAB, 0x00][..]);
2373        assert_eq!(format!("{buf:X}"), "01AB00");
2374        assert_eq!(format!("{buf:x}"), "01ab00");
2375        assert_eq!(format!("{:X}", buf.clone().into_mut()), "01AB00");
2376        assert_eq!(BufMut::from_hex("01AB00").unwrap().freeze(), buf);
2377        assert_eq!(BufMut::from_hex("01ab00").unwrap().freeze(), buf);
2378        assert!(BufMut::from_hex("01A").is_none());
2379        assert!(BufMut::from_hex("0G").is_none());
2380        // Larger values are grouped, in the order their octets are stored.
2381        let words = Buf::<u16, 1>::from([0x0102, 0xABCD]);
2382        let expected = if cfg!(target_endian = "little") { "0201 cdab" } else { "0102 abcd" };
2383        assert_eq!(format!("{words:x}"), expected);
2384        assert_eq!(format!("{:X}", Buf::<u32, 1>::new()), "");
2385    }
2386
2387    /// A buffer is a reference to a storage and its dimensions, nothing more: the spans of
2388    /// a packed type take no room, and a table is one pointer.
2389    #[test]
2390    fn sizes() {
2391        assert_eq!(mem::size_of::<Buf<f64, 0>>(), 16);
2392        assert_eq!(mem::size_of::<Buf<u8, 1>>(), 24);
2393        assert_eq!(mem::size_of::<Buf<f64, 2>>(), 32);
2394        assert_eq!(mem::size_of::<Buf<str, 1>>(), 32);
2395        assert_eq!(mem::size_of::<BufMut<u8, 1>>(), 24);
2396    }
2397
2398}