• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vortex-data / vortex / 16331938722

16 Jul 2025 10:49PM UTC coverage: 80.702% (-0.9%) from 81.557%
16331938722

push

github

web-flow
feat: build with stable rust (#3881)

120 of 173 new or added lines in 28 files covered. (69.36%)

174 existing lines in 102 files now uncovered.

41861 of 51871 relevant lines covered (80.7%)

157487.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.13
/vortex-buffer/src/buffer.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::any::type_name;
5
use std::cmp::Ordering;
6
use std::collections::Bound;
7
use std::fmt::{Debug, Formatter};
8
use std::hash::{Hash, Hasher};
9
use std::ops::{Deref, RangeBounds};
10

11
use bytes::{Buf, Bytes};
12
use vortex_error::{VortexExpect, vortex_panic};
13

14
use crate::debug::TruncatedDebug;
15
use crate::{Alignment, BufferMut, ByteBuffer};
16

17
/// An immutable buffer of items of `T`.
18
#[derive(Clone)]
19
pub struct Buffer<T> {
20
    pub(crate) bytes: Bytes,
21
    pub(crate) length: usize,
22
    pub(crate) alignment: Alignment,
23
    pub(crate) _marker: std::marker::PhantomData<T>,
24
}
25

26
impl<T> PartialEq for Buffer<T> {
27
    fn eq(&self, other: &Self) -> bool {
5,464✔
28
        self.bytes == other.bytes
5,464✔
29
    }
5,464✔
30
}
31

32
impl<T> Eq for Buffer<T> {}
33

34
impl<T> Ord for Buffer<T> {
35
    fn cmp(&self, other: &Self) -> Ordering {
5,962✔
36
        self.bytes.cmp(&other.bytes)
5,962✔
37
    }
5,962✔
38
}
39

40
impl<T> PartialOrd for Buffer<T> {
41
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
×
42
        Some(self.bytes.cmp(&other.bytes))
×
43
    }
×
44
}
45

46
impl<T> Hash for Buffer<T> {
47
    fn hash<H: Hasher>(&self, state: &mut H) {
8,398✔
48
        self.bytes.as_ref().hash(state)
8,398✔
49
    }
8,398✔
50
}
51

