scolapasta_strbuf/nul_terminated_vec.rs
1#![expect(
2 clippy::missing_panics_doc,
3 reason = "enforcing nul termination will not panic in practice"
4)]
5
6use alloc::borrow::Cow;
7use alloc::boxed::Box;
8use alloc::collections::TryReserveError;
9use alloc::string::String;
10use alloc::vec::{IntoIter, Vec};
11use core::borrow::{Borrow, BorrowMut};
12use core::fmt;
13use core::ops::{Deref, DerefMut};
14use core::slice::{Iter, IterMut};
15#[cfg(feature = "std")]
16use std::io::{self, IoSlice, Write};
17
18use raw_parts::RawParts;
19
20/// Ensure the given `Vec` can be used safely by C code as a string buffer.
21///
22/// mruby C code assumes that all string buffers it allocates have at least one
23/// extra byte trailing the requested capacity AND that said byte is the NUL
24/// byte (`b'\0'` or `0`).
25///
26/// This function MUST be called by all APIs which may modify the inner `Vec`.
27///
28/// This function produces a stronger guarantee than that provided by mruby: the
29/// first AND last bytes of the spare capacity trailing the `Vec` will be the
30/// NUL byte.
31fn ensure_nul_terminated(vec: &mut Vec<u8>) -> Result<(), TryReserveError> {
32 const NUL_BYTE: u8 = 0;
33
34 let spare_capacity = vec.spare_capacity_mut();
35 // If the vec has spare capacity, set the first and last bytes to NUL.
36 //
37 // See:
38 //
39 // - <https://github.com/artichoke/artichoke/pull/1976#discussion_r932782264>
40 // - <https://github.com/artichoke/artichoke/blob/16c869a9ad29acfe143bfcc011917ef442ccac54/artichoke-backend/vendor/mruby/src/string.c#L36-L38>
41 match spare_capacity {
42 [] => {}
43 [next] => {
44 next.write(NUL_BYTE);
45 return Ok(());
46 }
47 [head, .., tail] => {
48 head.write(NUL_BYTE);
49 tail.write(NUL_BYTE);
50 return Ok(());
51 }
52 }
53 // Else `vec.len == vec.capacity`, so reserve an extra byte.
54 vec.try_reserve_exact(1)?;
55 let spare_capacity = vec.spare_capacity_mut();
56 match spare_capacity {
57 [] => unreachable!("Vec should have spare capacity"),
58 [next] => {
59 next.write(NUL_BYTE);
60 }
61 [head, .., tail] => {
62 head.write(NUL_BYTE);
63 tail.write(NUL_BYTE);
64 }
65 }
66 Ok(())
67}
68
69/// A contiguous growable byte string, written as `Buf`, short for "buffer".
70///
71/// This buffer is a transparent wrapper around [`Vec<u8>`] with a minimized API
72/// sufficient for implementing the Ruby [`String`] type.
73///
74/// This buffer does not assume any encoding. Encoding is a higher-level concept
75/// that should be built on top of `Buf`.
76///
77/// # Examples
78///
79/// ```
80/// use scolapasta_strbuf::Buf;
81///
82/// let mut buf = Buf::new();
83/// buf.push_byte(b'a');
84/// buf.push_byte(b'z');
85///
86/// assert_eq!(buf.len(), 2);
87/// assert_eq!(buf[0], b'a');
88///
89/// assert_eq!(buf.pop_byte(), Some(b'z'));
90/// assert_eq!(buf.len(), 1);
91///
92/// buf[0] = b'!';
93/// assert_eq!(buf[0], b'!');
94///
95/// buf.extend(b"excite!!!");
96///
97/// for byte in &buf {
98/// println!("{byte}");
99/// }
100/// assert_eq!(buf, b"!excite!!!");
101/// ```
102///
103/// # Indexing
104///
105/// The `Buf` type allows to access values by index, because it implements the
106/// [`Index`] trait. An example will be more explicit:
107///
108/// ```
109/// use scolapasta_strbuf::Buf;
110///
111/// let buf = Buf::from(b"scolapasta-strbuf");
112/// println!("{}", buf[1]); // it will display 'c'
113/// ```
114///
115/// However be careful: if you try to access an index which isn't in the `Buf`,
116/// your software will panic! You cannot do this:
117///
118/// ```should_panic
119/// use scolapasta_strbuf::Buf;
120///
121/// let buf = Buf::from(b"scolapasta-strbuf");
122/// println!("{}", buf[100]); // it will panic!
123/// ```
124///
125/// # Capacity and reallocation
126///
127/// The capacity of a buffer is the amount of space allocated for any future
128/// bytes that will be added onto the buffer. This is not to be confused with
129/// the _length_ of a buffer, which specifies the number of actual bytes within
130/// the buffer. If a buffer's length exceeds its capacity, its capacity will
131/// automatically be increased, but its contents will have to be reallocated.
132///
133/// For example, a buffer with capacity 10 and length 0 would be an empty buffer
134/// with space for 10 more bytes. Pushing 10 or fewer bytes into the buffer will
135/// not change its capacity or cause reallocation to occur. However, if the
136/// buffer's length is increased to 11, it will have to reallocate, which can be
137/// slow. For this reason, it is recommended to use `Buf::with_capacity`
138/// whenever possible to specify how big the buffer is expected to get.
139///
140/// # Guarantees
141///
142/// `Buf` is guaranteed to be a `repr(transparent)` wrapper around a `Vec<u8>`,
143/// which means it shares all the same [guarantees as a `Vec`]. See the upstream
144/// documentation in [`std`][vec-docs] for more details.
145///
146/// In addition to the guarantees of the underlying `Vec`, `Buf` is guaranteed
147/// to have a NUL-terminated allocation. All `Buf`s will have spare capacity.
148/// The first and last bytes of that spare capacity will be the NUL byte.
149///
150/// `Buf` does not expose any APIs, such as mutable access to the underlying
151/// `Vec`, that allow violating this invariant. This variant is even upheld by
152/// unsafe APIs such as [`set_len`].
153///
154/// ```
155/// # #[cfg(feature = "nul-terminated")]
156/// # {
157/// use scolapasta_strbuf::Buf;
158///
159/// let buf = Buf::new();
160/// assert_eq!(buf.capacity(), 1);
161///
162/// let mut inner = buf.into_inner();
163/// let spare = inner.spare_capacity_mut();
164/// assert!(!spare.is_empty());
165/// assert_eq!(unsafe { spare.first().unwrap().assume_init() }, 0);
166/// assert_eq!(unsafe { spare.last().unwrap().assume_init() }, 0);
167/// # }
168/// ```
169///
170/// [`Vec<u8>`]: Vec
171/// [`String`]: https://ruby-doc.org/3.2.0/String.html
172/// [`Index`]: core::ops::Index
173/// [guarantees as a `Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#guarantees
174/// [vec-docs]: mod@alloc::vec
175/// [`set_len`]: Self::set_len
176#[repr(transparent)]
177#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
178pub struct Buf {
179 inner: Vec<u8>,
180}
181
182impl Buf {
183 /// Consume this buffer and return its inner [`Vec<u8>`].
184 ///
185 /// # Examples
186 ///
187 /// ```
188 /// use scolapasta_strbuf::Buf;
189 ///
190 /// let buf = Buf::from(b"abc");
191 /// let vec: Vec<u8> = buf.into_inner();
192 /// assert_eq!(vec, b"abc");
193 /// ```
194 ///
195 /// [`Vec<u8>`]: Vec
196 #[inline]
197 #[must_use]
198 pub fn into_inner(self) -> Vec<u8> {
199 self.inner
200 }
201}
202
203impl Default for Buf {
204 #[inline]
205 fn default() -> Self {
206 Self::new()
207 }
208}
209
210impl Clone for Buf {
211 #[inline]
212 fn clone(&self) -> Self {
213 let vec = self.inner.clone();
214 Self::from(vec)
215 }
216}
217
218impl From<Vec<u8>> for Buf {
219 #[inline]
220 fn from(mut vec: Vec<u8>) -> Self {
221 ensure_nul_terminated(&mut vec).expect("alloc failure");
222 Self { inner: vec }
223 }
224}
225
226impl<'a> From<&'a [u8]> for Buf {
227 #[inline]
228 fn from(s: &'a [u8]) -> Self {
229 let vec = s.to_vec();
230 Self::from(vec)
231 }
232}
233
234impl<'a> From<&'a mut [u8]> for Buf {
235 #[inline]
236 fn from(s: &'a mut [u8]) -> Self {
237 let vec = s.to_vec();
238 Self::from(vec)
239 }
240}
241
242impl<const N: usize> From<[u8; N]> for Buf {
243 #[inline]
244 fn from(s: [u8; N]) -> Self {
245 let vec = Vec::from(s);
246 Self::from(vec)
247 }
248}
249
250impl<'a, const N: usize> From<&'a [u8; N]> for Buf {
251 #[inline]
252 fn from(s: &'a [u8; N]) -> Self {
253 let vec = s.to_vec();
254 Self::from(vec)
255 }
256}
257
258impl<'a, const N: usize> From<&'a mut [u8; N]> for Buf {
259 #[inline]
260 fn from(s: &'a mut [u8; N]) -> Self {
261 let vec = s.to_vec();
262 Self::from(vec)
263 }
264}
265
266impl<'a> From<Cow<'a, [u8]>> for Buf {
267 #[inline]
268 fn from(s: Cow<'a, [u8]>) -> Self {
269 let vec = s.into_owned();
270 Self::from(vec)
271 }
272}
273
274impl From<String> for Buf {
275 #[inline]
276 fn from(s: String) -> Self {
277 let vec = s.into_bytes();
278 Self::from(vec)
279 }
280}
281
282impl<'a> From<&'a str> for Buf {
283 #[inline]
284 fn from(s: &'a str) -> Self {
285 let vec = s.as_bytes().to_vec();
286 Self::from(vec)
287 }
288}
289
290impl<'a> From<&'a mut str> for Buf {
291 #[inline]
292 fn from(s: &'a mut str) -> Self {
293 let vec = s.as_bytes().to_vec();
294 Self::from(vec)
295 }
296}
297
298impl<'a> From<Cow<'a, str>> for Buf {
299 #[inline]
300 fn from(s: Cow<'a, str>) -> Self {
301 let vec = s.into_owned().into_bytes();
302 Self::from(vec)
303 }
304}
305
306impl From<Buf> for Vec<u8> {
307 #[inline]
308 fn from(buf: Buf) -> Self {
309 buf.inner
310 }
311}
312
313impl<const N: usize> TryFrom<Buf> for [u8; N] {
314 type Error = Buf;
315
316 #[inline]
317 fn try_from(buf: Buf) -> Result<Self, Self::Error> {
318 match buf.into_inner().try_into() {
319 Ok(array) => Ok(array),
320 Err(vec) => Err(vec.into()),
321 }
322 }
323}
324
325impl From<Buf> for Cow<'_, [u8]> {
326 #[inline]
327 fn from(buf: Buf) -> Self {
328 Cow::Owned(buf.into())
329 }
330}
331
332impl AsRef<[u8]> for Buf {
333 #[inline]
334 fn as_ref(&self) -> &[u8] {
335 self.inner.as_ref()
336 }
337}
338
339impl AsMut<[u8]> for Buf {
340 #[inline]
341 fn as_mut(&mut self) -> &mut [u8] {
342 self.inner.as_mut()
343 }
344}
345
346impl Borrow<[u8]> for Buf {
347 fn borrow(&self) -> &[u8] {
348 self
349 }
350}
351
352impl BorrowMut<[u8]> for Buf {
353 fn borrow_mut(&mut self) -> &mut [u8] {
354 self
355 }
356}
357
358impl Deref for Buf {
359 type Target = [u8];
360
361 #[inline]
362 fn deref(&self) -> &Self::Target {
363 &self.inner
364 }
365}
366
367impl DerefMut for Buf {
368 #[inline]
369 fn deref_mut(&mut self) -> &mut Self::Target {
370 // SAFETY: the mutable reference given out is a slice, NOT the
371 // underlying `Vec`, so the allocation cannot change size.
372 &mut self.inner
373 }
374}
375
376impl FromIterator<u8> for Buf {
377 #[inline]
378 fn from_iter<T>(iter: T) -> Self
379 where
380 T: IntoIterator<Item = u8>,
381 {
382 let inner = iter.into_iter().collect::<Vec<u8>>();
383 Self::from(inner)
384 }
385}
386
387impl Extend<u8> for Buf {
388 #[inline]
389 fn extend<I: IntoIterator<Item = u8>>(&mut self, iter: I) {
390 self.inner.extend(iter);
391 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
392 }
393}
394
395impl<'a> Extend<&'a u8> for Buf {
396 #[inline]
397 fn extend<I: IntoIterator<Item = &'a u8>>(&mut self, iter: I) {
398 self.inner.extend(iter.into_iter().copied());
399 }
400}
401
402impl_partial_eq!(Buf, Vec<u8>);
403impl_partial_eq!(Buf, &'a Vec<u8>);
404impl_partial_eq!(Buf, [u8]);
405impl_partial_eq!(Buf, &'a [u8]);
406impl_partial_eq!(Buf, &'a mut [u8]);
407impl_partial_eq!(Buf, String);
408impl_partial_eq!(Buf, &'a String);
409impl_partial_eq!(Buf, str);
410impl_partial_eq!(Buf, &'a str);
411impl_partial_eq!(Buf, &'a mut str);
412impl_partial_eq_array!(Buf, [u8; N]);
413impl_partial_eq_array!(Buf, &'a [u8; N]);
414impl_partial_eq_array!(Buf, &'a mut [u8; N]);
415
416impl IntoIterator for Buf {
417 type Item = u8;
418 type IntoIter = IntoIter<u8>;
419
420 fn into_iter(self) -> Self::IntoIter {
421 self.into_inner().into_iter()
422 }
423}
424
425impl<'a> IntoIterator for &'a Buf {
426 type Item = &'a u8;
427 type IntoIter = Iter<'a, u8>;
428
429 fn into_iter(self) -> Self::IntoIter {
430 self.iter()
431 }
432}
433
434impl<'a> IntoIterator for &'a mut Buf {
435 type Item = &'a mut u8;
436 type IntoIter = IterMut<'a, u8>;
437
438 fn into_iter(self) -> Self::IntoIter {
439 self.iter_mut()
440 }
441}
442
443/// Minimal [`Vec`] API.
444impl Buf {
445 /// Constructs a new, empty `Buf`.
446 ///
447 /// The buffer will allocate one byte to maintain its NUL termination
448 /// invariant.
449 ///
450 /// # Examples
451 ///
452 /// ```
453 /// use scolapasta_strbuf::Buf;
454 ///
455 /// let mut buf = Buf::new();
456 /// ```
457 #[inline]
458 #[must_use]
459 pub fn new() -> Self {
460 let inner = Vec::with_capacity(1);
461 Self::from(inner)
462 }
463
464 /// Constructs a new, empty `Buf` with at least the specified capacity.
465 ///
466 /// The buffer will be able to hold at least `capacity` bytes without
467 /// reallocating. This method is allowed to allocate for more elements than
468 /// `capacity`. If `capacity` is 0, the buffer will allocate 1 byte to
469 /// maintain its NUL termination invariant.
470 ///
471 /// It is important to note that although the returned buffer has the
472 /// minimum *capacity* specified, the vector will have a zero *length*. For
473 /// an explanation of the difference between length and capacity, see
474 /// *[Capacity and reallocation]*.
475 ///
476 /// If it is important to know the exact allocated capacity of a `Buf`,
477 /// always use the [`capacity`] method after construction.
478 ///
479 /// [Capacity and reallocation]: #capacity-and-reallocation
480 /// [`capacity`]: Self::capacity
481 ///
482 /// # Panics
483 ///
484 /// Panics if the new capacity exceeds `isize::MAX` bytes.
485 ///
486 /// # Examples
487 ///
488 /// ```
489 /// use scolapasta_strbuf::Buf;
490 ///
491 /// let mut buf = Buf::with_capacity(26);
492 ///
493 /// // The buffer is empty, even though it has capacity for more
494 /// assert_eq!(buf.len(), 0);
495 /// assert!(buf.capacity() >= 26);
496 ///
497 /// // These are all done without reallocating...
498 /// for ch in b'a'..=b'z' {
499 /// buf.push_byte(ch);
500 /// }
501 /// assert_eq!(buf.len(), 26);
502 /// assert!(buf.capacity() >= 26);
503 ///
504 /// // ...but this may make the buffer reallocate
505 /// buf.push_byte(b'!');
506 /// assert_eq!(buf.len(), 27);
507 /// assert!(buf.capacity() >= 27);
508 /// ```
509 #[inline]
510 #[must_use]
511 pub fn with_capacity(capacity: usize) -> Self {
512 let capacity = capacity.checked_add(1).expect("capacity overflow");
513 let inner = Vec::with_capacity(capacity);
514 Self::from(inner)
515 }
516
517 /// Creates a `Buf` directly from a pointer, a capacity, and a length.
518 ///
519 /// Reconstructing the buffer may cause a reallocation to maintain the
520 /// buffer's NUL termination invariant.
521 ///
522 /// # Safety
523 ///
524 /// This is highly unsafe, due to the number of invariants that aren't
525 /// checked.
526 ///
527 /// Refer to the safety documentation for [`Vec::from_raw_parts`] for more
528 /// details.
529 ///
530 /// In addition to the safety invariants of `Vec`, `Buf` has the additional
531 /// requirement that callers ensure the spare capacity of the allocation
532 /// referred to by `ptr` is NUL terminated at offset `length` and `capacity`.
533 ///
534 /// # Examples
535 ///
536 /// ```
537 /// use core::ptr;
538 ///
539 /// use raw_parts::RawParts;
540 /// use scolapasta_strbuf::Buf;
541 ///
542 /// let buf = Buf::from(b"abcde");
543 /// let RawParts { ptr, length, capacity } = buf.into_raw_parts();
544 ///
545 /// unsafe {
546 /// ptr::write(ptr, b'A');
547 /// ptr::write(ptr.add(1), b'B');
548 ///
549 /// let raw_parts = RawParts { ptr, length, capacity };
550 /// let rebuilt = Buf::from_raw_parts(raw_parts);
551 ///
552 /// assert_eq!(rebuilt, b"ABcde");
553 /// }
554 /// ```
555 #[inline]
556 #[must_use]
557 pub unsafe fn from_raw_parts(raw_parts: RawParts<u8>) -> Self {
558 // SAFETY: Callers ensure that the raw parts safety invariants are
559 // upheld.
560 let inner = unsafe { raw_parts.into_vec() };
561 Self::from(inner)
562 }
563
564 /// Decomposes a `Buf` into its raw components.
565 ///
566 /// Returns the raw pointer to the underlying bytes, the length of the
567 /// buffer (in bytes), and the allocated capacity of the data (in bytes).
568 ///
569 /// After calling this function, the caller is responsible for the memory
570 /// previously managed by the `Buf`. The only way to do this is to convert
571 /// the raw pointer, length, and capacity back into a `Buf` with the
572 /// [`from_raw_parts`] function, allowing the destructor to perform the cleanup.
573 ///
574 /// [`from_raw_parts`]: Self::from_raw_parts
575 ///
576 /// # Examples
577 ///
578 /// ```
579 /// use core::ptr;
580 ///
581 /// use raw_parts::RawParts;
582 /// use scolapasta_strbuf::Buf;
583 ///
584 /// let buf = Buf::from(b"abcde");
585 /// let RawParts { ptr, length, capacity } = buf.into_raw_parts();
586 ///
587 /// unsafe {
588 /// ptr::write(ptr, b'A');
589 /// ptr::write(ptr.add(1), b'B');
590 ///
591 /// let raw_parts = RawParts { ptr, length, capacity };
592 /// let rebuilt = Buf::from_raw_parts(raw_parts);
593 ///
594 /// assert_eq!(rebuilt, b"ABcde");
595 /// }
596 /// ```
597 #[inline]
598 #[must_use]
599 pub fn into_raw_parts(self) -> RawParts<u8> {
600 RawParts::from_vec(self.inner)
601 }
602
603 /// Returns the total number of bytes the buffer can hold without
604 /// reallocating.
605 ///
606 /// # Examples
607 ///
608 /// ```
609 /// # #[cfg(feature = "nul-terminated")]
610 /// # {
611 /// use scolapasta_strbuf::Buf;
612 ///
613 /// let mut buf = Buf::with_capacity(10);
614 /// buf.push_byte(b'!');
615 /// assert_eq!(buf.capacity(), 11);
616 /// # }
617 /// ```
618 #[inline]
619 #[must_use]
620 pub fn capacity(&self) -> usize {
621 self.inner.capacity()
622 }
623
624 /// Reserves capacity for at least `additional` more bytes to be inserted in
625 /// the given `Buf`.
626 ///
627 /// The buffer may reserve more space to speculatively avoid frequent
628 /// reallocations. After calling `reserve`, capacity will be greater than or
629 /// equal to `self.len() + additional`. Does nothing if capacity is already
630 /// sufficient.
631 ///
632 /// # Panics
633 ///
634 /// Panics if the new capacity exceeds `isize::MAX` bytes.
635 ///
636 /// # Examples
637 ///
638 /// ```
639 /// use scolapasta_strbuf::Buf;
640 ///
641 /// let mut buf = Buf::from(b"@");
642 /// buf.reserve(10);
643 /// assert!(buf.capacity() >= 11);
644 /// ```
645 #[inline]
646 pub fn reserve(&mut self, additional: usize) {
647 self.inner.reserve(additional);
648 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
649 }
650
651 /// Reserves the minimum capacity for at least `additional` more bytes to
652 /// be inserted in the given `Buf`.
653 ///
654 /// Unlike [`reserve`], this will not deliberately over-allocate to
655 /// speculatively avoid frequent allocations. After calling `reserve_exact`,
656 /// capacity will be greater than or equal to `self.len() + additional`.
657 /// Does nothing if the capacity is already sufficient.
658 ///
659 /// Note that the allocator may give the buffer more space than it requests.
660 /// Therefore, capacity can not be relied upon to be precisely minimal.
661 /// Prefer [`reserve`] if future insertions are expected.
662 ///
663 /// [`reserve`]: Self::reserve
664 ///
665 /// # Panics
666 ///
667 /// Panics if the new capacity exceeds `isize::MAX` bytes.
668 ///
669 /// # Examples
670 ///
671 /// ```
672 /// use scolapasta_strbuf::Buf;
673 ///
674 /// let mut buf = Buf::from(b"@");
675 /// buf.reserve_exact(10);
676 /// assert!(buf.capacity() >= 11);
677 /// ```
678 #[inline]
679 pub fn reserve_exact(&mut self, additional: usize) {
680 self.inner.reserve_exact(additional);
681 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
682 }
683
684 /// Tries to reserve capacity for at least `additional` more bytes to be
685 /// inserted in the given `Buf`.
686 ///
687 /// The buffer may reserve more space to speculatively avoid frequent
688 /// reallocations. After calling `try_reserve`, capacity will be greater
689 /// than or equal to `self.len() + additional` if it returns `Ok(())`. Does
690 /// nothing if capacity is already sufficient. This method preserves the
691 /// byte contents even if an error occurs.
692 ///
693 /// # Errors
694 ///
695 /// If the capacity overflows, or the allocator reports a failure, then an
696 /// error is returned.
697 #[inline]
698 pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
699 let additional = additional.checked_add(1).unwrap_or(additional);
700 self.inner.try_reserve(additional)?;
701 ensure_nul_terminated(&mut self.inner)?;
702 Ok(())
703 }
704
705 /// Tries to reserve the minimum capacity for at least `additional`
706 /// elements to be inserted in the given `Buf`.
707 ///
708 /// Unlike [`try_reserve`], this will not deliberately over-allocate to
709 /// speculatively avoid frequent allocations. After calling
710 /// `try_reserve_exact`, capacity will be greater than or equal to
711 /// `self.len() + additional` if it returns `Ok(())`. Does nothing if the
712 /// capacity is already sufficient.
713 ///
714 /// Note that the allocator may give the buffer more space than it requests.
715 /// Therefore, capacity can not be relied upon to be precisely minimal.
716 /// Prefer [`try_reserve`] if future insertions are expected.
717 ///
718 /// [`try_reserve`]: Self::try_reserve
719 ///
720 /// # Errors
721 ///
722 /// If the capacity overflows, or the allocator reports a failure, then an
723 /// error is returned.
724 #[inline]
725 pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
726 let additional = additional.checked_add(1).unwrap_or(additional);
727 self.inner.try_reserve_exact(additional)?;
728 ensure_nul_terminated(&mut self.inner)?;
729 Ok(())
730 }
731
732 /// Shrinks the capacity of the buffer as much as possible while maintaining
733 /// its NUL termination invariant.
734 ///
735 /// It will drop down as close as possible to the length but the allocator
736 /// may still inform the buffer that there is space for a few more bytes.
737 ///
738 /// # Examples
739 ///
740 /// ```
741 /// # #[cfg(feature = "nul-terminated")]
742 /// # {
743 /// use scolapasta_strbuf::Buf;
744 ///
745 /// let mut buf = Buf::with_capacity(10);
746 /// buf.extend(b"123");
747 /// assert_eq!(buf.capacity(), 11);
748 /// buf.shrink_to(4);
749 /// assert!(buf.capacity() >= 4);
750 /// buf.shrink_to_fit();
751 /// assert!(buf.capacity() >= 4);
752 /// # }
753 /// ```
754 #[inline]
755 pub fn shrink_to_fit(&mut self) {
756 self.inner.shrink_to_fit();
757 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
758 }
759
760 /// Shrinks the capacity of the buffer with a lower bound.
761 ///
762 /// The capacity will remain at least as large as both the length and the
763 /// supplied value.
764 ///
765 /// If the current capacity is less than the lower limit, this is a no-op.
766 ///
767 /// # Examples
768 ///
769 /// ```
770 /// # #[cfg(feature = "nul-terminated")]
771 /// # {
772 /// use scolapasta_strbuf::Buf;
773 ///
774 /// let mut buf = Buf::with_capacity(10);
775 /// buf.extend(b"123");
776 /// assert_eq!(buf.capacity(), 11);
777 /// buf.shrink_to(4);
778 /// assert!(buf.capacity() >= 4);
779 /// buf.shrink_to(0);
780 /// assert!(buf.capacity() >= 4);
781 /// # }
782 /// ```
783 #[inline]
784 pub fn shrink_to(&mut self, min_capacity: usize) {
785 self.inner.shrink_to(min_capacity);
786 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
787 }
788
789 /// Converts the buffer into [`Box<[u8]>`][owned slice].
790 ///
791 /// If the buffer has excess capacity, its bytes will be moved into a
792 /// newly-allocated buffer with exactly the right capacity.
793 ///
794 /// [owned slice]: Box
795 ///
796 /// # Examples
797 ///
798 /// ```
799 /// use scolapasta_strbuf::Buf;
800 ///
801 /// let buf = Buf::from(b"123");
802 ///
803 /// let slice = buf.into_boxed_slice();
804 /// ```
805 ///
806 /// Any excess capacity is removed:
807 ///
808 /// ```
809 /// # #[cfg(feature = "nul-terminated")]
810 /// # {
811 /// use scolapasta_strbuf::Buf;
812 ///
813 /// let mut buf = Buf::with_capacity(10);
814 /// buf.extend(b"123");
815 ///
816 /// assert_eq!(buf.capacity(), 11);
817 /// let slice = buf.into_boxed_slice();
818 /// assert_eq!(slice.into_vec().capacity(), 3);
819 /// # }
820 /// ```
821 #[inline]
822 #[must_use]
823 pub fn into_boxed_slice(self) -> Box<[u8]> {
824 self.inner.into_boxed_slice()
825 }
826
827 /// Shorten the buffer, keeping the first `len` bytes and dropping the rest.
828 ///
829 /// If `len` is greater than the buffer's current length, this has no
830 /// effect.
831 ///
832 /// Note that this method has no effect on the allocated capacity of the
833 /// buffer.
834 ///
835 /// # Examples
836 ///
837 /// Truncating a five byte buffer to two bytes:
838 ///
839 /// ```
840 /// use scolapasta_strbuf::Buf;
841 ///
842 /// let mut buf = Buf::from(b"12345");
843 /// buf.truncate(2);
844 /// assert_eq!(buf, b"12");
845 /// ```
846 ///
847 /// No truncation occurs when `len` is greater than the buffer's current
848 /// length:
849 ///
850 /// ```
851 /// use scolapasta_strbuf::Buf;
852 ///
853 /// let mut buf = Buf::from(b"123");
854 /// buf.truncate(8);
855 /// assert_eq!(buf, b"123");
856 /// ```
857 ///
858 /// Truncating when `len == 0` is equivalent to calling the [`clear`]
859 /// method.
860 ///
861 /// ```
862 /// use scolapasta_strbuf::Buf;
863 ///
864 /// let mut buf = Buf::from(b"123");
865 /// buf.truncate(0);
866 /// assert_eq!(buf, b"");
867 /// ```
868 ///
869 /// [`clear`]: Self::clear
870 #[inline]
871 pub fn truncate(&mut self, len: usize) {
872 self.inner.truncate(len);
873 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
874 }
875
876 /// Extract a slice containing the entire buffer.
877 ///
878 /// Equivalent to `&buf[..]`.
879 #[inline]
880 #[must_use]
881 pub fn as_slice(&self) -> &[u8] {
882 self.inner.as_slice()
883 }
884
885 /// Extract a mutable slice containing the entire buffer.
886 ///
887 /// Equivalent to `&mut buf[..]`.
888 #[inline]
889 #[must_use]
890 pub fn as_mut_slice(&mut self) -> &mut [u8] {
891 self.inner.as_mut_slice()
892 }
893
894 /// Return a raw pointer to the buffer's inner vec, or a dangling raw
895 /// pointer valid for zero sized reads if the buffer didn't allocate.
896 ///
897 /// The caller must ensure correct use of the pointer. See [`Vec::as_ptr`]
898 /// for more details.
899 ///
900 /// Callers must also ensure that the NUL termination invariant of the
901 /// buffer is maintained is the returned pointer is used for writes.
902 #[inline]
903 #[must_use]
904 pub fn as_ptr(&self) -> *const u8 {
905 self.inner.as_ptr()
906 }
907
908 /// Return an unsafe mutable pointer to the buffer's inner vec, or a
909 /// dangling raw pointer valid for zero sized reads if the buffer didn't
910 /// allocate.
911 ///
912 /// The caller must ensure correct use of the pointer. See [`Vec::as_mut_ptr`]
913 /// for more details.
914 ///
915 /// Callers must also ensure that the NUL termination invariant of the
916 /// buffer is maintained is the returned pointer is used for writes.
917 #[inline]
918 #[must_use]
919 pub fn as_mut_ptr(&mut self) -> *mut u8 {
920 self.inner.as_mut_ptr()
921 }
922
923 /// Force the length of the buffer to `new_len`.
924 ///
925 /// This is a low-level operation that maintains none of the normal
926 /// invariants of the type. Normally changing the length of a vector is done
927 /// using one of the safe operations instead, such as [`truncate`],
928 /// [`resize`], [`extend`], or [`clear`].
929 ///
930 /// [`truncate`]: Self::truncate
931 /// [`resize`]: Self::resize
932 /// [`extend`]: Self::extend
933 /// [`clear`]: Self::clear
934 ///
935 /// # Safety
936 ///
937 /// - `new_len` must be less than or equal to [`capacity()`].
938 /// - The elements at `old_len..new_len` must be initialized.
939 ///
940 /// [`capacity()`]: Self::capacity
941 #[inline]
942 pub unsafe fn set_len(&mut self, new_len: usize) {
943 // SAFETY: Caller has guaranteed the safety invariants of `Vec::set_len`
944 // are upheld.
945 unsafe {
946 self.inner.set_len(new_len);
947 }
948 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
949 }
950
951 /// Insert a byte at position `index` within the buffer, shifting all
952 /// elements after it to the right.
953 ///
954 /// # Panics
955 ///
956 /// Panics if `index > len`.
957 ///
958 /// # Examples
959 ///
960 /// ```
961 /// use scolapasta_strbuf::Buf;
962 ///
963 /// let mut buf = Buf::from(b"123");
964 /// buf.insert(1, b'4');
965 /// assert_eq!(buf, b"1423");
966 /// buf.insert(4, b'5');
967 /// assert_eq!(buf, b"14235");
968 /// ```
969 #[inline]
970 pub fn insert(&mut self, index: usize, element: u8) {
971 self.inner.insert(index, element);
972 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
973 }
974
975 /// Remove and return the byte at position `index` within the buffer,
976 /// shifting all bytes after it to the left.
977 ///
978 /// **Note**: Because this shifts over the remaining bytes, it has a
979 /// worst-case performance of *O*(*n*).
980 ///
981 /// # Panics
982 ///
983 /// Panics if `index` is out of bounds.
984 ///
985 /// # Examples
986 ///
987 /// ```
988 /// use scolapasta_strbuf::Buf;
989 ///
990 /// let mut buf = Buf::from(b"123");
991 /// assert_eq!(buf.remove(1), b'2');
992 /// assert_eq!(buf, b"13");
993 /// ```
994 #[inline]
995 #[track_caller]
996 pub fn remove(&mut self, index: usize) -> u8 {
997 let removed = self.inner.remove(index);
998 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
999 removed
1000 }
1001
1002 /// Retain only the bytes specified by the predicate.
1003 ///
1004 /// In other words, remove all bytes `b` for which `f(&b)` returns `false`.
1005 /// This method operates in place, visiting each byte exactly once in the
1006 /// original order, and preserves the order of the retained bytes.
1007 ///
1008 /// # Examples
1009 ///
1010 /// ```
1011 /// use scolapasta_strbuf::Buf;
1012 ///
1013 /// let mut buf = Buf::from(b"abc, 123!");
1014 /// buf.retain(|&b| b.is_ascii_alphanumeric());
1015 /// assert_eq!(buf, b"abc123");
1016 /// ```
1017 ///
1018 /// Because the bytes are visited exactly once in the original order,
1019 /// external state may be used to decide which elements to keep.
1020 ///
1021 /// ```
1022 /// use scolapasta_strbuf::Buf;
1023 ///
1024 /// let mut buf = Buf::from(b"abc, 123!");
1025 /// let mut seen_space = false;
1026 /// buf.retain(|&b| {
1027 /// if seen_space {
1028 /// true
1029 /// } else {
1030 /// seen_space = b.is_ascii_whitespace();
1031 /// false
1032 /// }
1033 /// });
1034 /// assert_eq!(buf, b"123!");
1035 /// ```
1036 #[inline]
1037 pub fn retain<F>(&mut self, f: F)
1038 where
1039 F: FnMut(&u8) -> bool,
1040 {
1041 self.inner.retain(f);
1042 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
1043 }
1044
1045 /// Remove the last byte from the buffer and return it, or [`None`] if the
1046 /// buffer is empty.
1047 ///
1048 /// # Examples
1049 ///
1050 /// ```
1051 /// use scolapasta_strbuf::Buf;
1052 ///
1053 /// let mut buf = Buf::from(b"abc, 123!");
1054 /// assert_eq!(buf.pop_byte(), Some(b'!'));
1055 /// assert_eq!(buf, "abc, 123");
1056 /// ```
1057 #[inline]
1058 pub fn pop_byte(&mut self) -> Option<u8> {
1059 let popped = self.inner.pop();
1060 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
1061 popped
1062 }
1063
1064 /// Clear the buffer, removing all bytes.
1065 ///
1066 /// This method sets the length of the buffer to zero. Note that this method
1067 /// has no effect on the allocated capacity of the buffer.
1068 ///
1069 /// # Examples
1070 ///
1071 /// ```
1072 /// use scolapasta_strbuf::Buf;
1073 ///
1074 /// let mut buf = Buf::from(b"abc, 123!");
1075 /// let capacity = buf.capacity();
1076 ///
1077 /// buf.clear();
1078 ///
1079 /// assert!(buf.is_empty());
1080 /// assert_eq!(buf.capacity(), capacity);
1081 /// ```
1082 #[inline]
1083 pub fn clear(&mut self) {
1084 self.inner.clear();
1085 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
1086 }
1087
1088 /// Return the number of bytes in the buffer, also referred to as its
1089 /// "length" or "bytesize".
1090 ///
1091 /// # Examples
1092 ///
1093 /// ```
1094 /// use scolapasta_strbuf::Buf;
1095 ///
1096 /// let buf = Buf::from(b"abc");
1097 /// assert_eq!(buf.len(), 3);
1098 /// ```
1099 #[inline]
1100 #[must_use]
1101 pub fn len(&self) -> usize {
1102 self.inner.len()
1103 }
1104
1105 /// Return `true` if the buffer has empty byte content.
1106 ///
1107 /// # Examples
1108 ///
1109 /// ```
1110 /// use scolapasta_strbuf::Buf;
1111 ///
1112 /// let mut buf = Buf::new();
1113 /// assert!(buf.is_empty());
1114 ///
1115 /// buf.push_byte(b'!');
1116 /// assert!(!buf.is_empty());
1117 /// ```
1118 #[inline]
1119 #[must_use]
1120 pub fn is_empty(&self) -> bool {
1121 self.inner.is_empty()
1122 }
1123
1124 /// Resize the `Buf` in-place so that `len` is equal to `new_len`.
1125 ///
1126 /// If `new_len` is greater than `len`, the `Vec` is extended by the
1127 /// difference, with each additional slot filled with `value`. If `new_len`
1128 /// is less than `len`, the `Buf` is simply truncated.
1129 ///
1130 /// # Examples
1131 ///
1132 /// ```
1133 /// use scolapasta_strbuf::Buf;
1134 ///
1135 /// let mut buf = Buf::from(b"hello");
1136 /// buf.resize(8, b'!');
1137 /// assert_eq!(buf, b"hello!!!");
1138 ///
1139 /// let mut buf = Buf::from("wxyz");
1140 /// buf.resize(2, b'.');
1141 /// assert_eq!(buf, b"wx");
1142 /// ```
1143 #[inline]
1144 pub fn resize(&mut self, new_len: usize, value: u8) {
1145 self.inner.resize(new_len, value);
1146 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
1147 }
1148
1149 /// Copy and append all bytes in the given slice to the `Buf`.
1150 ///
1151 /// Iterate over the slice `other`, copy each byte, and then append
1152 /// it to this `Buf`. The `other` slice is traversed in-order.
1153 ///
1154 /// # Examples
1155 ///
1156 /// ```
1157 /// use scolapasta_strbuf::Buf;
1158 ///
1159 /// let mut buf = Buf::from(b"h");
1160 /// buf.extend_from_slice(b"ello world");
1161 /// assert_eq!(buf, b"hello world");
1162 /// ```
1163 #[inline]
1164 pub fn extend_from_slice(&mut self, other: &[u8]) {
1165 self.inner.extend_from_slice(other);
1166 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
1167 }
1168}
1169
1170/// Implementation of useful extension methods from [`bstr::ByteVec`].
1171///
1172/// [`bstr::ByteVec`]: https://docs.rs/bstr/latest/bstr/trait.ByteVec.html
1173impl Buf {
1174 /// Append the given byte to the end of this buffer.
1175 ///
1176 /// Note that this is equivalent to the generic [`Vec::push`] method. This
1177 /// method is provided to permit callers to explicitly differentiate
1178 /// between pushing bytes, codepoints and strings.
1179 ///
1180 /// # Examples
1181 ///
1182 /// ```
1183 /// use scolapasta_strbuf::Buf;
1184 ///
1185 /// let mut buf = Buf::from(b"abc");
1186 /// buf.push_byte(b'\xF0');
1187 /// buf.push_byte(b'\x9F');
1188 /// buf.push_byte(b'\xA6');
1189 /// buf.push_byte(b'\x80');
1190 /// assert_eq!(buf, "abc🦀");
1191 /// ```
1192 #[inline]
1193 pub fn push_byte(&mut self, byte: u8) {
1194 self.inner.push(byte);
1195 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
1196 }
1197
1198 /// Append the given [`char`] to the end of the buffer.
1199 ///
1200 /// The given `char` is encoded to its UTF-8 byte sequence which is appended
1201 /// to the buffer.
1202 ///
1203 /// # Examples
1204 ///
1205 /// ```
1206 /// use scolapasta_strbuf::Buf;
1207 ///
1208 /// let mut buf = Buf::from(b"abc");
1209 /// buf.push_char('🦀');
1210 /// assert_eq!(buf, "abc🦀");
1211 /// ```
1212 #[inline]
1213 pub fn push_char(&mut self, ch: char) {
1214 let mut buf = [0; 4];
1215 let s = ch.encode_utf8(&mut buf[..]);
1216 self.push_str(s);
1217 }
1218
1219 /// Append the given slice to the end of this buffer.
1220 ///
1221 /// This method accepts any type that be converted to a `&[u8]`. This
1222 /// includes, but is not limited to, `&str`, `&Buf`, and of course, `&[u8]`
1223 /// itself.
1224 ///
1225 /// # Examples
1226 ///
1227 /// ```
1228 /// use scolapasta_strbuf::Buf;
1229 ///
1230 /// let mut buf = Buf::from(b"abc");
1231 /// buf.push_str("🦀");
1232 /// assert_eq!(buf, "abc🦀");
1233 ///
1234 /// buf.push_str(b"\xF0\x9F\xA6\x80");
1235 /// assert_eq!(buf, "abc🦀🦀");
1236 /// ```
1237 #[inline]
1238 pub fn push_str<B: AsRef<[u8]>>(&mut self, bytes: B) {
1239 self.extend_from_slice(bytes.as_ref());
1240 }
1241}
1242
1243impl fmt::Write for Buf {
1244 #[inline]
1245 fn write_str(&mut self, s: &str) -> fmt::Result {
1246 self.push_str(s);
1247 Ok(())
1248 }
1249
1250 #[inline]
1251 fn write_char(&mut self, c: char) -> fmt::Result {
1252 self.push_char(c);
1253 Ok(())
1254 }
1255}
1256
1257#[cfg(feature = "std")]
1258impl Write for Buf {
1259 #[inline]
1260 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1261 let result = self.inner.write(buf);
1262 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
1263 result
1264 }
1265
1266 #[inline]
1267 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
1268 let result = self.inner.write_vectored(bufs);
1269 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
1270 result
1271 }
1272
1273 #[inline]
1274 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
1275 let result = self.inner.write_all(buf);
1276 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
1277 result
1278 }
1279
1280 #[inline]
1281 fn flush(&mut self) -> io::Result<()> {
1282 let result = self.inner.flush();
1283 ensure_nul_terminated(&mut self.inner).expect("alloc failure");
1284 result
1285 }
1286}
1287
1288#[cfg(test)]
1289mod tests {
1290 use alloc::vec::Vec;
1291
1292 use super::Buf;
1293
1294 #[must_use]
1295 #[expect(clippy::undocumented_unsafe_blocks, reason = "Testing unsafe functions")]
1296 fn is_nul_terminated(bytes: &mut Vec<u8>) -> bool {
1297 let spare_capacity = bytes.spare_capacity_mut();
1298 if spare_capacity.is_empty() {
1299 return false;
1300 }
1301
1302 let first = unsafe { spare_capacity.first().unwrap().assume_init() };
1303 if first != 0 {
1304 return false;
1305 }
1306
1307 let last = unsafe { spare_capacity.last().unwrap().assume_init() };
1308 if last != 0 {
1309 return false;
1310 }
1311 true
1312 }
1313
1314 #[test]
1315 fn default_is_new() {
1316 assert_eq!(Buf::default(), Buf::new());
1317 }
1318
1319 #[test]
1320 fn extra_capa_is_not_included_in_len() {
1321 let buf = Buf::new();
1322 assert!(buf.is_empty());
1323 assert_eq!(buf.len(), 0);
1324
1325 let buf = Buf::with_capacity(0);
1326 assert!(buf.is_empty());
1327 assert_eq!(buf.len(), 0);
1328
1329 let buf = Buf::with_capacity(100);
1330 assert!(buf.is_empty());
1331 assert_eq!(buf.len(), 0);
1332 }
1333
1334 #[test]
1335 fn clone_is_equal() {
1336 let buf = Buf::from("abc");
1337 assert_eq!(buf, buf.clone());
1338 }
1339
1340 #[test]
1341 fn try_reserve_overflow_is_err() {
1342 let mut buf = Buf::new();
1343 assert!(buf.try_reserve(usize::MAX).is_err());
1344 assert!(buf.is_empty());
1345 assert_eq!(buf.len(), 0);
1346 }
1347
1348 #[test]
1349 fn try_reserve_exact_overflow_is_err() {
1350 let mut buf = Buf::new();
1351 assert!(buf.try_reserve_exact(usize::MAX).is_err());
1352 assert!(buf.is_empty());
1353 assert_eq!(buf.len(), 0);
1354 }
1355
1356 #[test]
1357 fn try_reserve_zero_is_ok() {
1358 let mut buf = Buf::new();
1359 assert!(buf.try_reserve(0).is_ok());
1360 assert_eq!(buf.capacity(), 1);
1361 assert!(buf.is_empty());
1362 assert_eq!(buf.len(), 0);
1363 }
1364
1365 #[test]
1366 fn try_reserve_exact_zero_is_ok() {
1367 let mut buf = Buf::new();
1368 assert!(buf.try_reserve_exact(0).is_ok());
1369 assert_eq!(buf.capacity(), 1);
1370 assert!(buf.is_empty());
1371 assert_eq!(buf.len(), 0);
1372 }
1373
1374 #[test]
1375 fn test_ensure_nul_terminated_default() {
1376 let buf = Buf::default();
1377 let mut bytes = buf.into_inner();
1378 assert!(is_nul_terminated(&mut bytes));
1379 }
1380
1381 #[test]
1382 fn test_ensure_nul_terminated_new() {
1383 let buf = Buf::new();
1384 let mut bytes = buf.into_inner();
1385 assert!(is_nul_terminated(&mut bytes));
1386 }
1387
1388 #[test]
1389 fn test_ensure_nul_terminated_with_capacity() {
1390 let capacities = [0_usize, 1, 2, 3, 4, 19, 280, 499, 1024, 4096, 4099];
1391 for capa in capacities {
1392 let buf = Buf::with_capacity(capa);
1393 let mut bytes = buf.into_inner();
1394 assert!(is_nul_terminated(&mut bytes), "failed for capacity {capa}");
1395 }
1396 }
1397}
1398
1399#[cfg(test)]
1400#[expect(clippy::undocumented_unsafe_blocks, reason = "Testing unsafe functions")]
1401mod proptests {
1402 use alloc::string::String;
1403 use alloc::vec;
1404 use alloc::vec::Vec;
1405 use core::fmt;
1406
1407 use arbitrary::{Arbitrary, Unstructured};
1408 use raw_parts::RawParts;
1409
1410 use super::{Buf, ensure_nul_terminated};
1411
1412 pub fn run_arbitrary<T>(mut f: impl FnMut(T))
1413 where
1414 T: for<'a> Arbitrary<'a> + fmt::Debug,
1415 {
1416 fn get_unstructured(buf: &mut [u8]) -> Unstructured<'_> {
1417 getrandom::fill(buf).unwrap();
1418 Unstructured::new(buf)
1419 }
1420
1421 let mut buf = vec![0; 2048];
1422 let mut unstructured = get_unstructured(&mut buf);
1423 for _ in 0..1024 {
1424 if let Ok(value) = T::arbitrary(&mut unstructured) {
1425 f(value);
1426 continue;
1427 }
1428 // try reloading on randomness
1429 unstructured = get_unstructured(&mut buf);
1430 if let Ok(value) = T::arbitrary(&mut unstructured) {
1431 f(value);
1432 }
1433 }
1434 }
1435
1436 /// Returns whether the given vectors spare capacity is nonempty and that
1437 /// both its first and last bytes (of the spare capacity) are the NUL byte.
1438 #[inline]
1439 fn is_nul_terminated(vec: &mut Vec<u8>) -> bool {
1440 let spare = vec.spare_capacity_mut();
1441 if spare.is_empty() {
1442 return false;
1443 }
1444 let first = unsafe { spare.first().unwrap().assume_init() };
1445 if first != 0 {
1446 return false;
1447 }
1448 let last = unsafe { spare.last().unwrap().assume_init() };
1449 last == 0
1450 }
1451
1452 #[test]
1453 fn prop_test_ensure_nul_terminated() {
1454 run_arbitrary::<Vec<u8>>(|mut bytes| {
1455 ensure_nul_terminated(&mut bytes).unwrap();
1456 assert!(is_nul_terminated(&mut bytes));
1457 });
1458 }
1459
1460 #[test]
1461 fn prop_test_ensure_nul_terminated_after_shrink() {
1462 run_arbitrary::<Vec<u8>>(|mut bytes| {
1463 bytes.shrink_to_fit();
1464 ensure_nul_terminated(&mut bytes).unwrap();
1465 assert!(is_nul_terminated(&mut bytes));
1466 });
1467 }
1468
1469 #[test]
1470 fn prop_test_ensure_nul_terminated_from_vec() {
1471 run_arbitrary::<Vec<u8>>(|bytes| {
1472 let buf = Buf::from(bytes);
1473 let mut inner = buf.into_inner();
1474 assert!(is_nul_terminated(&mut inner));
1475 });
1476 }
1477
1478 #[test]
1479 fn prop_test_ensure_nul_terminated_from_buf() {
1480 run_arbitrary::<Vec<u8>>(|bytes| {
1481 let buf = Buf::from(bytes);
1482 let mut inner: Vec<u8> = buf.into();
1483 assert!(is_nul_terminated(&mut inner));
1484 });
1485 }
1486
1487 #[test]
1488 fn prop_test_ensure_nul_terminated_after_clone() {
1489 run_arbitrary::<Vec<u8>>(|bytes| {
1490 let buf = Buf::from(bytes);
1491 let buf_clone = buf.clone();
1492 let mut inner = buf_clone.into_inner();
1493 assert!(is_nul_terminated(&mut inner));
1494 });
1495 }
1496
1497 #[test]
1498 fn prop_test_ensure_nul_terminated_from_iterator() {
1499 run_arbitrary::<Vec<u8>>(|bytes| {
1500 let buf = Buf::from_iter(bytes);
1501 let mut inner = buf.into_inner();
1502 assert!(is_nul_terminated(&mut inner));
1503 });
1504 }
1505
1506 #[test]
1507 fn prop_test_ensure_nul_terminated_collect() {
1508 run_arbitrary::<Vec<u8>>(|bytes| {
1509 let buf: Buf = bytes.into_iter().collect();
1510 let mut inner = buf.into_inner();
1511 assert!(is_nul_terminated(&mut inner));
1512 });
1513 }
1514
1515 #[test]
1516 fn prop_test_ensure_nul_terminated_after_extend() {
1517 run_arbitrary::<(Vec<u8>, Vec<u8>)>(|(bytes, extension)| {
1518 let mut buf = Buf::from(bytes);
1519 buf.extend(extension);
1520 let mut inner = buf.into_inner();
1521 assert!(is_nul_terminated(&mut inner));
1522 });
1523 }
1524
1525 #[test]
1526 fn prop_test_ensure_nul_terminated_from_raw_parts() {
1527 run_arbitrary::<Vec<u8>>(|bytes| {
1528 let raw_parts = RawParts::from_vec(bytes);
1529 let buf = unsafe { Buf::from_raw_parts(raw_parts) };
1530 let mut inner = buf.into_inner();
1531 assert!(is_nul_terminated(&mut inner));
1532 });
1533 }
1534
1535 #[test]
1536 fn prop_test_ensure_nul_terminated_raw_parts_round_trip() {
1537 run_arbitrary::<Vec<u8>>(|bytes| {
1538 let buf = Buf::from(bytes);
1539 let raw_parts = buf.into_raw_parts();
1540 let buf = unsafe { Buf::from_raw_parts(raw_parts) };
1541 let mut inner = buf.into_inner();
1542 assert!(is_nul_terminated(&mut inner));
1543 });
1544 }
1545
1546 #[test]
1547 fn prop_test_ensure_nul_terminated_reserve() {
1548 run_arbitrary::<Vec<u8>>(|bytes| {
1549 let additional = [0_usize, 1, 2, 3, 4, 19, 280, 499, 1024, 4096, 4099];
1550 for reserve in additional {
1551 let mut buf = Buf::from(bytes.clone());
1552 buf.reserve(reserve);
1553 let mut inner = buf.into_inner();
1554 assert!(is_nul_terminated(&mut inner));
1555 }
1556 });
1557 }
1558
1559 #[test]
1560 fn prop_test_ensure_nul_terminated_reserve_exact() {
1561 run_arbitrary::<Vec<u8>>(|bytes| {
1562 let additional = [0_usize, 1, 2, 3, 4, 19, 280, 499, 1024, 4096, 4099];
1563 for reserve in additional {
1564 let mut buf = Buf::from(bytes.clone());
1565 buf.reserve_exact(reserve);
1566 let mut inner = buf.into_inner();
1567 assert!(is_nul_terminated(&mut inner));
1568 }
1569 });
1570 }
1571
1572 #[test]
1573 fn prop_test_ensure_nul_terminated_try_reserve() {
1574 run_arbitrary::<Vec<u8>>(|bytes| {
1575 let additional = [0_usize, 1, 2, 3, 4, 19, 280, 499, 1024, 4096, 4099];
1576 for reserve in additional {
1577 let mut buf = Buf::from(bytes.clone());
1578 buf.try_reserve(reserve).unwrap();
1579 let mut inner = buf.into_inner();
1580 assert!(is_nul_terminated(&mut inner));
1581 }
1582 });
1583 }
1584
1585 #[test]
1586 fn prop_test_ensure_nul_terminated_try_reserve_exact() {
1587 run_arbitrary::<Vec<u8>>(|bytes| {
1588 let additional = [0_usize, 1, 2, 3, 4, 19, 280, 499, 1024, 4096, 4099];
1589 for reserve in additional {
1590 let mut buf = Buf::from(bytes.clone());
1591 buf.try_reserve_exact(reserve).unwrap();
1592 let mut inner = buf.into_inner();
1593 assert!(is_nul_terminated(&mut inner));
1594 }
1595 });
1596 }
1597
1598 #[test]
1599 fn prop_test_ensure_nul_terminated_shrink_to_fit() {
1600 run_arbitrary::<Vec<u8>>(|bytes| {
1601 let mut buf = Buf::from(bytes);
1602 buf.shrink_to_fit();
1603 let mut inner = buf.into_inner();
1604 assert!(is_nul_terminated(&mut inner));
1605 });
1606 }
1607
1608 #[test]
1609 fn prop_test_ensure_nul_terminated_shrink_to() {
1610 run_arbitrary::<(Vec<u8>, usize)>(|(bytes, shrink_to)| {
1611 let mut buf = Buf::from(bytes);
1612 buf.shrink_to(shrink_to);
1613 let mut inner = buf.into_inner();
1614 assert!(is_nul_terminated(&mut inner));
1615 });
1616 }
1617
1618 #[test]
1619 fn prop_test_ensure_nul_terminated_truncate() {
1620 run_arbitrary::<(Vec<u8>, usize)>(|(bytes, truncate_to)| {
1621 let mut buf = Buf::from(bytes);
1622 buf.truncate(truncate_to);
1623 let mut inner = buf.into_inner();
1624 assert!(is_nul_terminated(&mut inner));
1625 });
1626 }
1627
1628 #[test]
1629 fn prop_test_ensure_nul_terminated_set_len() {
1630 run_arbitrary::<Vec<u8>>(|bytes| {
1631 let mut buf = Buf::from(bytes);
1632 unsafe {
1633 buf.set_len(0);
1634 }
1635 let mut inner = buf.into_inner();
1636 assert!(is_nul_terminated(&mut inner));
1637 });
1638 }
1639
1640 #[test]
1641 fn prop_test_ensure_nul_terminated_insert_first() {
1642 run_arbitrary::<Vec<u8>>(|bytes| {
1643 if bytes.is_empty() {
1644 return;
1645 }
1646 let mut buf = Buf::from(bytes);
1647 buf.insert(0, u8::MAX);
1648 let mut inner = buf.into_inner();
1649 assert!(is_nul_terminated(&mut inner));
1650 });
1651 }
1652
1653 #[test]
1654 fn prop_test_ensure_nul_terminated_insert_past_end() {
1655 run_arbitrary::<Vec<u8>>(|bytes| {
1656 let mut buf = Buf::from(bytes);
1657 buf.insert(buf.len(), u8::MAX);
1658 let mut inner = buf.into_inner();
1659 assert!(is_nul_terminated(&mut inner));
1660 });
1661 }
1662
1663 #[test]
1664 fn prop_test_ensure_nul_terminated_insert_last() {
1665 run_arbitrary::<Vec<u8>>(|bytes| {
1666 if bytes.is_empty() {
1667 return;
1668 }
1669 let mut buf = Buf::from(bytes);
1670 buf.insert(buf.len() - 1, u8::MAX);
1671 let mut inner = buf.into_inner();
1672 assert!(is_nul_terminated(&mut inner));
1673 });
1674 }
1675
1676 #[test]
1677 fn prop_test_ensure_nul_terminated_insert_interior() {
1678 run_arbitrary::<Vec<u8>>(|bytes| {
1679 if bytes.len() < 2 {
1680 return;
1681 }
1682 let mut buf = Buf::from(bytes);
1683 buf.insert(buf.len() - 2, u8::MAX);
1684 let mut inner = buf.into_inner();
1685 assert!(is_nul_terminated(&mut inner));
1686 });
1687 }
1688
1689 #[test]
1690 fn prop_test_ensure_nul_terminated_remove_first() {
1691 run_arbitrary::<Vec<u8>>(|bytes| {
1692 if bytes.is_empty() {
1693 return;
1694 }
1695 let mut buf = Buf::from(bytes);
1696 buf.remove(0);
1697 let mut inner = buf.into_inner();
1698 assert!(is_nul_terminated(&mut inner));
1699 });
1700 }
1701
1702 #[test]
1703 fn prop_test_ensure_nul_terminated_remove_last() {
1704 run_arbitrary::<Vec<u8>>(|bytes| {
1705 if bytes.is_empty() {
1706 return;
1707 }
1708 let mut buf = Buf::from(bytes);
1709 buf.remove(buf.len() - 1);
1710 let mut inner = buf.into_inner();
1711 assert!(is_nul_terminated(&mut inner));
1712 });
1713 }
1714
1715 #[test]
1716 fn prop_test_ensure_nul_terminated_remove_interior() {
1717 run_arbitrary::<Vec<u8>>(|bytes| {
1718 if bytes.len() < 2 {
1719 return;
1720 }
1721 let mut buf = Buf::from(bytes);
1722 buf.remove(buf.len() - 2);
1723 let mut inner = buf.into_inner();
1724 assert!(is_nul_terminated(&mut inner));
1725 });
1726 }
1727
1728 #[test]
1729 fn prop_test_ensure_nul_terminated_retain_all() {
1730 run_arbitrary::<Vec<u8>>(|bytes| {
1731 let mut buf = Buf::from(bytes);
1732 buf.retain(|_| true);
1733 let mut inner = buf.into_inner();
1734 assert!(is_nul_terminated(&mut inner));
1735 });
1736 }
1737
1738 #[test]
1739 fn prop_test_ensure_nul_terminated_retain_none() {
1740 run_arbitrary::<Vec<u8>>(|bytes| {
1741 let mut buf = Buf::from(bytes);
1742 buf.retain(|_| false);
1743 let mut inner = buf.into_inner();
1744 assert!(is_nul_terminated(&mut inner));
1745 });
1746 }
1747
1748 #[test]
1749 fn prop_test_ensure_nul_terminated_retain_some() {
1750 run_arbitrary::<Vec<u8>>(|bytes| {
1751 let mut idx = 0;
1752 let mut buf = Buf::from(bytes);
1753 buf.retain(|_| {
1754 idx += 1;
1755 idx % 2 == 0
1756 });
1757 let mut inner = buf.into_inner();
1758 assert!(is_nul_terminated(&mut inner));
1759 });
1760 }
1761
1762 #[test]
1763 fn prop_test_ensure_nul_terminated_pop() {
1764 run_arbitrary::<Vec<u8>>(|bytes| {
1765 if bytes.is_empty() {
1766 return;
1767 }
1768 let mut buf = Buf::from(bytes);
1769 buf.pop_byte();
1770 let mut inner = buf.into_inner();
1771 assert!(is_nul_terminated(&mut inner));
1772 });
1773 }
1774
1775 #[test]
1776 fn prop_test_ensure_nul_terminated_clear() {
1777 run_arbitrary::<Vec<u8>>(|bytes| {
1778 let mut buf = Buf::from(bytes);
1779 buf.clear();
1780 let mut inner = buf.into_inner();
1781 assert!(is_nul_terminated(&mut inner));
1782 });
1783 }
1784
1785 #[test]
1786 fn prop_test_ensure_nul_terminated_resize() {
1787 run_arbitrary::<Vec<u8>>(|bytes| {
1788 let lengths = [0_usize, 1, 2, 3, 4, 19, 280, 499, 1024, 4096, 4099];
1789 for len in lengths {
1790 let mut buf = Buf::from(bytes.clone());
1791 buf.resize(len, u8::MAX);
1792 let mut inner = buf.into_inner();
1793 assert!(is_nul_terminated(&mut inner));
1794 }
1795 });
1796 }
1797
1798 #[test]
1799 fn prop_test_ensure_nul_terminated_extend_from_slice() {
1800 run_arbitrary::<(Vec<u8>, Vec<u8>)>(|(bytes, other)| {
1801 let mut buf = Buf::from(bytes);
1802 buf.extend_from_slice(&other);
1803 let mut inner = buf.into_inner();
1804 assert!(is_nul_terminated(&mut inner));
1805 });
1806 }
1807
1808 #[test]
1809 fn prop_test_ensure_nul_terminated_push_byte() {
1810 run_arbitrary::<(Vec<u8>, u8)>(|(bytes, pushed)| {
1811 let mut buf = Buf::from(bytes);
1812 buf.push_byte(pushed);
1813 let mut inner = buf.into_inner();
1814 assert!(is_nul_terminated(&mut inner));
1815 });
1816 }
1817
1818 #[test]
1819 fn prop_test_ensure_nul_terminated_push_char() {
1820 run_arbitrary::<(Vec<u8>, char)>(|(bytes, pushed)| {
1821 let mut buf = Buf::from(bytes);
1822 buf.push_char(pushed);
1823 let mut inner = buf.into_inner();
1824 assert!(is_nul_terminated(&mut inner));
1825 });
1826 }
1827
1828 #[test]
1829 fn prop_test_ensure_nul_terminated_push_str() {
1830 run_arbitrary::<(Vec<u8>, String)>(|(bytes, pushed)| {
1831 let mut buf = Buf::from(bytes);
1832 buf.push_str(pushed);
1833 let mut inner = buf.into_inner();
1834 assert!(is_nul_terminated(&mut inner));
1835 });
1836 }
1837
1838 // std::io-related tests (enabled only with the "std" feature)
1839
1840 #[test]
1841 #[cfg(feature = "std")]
1842 fn prop_test_ensure_nul_terminated_write() {
1843 run_arbitrary::<(Vec<u8>, Vec<u8>)>(|(bytes, data)| {
1844 use std::io::Write;
1845 let mut buf = Buf::from(bytes);
1846 let _written = buf.write(&data).unwrap();
1847 let mut inner = buf.into_inner();
1848 assert!(is_nul_terminated(&mut inner));
1849 });
1850 }
1851
1852 #[test]
1853 #[cfg(feature = "std")]
1854 fn prop_test_ensure_nul_terminated_flush() {
1855 run_arbitrary::<(Vec<u8>, Vec<u8>)>(|(bytes, data)| {
1856 use std::io::Write;
1857 let mut buf = Buf::from(bytes);
1858 buf.write_all(&data).unwrap();
1859 buf.flush().unwrap();
1860 let mut inner = buf.into_inner();
1861 assert!(is_nul_terminated(&mut inner));
1862 });
1863 }
1864
1865 #[test]
1866 #[cfg(feature = "std")]
1867 fn prop_test_ensure_nul_terminated_write_vectored() {
1868 run_arbitrary::<(Vec<u8>, Vec<u8>, Vec<u8>)>(|(bytes, data1, data2)| {
1869 use std::io::{IoSlice, Write};
1870 let mut buf = Buf::from(bytes);
1871 let _written = buf
1872 .write_vectored(&[IoSlice::new(&data1), IoSlice::new(&data2)])
1873 .unwrap();
1874 let mut inner = buf.into_inner();
1875 assert!(is_nul_terminated(&mut inner));
1876 });
1877 }
1878
1879 #[test]
1880 #[cfg(feature = "std")]
1881 fn prop_test_ensure_nul_terminated_write_all() {
1882 run_arbitrary::<(Vec<u8>, Vec<u8>)>(|(bytes, data)| {
1883 use std::io::Write;
1884 let mut buf = Buf::from(bytes);
1885 buf.write_all(&data).unwrap();
1886 let mut inner = buf.into_inner();
1887 assert!(is_nul_terminated(&mut inner));
1888 });
1889 }
1890
1891 #[test]
1892 #[cfg(feature = "std")]
1893 fn prop_test_ensure_nul_terminated_write_fmt() {
1894 run_arbitrary::<(Vec<u8>, String)>(|(bytes, data)| {
1895 use std::io::Write;
1896 let mut buf = Buf::from(bytes);
1897 buf.write_fmt(format_args!("{data}")).unwrap();
1898 let mut inner = buf.into_inner();
1899 assert!(is_nul_terminated(&mut inner));
1900 });
1901 }
1902}