52
impl<T> Buffer<T> {
53
    /// Returns a new `Buffer<T>` copied from the provided `Vec<T>`, `&[T]`, etc.
54
    ///
55
    /// Due to our underlying usage of `bytes::Bytes`, we are unable to take zero-copy ownership
56
    /// of the provided `Vec<T>` while maintaining the ability to convert it back into a mutable
57
    /// buffer. We could fix this by forking `Bytes`, or in many other complex ways, but for now
58
    /// callers should prefer to construct `Buffer<T>` from a `BufferMut<T>`.
59
    pub fn copy_from(values: impl AsRef<[T]>) -> Self {
12,363✔
60
        BufferMut::copy_from(values).freeze()
12,363✔
61
    }
12,363✔
62

63
    /// Returns a new `Buffer<T>` copied from the provided slice and with the requested alignment.
64
    pub fn copy_from_aligned(values: impl AsRef<[T]>, alignment: Alignment) -> Self {
4,096✔
65
        BufferMut::copy_from_aligned(values, alignment).freeze()
4,096✔
66
    }
4,096✔
67

68
    /// Create a new zeroed `Buffer` with the given value.
69
    pub fn zeroed(len: usize) -> Self {
12,109✔
70
        Self::zeroed_aligned(len, Alignment::of::<T>())
12,109✔
71
    }
12,109✔
72

73
    /// Create a new zeroed `Buffer` with the given value.
74
    pub fn zeroed_aligned(len: usize, alignment: Alignment) -> Self {
19,092✔
75
        BufferMut::zeroed_aligned(len, alignment).freeze()
19,092✔
76
    }
19,092✔
77

78
    /// Create a new empty `ByteBuffer` with the provided alignment.
79
    pub fn empty() -> Self {
2,004✔
80
        BufferMut::empty().freeze()
2,004✔
81
    }
2,004✔
82

83
    /// Create a new empty `ByteBuffer` with the provided alignment.
84
    pub fn empty_aligned(alignment: Alignment) -> Self {
1,171✔
85
        BufferMut::empty_aligned(alignment).freeze()
1,171✔
86
    }
1,171✔
87

88
    /// Create a new full `ByteBuffer` with the given value.
89
    pub fn full(item: T, len: usize) -> Self
8,113✔
90
    where
8,113✔
91
        T: Copy,
8,113✔
92
    {
93
        BufferMut::full(item, len).freeze()
8,113✔
94
    }
8,113✔
95

96
    /// Create a `Buffer<T>` zero-copy from a `ByteBuffer`.
97
    ///
98
    /// ## Panics
99
    ///
100
    /// Panics if the buffer is not aligned to the size of `T`, or the length is not a multiple of
101
    /// the size of `T`.
102
    pub fn from_byte_buffer(buffer: ByteBuffer) -> Self {
150,033✔
103
        // TODO(ngates): should this preserve the current alignment of the buffer?
104
        Self::from_byte_buffer_aligned(buffer, Alignment::of::<T>())
150,033✔
105
    }
150,033✔
106

107
    /// Create a `Buffer<T>` zero-copy from a `ByteBuffer`.
108
    ///
109
    /// ## Panics
110
    ///
111
    /// Panics if the buffer is not aligned to the given alignment, if the length is not a multiple
112
    /// of the size of `T`, or if the given alignment is not aligned to that of `T`.
113
    pub fn from_byte_buffer_aligned(buffer: ByteBuffer, alignment: Alignment) -> Self {
150,033✔
114
        Self::from_bytes_aligned(buffer.into_inner(), alignment)
150,033✔
115
    }
150,033✔
116

117
    /// Create a `Buffer<T>` zero-copy from a `Bytes`.
118
    ///
119
    /// ## Panics
120
    ///
121
    /// Panics if the buffer is not aligned to the size of `T`, or the length is not a multiple of
122
    /// the size of `T`.
123
    pub fn from_bytes_aligned(bytes: Bytes, alignment: Alignment) -> Self {
150,033✔
124
        if !alignment.is_aligned_to(Alignment::of::<T>()) {
150,033✔
125
            vortex_panic!(
×
126
                "Alignment {} must be compatible with the scalar type's alignment {}",
×
127
                alignment,
128
                Alignment::of::<T>(),
×
129
            );
130
        }
150,033✔
131
        if bytes.as_ptr().align_offset(*alignment) != 0 {
150,033✔
132
            vortex_panic!(
×
133
                "Bytes alignment must align to the requested alignment {}",
×
134
                alignment,
135
            );
136
        }
150,033✔
137
        if bytes.len() % size_of::<T>() != 0 {
150,033✔
138
            vortex_panic!(
×
139
                "Bytes length {} must be a multiple of the scalar type's size {}",
×
140
                bytes.len(),
×
141
                size_of::<T>()
142
            );
143
        }
150,033✔
144
        let length = bytes.len() / size_of::<T>();
150,033✔
145
        Self {
150,033✔
146
            bytes,
150,033✔
147
            length,
150,033✔
148
            alignment,
150,033✔
149
            _marker: Default::default(),
150,033✔
150
        }
150,033✔
151
    }
150,033✔
152

153
    /// Returns the length of the buffer in elements of type T.
154
    #[inline(always)]
155
    pub fn len(&self) -> usize {
57,292,760✔
156
        self.length
57,292,760✔
157
    }
57,292,760✔
158

159
    /// Returns whether the buffer is empty.
160
    #[inline(always)]
161
    pub fn is_empty(&self) -> bool {
441✔
162
        self.length == 0
441✔
163
    }
441✔
164

165
    /// Returns the alignment of the buffer.
166
    #[inline(always)]
167
    pub fn alignment(&self) -> Alignment {
87,274✔
168
        self.alignment
87,274✔
169
    }
87,274✔
170

171
    /// Returns a slice over the buffer of elements of type T.
172
    #[inline(always)]
173
    pub fn as_slice(&self) -> &[T] {
61,691,561✔
174
        let raw_slice = self.bytes.as_ref();
61,691,561✔
175
        // SAFETY: alignment of Buffer is checked on construction
176
        unsafe { std::slice::from_raw_parts(raw_slice.as_ptr().cast(), self.length) }
61,691,561✔
177
    }
61,691,561✔
178

179
    /// Returns an iterator over the buffer of elements of type T.
180
    pub fn iter(&self) -> Iter<'_, T> {
39,224✔
181
        Iter {
39,224✔
182
            inner: self.as_slice().iter(),
39,224✔
183
        }
39,224✔
184
    }
39,224✔
185

186
    /// Returns a slice of self for the provided range.
187
    ///
188
    /// # Panics
189
    ///
190
    /// Requires that `begin <= end` and `end <= self.len()`.
191
    /// Also requires that both `begin` and `end` are aligned to the buffer's required alignment.
192
    #[inline(always)]
193
    pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
122,125✔
194
        self.slice_with_alignment(range, self.alignment)
122,125✔
195
    }
122,125✔
196

197
    /// Returns a slice of self for the provided range, with no guarantees about the resulting
198
    /// alignment.
199
    ///
200
    /// # Panics
201
    ///
202
    /// Requires that `begin <= end` and `end <= self.len()`.
203
    #[inline(always)]
204
    pub fn slice_unaligned(&self, range: impl RangeBounds<usize>) -> Self {
1✔
205
        self.slice_with_alignment(range, Alignment::of::<u8>())
1✔
206
    }
1✔
207

208
    /// Returns a slice of self for the provided range, ensuring the resulting slice has the
209
    /// given alignment.
210
    ///
211
    /// # Panics
212
    ///
213
    /// Requires that `begin <= end` and `end <= self.len()`.
214
    /// Also requires that both `begin` and `end` are aligned to the given alignment.
215
    pub fn slice_with_alignment(
158,518✔
216
        &self,
158,518✔
217
        range: impl RangeBounds<usize>,
158,518✔
218
        alignment: Alignment,
158,518✔
219
    ) -> Self {
158,518✔
220
        let len = self.len();
158,518✔
221
        let begin = match range.start_bound() {
158,518✔
222
            Bound::Included(&n) => n,
158,518✔
223
            Bound::Excluded(&n) => n.checked_add(1).vortex_expect("out of range"),
×
224
            Bound::Unbounded => 0,
×
225
        };
226
        let end = match range.end_bound() {
158,518✔
227
            Bound::Included(&n) => n.checked_add(1).vortex_expect("out of range"),
1✔
228
            Bound::Excluded(&n) => n,
158,517✔
229
            Bound::Unbounded => len,
×
230
        };
231

232
        if begin > end {
158,518✔
233
            vortex_panic!(
×
234
                "range start must not be greater than end: {:?} <= {:?}",
×
235
                begin,
236
                end
237
            );
238
        }
158,518✔
239
        if end > len {
158,518✔
240
            vortex_panic!("range end out of bounds: {:?} <= {:?}", end, len);
×
241
        }
158,518✔
242

243
        if end == begin {
158,518✔
244
            // We prefer to return a new empty buffer instead of sharing this one and creating a
245
            // strong reference just to hold an empty slice.
246
            return Self::empty_aligned(alignment);
1,171✔
247
        }
157,347✔
248

249
        let begin_byte = begin * size_of::<T>();
157,347✔
250
        let end_byte = end * size_of::<T>();
157,347✔
251

252
        if !begin_byte.is_multiple_of(*alignment) {
157,347✔
253
            vortex_panic!("range start must be aligned to {:?}", alignment);
1✔
254
        }
157,346✔
255
        if !end_byte.is_multiple_of(*alignment) {
157,346✔
256
            vortex_panic!("range end must be aligned to {:?}", alignment);
×
257
        }
157,346✔
258
        if !alignment.is_aligned_to(Alignment::of::<T>()) {
157,346✔
259
            vortex_panic!("Slice alignment must at least align to type T")
×
260
        }
157,346✔
261

262
        Self {
157,346✔
263
            bytes: self.bytes.slice(begin_byte..end_byte),
157,346✔
264
            length: end - begin,
157,346✔
265
            alignment,
157,346✔
266
            _marker: Default::default(),
157,346✔
267
        }
157,346✔
268
    }
158,517✔
269

270
    /// Returns a slice of self that is equivalent to the given subset.
271
    ///
272
    /// When processing the buffer you will often end up with &\[T\] that is a subset
273
    /// of the underlying buffer. This function turns the slice into a slice of the buffer
274
    /// it has been taken from.
275
    ///
276
    /// # Panics:
277
    /// Requires that the given sub slice is in fact contained within the Bytes buffer; otherwise this function will panic.
278
    #[inline(always)]
279
    pub fn slice_ref(&self, subset: &[T]) -> Self {
1,321✔
280
        self.slice_ref_with_alignment(subset, Alignment::of::<T>())
1,321✔
281
    }
1,321✔
282

283
    /// Returns a slice of self that is equivalent to the given subset.
284
    ///
285
    /// When processing the buffer you will often end up with &\[T\] that is a subset
286
    /// of the underlying buffer. This function turns the slice into a slice of the buffer
287
    /// it has been taken from.
288
    ///
289
    /// # Panics:
290
    /// Requires that the given sub slice is in fact contained within the Bytes buffer; otherwise this function will panic.
291
    /// Also requires that the given alignment aligns to the type of slice and is smaller or equal to the buffers alignment
292
    pub fn slice_ref_with_alignment(&self, subset: &[T], alignment: Alignment) -> Self {
1,321✔
293
        if !alignment.is_aligned_to(Alignment::of::<T>()) {
1,321✔
294
            vortex_panic!("slice_ref alignment must at least align to type T")
×
295
        }
1,321✔
296

297
        if !self.alignment.is_aligned_to(alignment) {
1,321✔
298
            vortex_panic!("slice_ref subset alignment must at least align to the buffer alignment")
×
299
        }
1,321✔
300

301
        if subset.as_ptr().align_offset(*alignment) != 0 {
1,321✔
302
            vortex_panic!("slice_ref subset must be aligned to {:?}", alignment);
×
303
        }
1,321✔
304

305
        let subset_u8 =
1,321✔
306
            unsafe { std::slice::from_raw_parts(subset.as_ptr().cast(), size_of_val(subset)) };
1,321✔
307

308
        Self {
1,321✔
309
            bytes: self.bytes.slice_ref(subset_u8),
1,321✔
310
            length: subset.len(),
1,321✔
311
            alignment,
1,321✔
312
            _marker: Default::default(),
1,321✔
313
        }
1,321✔
314
    }
1,321✔
315

316
    /// Returns the underlying aligned buffer.
317
    pub fn inner(&self) -> &Bytes {
×
318
        debug_assert_eq!(
×
319
            self.length * size_of::<T>(),
×
320
            self.bytes.len(),
×
321
            "Own length has to be the same as the underlying bytes length"
×
322
        );
323
        &self.bytes
×
324
    }
×
325

326
    /// Returns the underlying aligned buffer.
327
    pub fn into_inner(self) -> Bytes {
215,735✔
328
        debug_assert_eq!(
215,735✔
329
            self.length * size_of::<T>(),
215,735✔
330
            self.bytes.len(),
215,735✔
331
            "Own length has to be the same as the underlying bytes length"
×
332
        );
333
        self.bytes
215,735✔
334
    }
215,735✔
335

336
    /// Return the ByteBuffer for this `Buffer<T>`.
337
    pub fn into_byte_buffer(self) -> ByteBuffer {
284,646✔
338
        ByteBuffer {
284,646✔
339
            bytes: self.bytes,
284,646✔
340
            length: self.length * size_of::<T>(),
284,646✔
341
            alignment: self.alignment,
284,646✔
342
            _marker: Default::default(),
284,646✔
343
        }
284,646✔
344
    }
284,646✔
345

346
    /// Convert self into `BufferMut<T>`, copying if there are multiple strong references.
347
    pub fn into_mut(self) -> BufferMut<T> {
190✔
348
        self.try_into_mut()
190✔
349
            .unwrap_or_else(|buffer| BufferMut::<T>::copy_from(&buffer))
190✔
350
    }
190✔
351

352
    /// Try to convert self into `BufferMut<T>` if there is only a single strong reference.
353
    pub fn try_into_mut(self) -> Result<BufferMut<T>, Self> {
8,435✔
354
        self.bytes
8,435✔
355
            .try_into_mut()
8,435✔
356
            .map(|bytes| BufferMut {
8,435✔
357
                bytes,
4,442✔
358
                length: self.length,
4,442✔
359
                alignment: self.alignment,
4,442✔
360
                _marker: Default::default(),
4,442✔
361
            })
4,442✔
362
            .map_err(|bytes| Self {
8,435✔
363
                bytes,
3,993✔
364
                length: self.length,
3,993✔
365
                alignment: self.alignment,
3,993✔
366
                _marker: Default::default(),
3,993✔
367
            })
3,993✔
368
    }
8,435✔
369

370
    /// Returns whether a `Buffer<T>` is aligned to the given alignment.
371
    pub fn is_aligned(&self, alignment: Alignment) -> bool {
6,695✔
372
        self.bytes.as_ptr().align_offset(*alignment) == 0
6,695✔
373
    }
6,695✔
374

375
    /// Return a `Buffer<T>` with the given alignment. Where possible, this will be zero-copy.
376
    pub fn aligned(mut self, alignment: Alignment) -> Self {
71,770✔
377
        if self.as_ptr().align_offset(*alignment) == 0 {
71,770✔
378
            self.alignment = alignment;
69,658✔
379
            self
69,658✔
380
        } else {
381
            #[cfg(feature = "warn-copy")]
382
            {
383
                let bt = std::backtrace::Backtrace::capture();
1,262✔
384
                log::warn!(
1,262✔
385
                    "Buffer is not aligned to requested alignment {alignment}, copying: {bt}"
386
                )
387
            }
388
            Self::copy_from_aligned(self, alignment)
2,112✔
389
        }
390
    }
71,770✔
391

392
    /// Return a `Buffer<T>` with the given alignment. Panics if the buffer is not aligned.
393
    pub fn ensure_aligned(mut self, alignment: Alignment) -> Self {
×
394
        if self.as_ptr().align_offset(*alignment) == 0 {
×
395
            self.alignment = alignment;
×
396
            self
×
397
        } else {
398
            vortex_panic!("Buffer is not aligned to requested alignment {}", alignment)
×
399
        }
400
    }
×
401
}
402

403
/// An iterator over Buffer elements.
404
///
405
/// This is an analog to the `std::slice::Iter` type.
406
pub struct Iter<'a, T> {
407
    inner: std::slice::Iter<'a, T>,
408
}
409

410
impl<'a, T> Iterator for Iter<'a, T> {
411
    type Item = &'a T;
412

413
    fn next(&mut self) -> Option<Self::Item> {
58,896,859✔
414
        self.inner.next()
58,896,859✔
415
    }
58,896,859✔
416

417
    fn size_hint(&self) -> (usize, Option<usize>) {
8,563✔
418
        self.inner.size_hint()
8,563✔
419
    }
8,563✔
420

NEW
421
    fn count(self) -> usize {
×
NEW
422
        self.inner.count()
×
NEW
423
    }
×
424

NEW
425
    fn last(self) -> Option<Self::Item> {
×
NEW
426
        self.inner.last()
×
NEW
427
    }
×
428

NEW
429
    fn nth(&mut self, n: usize) -> Option<Self::Item> {
×
NEW
430
        self.inner.nth(n)
×
NEW
431
    }
×
432
}
433

434
impl<T> ExactSizeIterator for Iter<'_, T> {
NEW
435
    fn len(&self) -> usize {
×
NEW
436
        self.inner.len()
×
NEW
437
    }
×
438
}
439

440
impl<T: Debug> Debug for Buffer<T> {
441
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
×
442
        f.debug_struct(&format!("Buffer<{}>", type_name::<T>()))
×
443
            .field("length", &self.length)
×
444
            .field("alignment", &self.alignment)
×
445
            .field("as_slice", &TruncatedDebug(self.as_slice()))
×
446
            .finish()
×
447
    }
×
448
}
449

450
impl<T> Deref for Buffer<T> {
451
    type Target = [T];
452

453
    fn deref(&self) -> &Self::Target {
18,458,563✔
454
        self.as_slice()
18,458,563✔
455
    }
18,458,563✔
456
}
457

458
impl<T> AsRef<[T]> for Buffer<T> {
459
    fn as_ref(&self) -> &[T] {
44,316✔
460
        self.as_slice()
44,316✔
461
    }
44,316✔
462
}
463

464
impl<T> FromIterator<T> for Buffer<T> {
465
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
11,499✔
466
        BufferMut::from_iter(iter).freeze()
11,499✔
467
    }
11,499✔
468
}
469

470
/// Only for `Buffer<u8>` can we zero-copy from a `Vec<u8>` since we can use a 1-byte alignment.
471
impl From<Vec<u8>> for ByteBuffer {
472
    fn from(value: Vec<u8>) -> Self {
43,223✔
473
        Self::from(Bytes::from(value))
43,223✔
474
    }
43,223✔
475
}
476

477
/// Only for `Buffer<u8>` can we zero-copy from a `Bytes` since we can use a 1-byte alignment.
478
impl From<Bytes> for ByteBuffer {
479
    fn from(bytes: Bytes) -> Self {
43,943✔
480
        let length = bytes.len();
43,943✔
481
        Self {
43,943✔
482
            bytes,
43,943✔
483
            length,
43,943✔
484
            alignment: Alignment::of::<u8>(),
43,943✔
485
            _marker: Default::default(),
43,943✔
486
        }
43,943✔
487
    }
43,943✔
488
}
489

490
impl Buf for ByteBuffer {
491
    fn remaining(&self) -> usize {
2✔
492
        self.len()
2✔
493
    }
2✔
494

495
    fn chunk(&self) -> &[u8] {
2✔
496
        self.as_slice()
2✔
497
    }
2✔
498

499
    fn advance(&mut self, cnt: usize) {
1✔
500
        if !cnt.is_multiple_of(*self.alignment) {
1✔
501
            vortex_panic!(
×
502
                "Cannot advance buffer by {} items, resulting alignment is not {}",
×
503
                cnt,
504
                self.alignment
505
            );
506
        }
1✔
507
        self.bytes.advance(cnt);
1✔
508
        self.length -= cnt;
1✔
509
    }
1✔
510
}
511

512
/// Owned iterator over a [`Buffer`].
513
pub struct BufferIterator<T> {
514
    buffer: Buffer<T>,
515
    index: usize,
516
}
517

518
impl<T: Copy> Iterator for BufferIterator<T> {
519
    type Item = T;
520

521
    fn next(&mut self) -> Option<Self::Item> {
43,082,404✔
522
        (self.index < self.buffer.len()).then(move || {
43,082,404✔
523
            let value = self.buffer.as_slice()[self.index];
43,068,010✔
524
            self.index += 1;
43,068,010✔
525
            value
43,068,010✔
526
        })
43,068,010✔
527
    }
43,082,404✔
528

529
    fn size_hint(&self) -> (usize, Option<usize>) {
7,060✔
530
        let remaining = self.buffer.len() - self.index;
7,060✔
531
        (remaining, Some(remaining))
7,060✔
532
    }
7,060✔
533
}
534

535
impl<T: Copy> IntoIterator for Buffer<T> {
536
    type Item = T;
537
    type IntoIter = BufferIterator<T>;
538

539
    fn into_iter(self) -> Self::IntoIter {
7,880✔
540
        BufferIterator {
7,880✔
541
            buffer: self,
7,880✔
542
            index: 0,
7,880✔
543
        }
7,880✔
544
    }
7,880✔
545
}
546

547
impl<T> From<BufferMut<T>> for Buffer<T> {
548
    fn from(value: BufferMut<T>) -> Self {
14,076✔
549
        value.freeze()
14,076✔
550
    }
14,076✔
551
}
552

553
#[cfg(test)]
554
mod test {
555
    use bytes::Buf;
556

557
    use crate::{Alignment, ByteBuffer, buffer};
558

559
    #[test]
560
    fn align() {
1✔
561
        let buf = buffer![0u8, 1, 2];
1✔
562
        let aligned = buf.aligned(Alignment::new(32));
1✔
563
        assert_eq!(aligned.alignment(), Alignment::new(32));
1✔
564
        assert_eq!(aligned.as_slice(), &[0, 1, 2]);
1✔
565
    }
1✔
566

567
    #[test]
568
    fn slice() {
1✔
569
        let buf = buffer![0, 1, 2, 3, 4];
1✔
570
        assert_eq!(buf.slice(1..3).as_slice(), &[1, 2]);
1✔
571
        assert_eq!(buf.slice(1..=3).as_slice(), &[1, 2, 3]);
1✔
572
    }
1✔
573

574
    #[test]
575
    fn slice_unaligned() {
1✔
576
        let buf = buffer![0i32, 1, 2, 3, 4].into_byte_buffer();
1✔
577
        // With a regular slice, this would panic. See [`slice_bad_alignment`].
578
        buf.slice_unaligned(1..2);
1✔
579
    }
1✔
580

581
    #[test]
582
    #[should_panic]
583
    fn slice_bad_alignment() {
1✔
584
        let buf = buffer![0i32, 1, 2, 3, 4].into_byte_buffer();
1✔
585
        // We should only be able to slice this buffer on 4-byte (i32) boundaries.
586
        buf.slice(1..2);
1✔
587
    }
1✔
588

589
    #[test]
590
    fn bytes_buf() {
1✔
591
        let mut buf = ByteBuffer::copy_from("helloworld".as_bytes());
1✔
592
        assert_eq!(buf.remaining(), 10);
1✔
593
        assert_eq!(buf.chunk(), b"helloworld");
1✔
594

595
        Buf::advance(&mut buf, 5);
1✔
596
        assert_eq!(buf.remaining(), 5);
1✔
597
        assert_eq!(buf.as_slice(), b"world");
1✔
598
        assert_eq!(buf.chunk(), b"world");
1✔
599
    }
1✔
600
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc