Skip to content

Commit e0e9b0d

Browse files
committed
Return remaining bytes in FromBytes conversion methods
This change makes the slice and non-slice conversion methods consistent, and provides a lightweight way (i.e., without `Ref`) to access the leftover bytes after conversions.
1 parent 9fe8aae commit e0e9b0d

File tree

1 file changed

+85
-77
lines changed

1 file changed

+85
-77
lines changed

src/lib.rs

Lines changed: 85 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,12 +2203,10 @@ pub unsafe trait FromBytes: FromZeros {
22032203

22042204
/// Interprets the prefix of the given `bytes` as a `&Self` without copying.
22052205
///
2206-
/// `ref_from_prefix` returns a reference to the first `size_of::<Self>()`
2207-
/// bytes of `bytes`. If `bytes.len() < size_of::<Self>()` or `bytes` is not
2208-
/// aligned to `align_of::<Self>()`, this returns `None`.
2209-
///
2210-
/// To also access the prefix bytes, use [`Ref::new_from_prefix`]. Then, use
2211-
/// [`Ref::into_ref`] to get a `&Self` with the same lifetime.
2206+
/// This method returns both a reference to the first `size_of::<Self>()`
2207+
/// bytes of `bytes` interpreted as `Self`, and a reference to the remaining
2208+
/// bytes. If `bytes.len() < size_of::<Self>()` or `bytes` is not aligned to
2209+
/// `align_of::<Self>()`, this returns `None`.
22122210
///
22132211
/// # Examples
22142212
///
@@ -2235,31 +2233,31 @@ pub unsafe trait FromBytes: FromZeros {
22352233
/// // These are more bytes than are needed to encode a `Packet`.
22362234
/// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14][..];
22372235
///
2238-
/// let packet = Packet::ref_from_prefix(bytes).unwrap();
2236+
/// let (packet, excess) = Packet::ref_from_prefix(bytes).unwrap();
22392237
///
22402238
/// assert_eq!(packet.header.src_port, [0, 1]);
22412239
/// assert_eq!(packet.header.dst_port, [2, 3]);
22422240
/// assert_eq!(packet.header.length, [4, 5]);
22432241
/// assert_eq!(packet.header.checksum, [6, 7]);
22442242
/// assert_eq!(packet.body, [[8, 9], [10, 11], [12, 13]]);
2243+
/// assert_eq!(excess, &[14u8][..]);
22452244
/// ```
22462245
#[must_use = "has no side effects"]
22472246
#[inline]
2248-
fn ref_from_prefix(bytes: &[u8]) -> Option<&Self>
2247+
fn ref_from_prefix(bytes: &[u8]) -> Option<(&Self, &[u8])>
22492248
where
22502249
Self: KnownLayout + NoCell,
22512250
{
2252-
Ref::<&[u8], Self>::bikeshed_new_from_prefix_known_layout(bytes).map(|(r, _)| r.into_ref())
2251+
Ref::<&[u8], Self>::bikeshed_new_from_prefix_known_layout(bytes)
2252+
.map(|(r, s)| (r.into_ref(), s))
22532253
}
22542254

22552255
/// Interprets the suffix of the given `bytes` as a `&Self` without copying.
22562256
///
2257-
/// `ref_from_suffix` returns a reference to the last `size_of::<Self>()`
2258-
/// bytes of `bytes`. If `bytes.len() < size_of::<Self>()` or the suffix of
2259-
/// `bytes` is not aligned to `align_of::<Self>()`, this returns `None`.
2260-
///
2261-
/// To also access the suffix bytes, use [`Ref::new_from_suffix`]. Then, use
2262-
/// [`Ref::into_ref`] to get a `&Self` with the same lifetime.
2257+
/// This method returns both a reference to the last `size_of::<Self>()`
2258+
/// bytes of `bytes` interpreted as `Self`, and a reference to the preceding
2259+
/// bytes. If `bytes.len() < size_of::<Self>()` or the suffix of `bytes` is
2260+
/// not aligned to `align_of::<Self>()`, this returns `None`.
22632261
///
22642262
/// # Examples
22652263
///
@@ -2276,17 +2274,19 @@ pub unsafe trait FromBytes: FromZeros {
22762274
/// // These are more bytes than are needed to encode a `PacketTrailer`.
22772275
/// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
22782276
///
2279-
/// let trailer = PacketTrailer::ref_from_suffix(bytes).unwrap();
2277+
/// let (prefix, trailer) = PacketTrailer::ref_from_suffix(bytes).unwrap();
22802278
///
2279+
/// assert_eq!(prefix, &[0, 1, 2, 3, 4, 5][..]);
22812280
/// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
22822281
/// ```
22832282
#[must_use = "has no side effects"]
22842283
#[inline]
2285-
fn ref_from_suffix(bytes: &[u8]) -> Option<&Self>
2284+
fn ref_from_suffix(bytes: &[u8]) -> Option<(&[u8], &Self)>
22862285
where
22872286
Self: NoCell + KnownLayout,
22882287
{
2289-
Ref::<&[u8], Self>::bikeshed_new_from_suffix_known_layout(bytes).map(|(_, r)| r.into_ref())
2288+
Ref::<&[u8], Self>::bikeshed_new_from_suffix_known_layout(bytes)
2289+
.map(|(p, r)| (p, r.into_ref()))
22902290
}
22912291

22922292
/// Interprets the given `bytes` as a `&mut Self` without copying.
@@ -2335,12 +2335,10 @@ pub unsafe trait FromBytes: FromZeros {
23352335
/// Interprets the prefix of the given `bytes` as a `&mut Self` without
23362336
/// copying.
23372337
///
2338-
/// `mut_from_prefix` returns a reference to the first `size_of::<Self>()`
2339-
/// bytes of `bytes`. If `bytes.len() < size_of::<Self>()` or `bytes` is not
2340-
/// aligned to `align_of::<Self>()`, this returns `None`.
2341-
///
2342-
/// To also access the prefix bytes, use [`Ref::new_from_prefix`]. Then, use
2343-
/// [`Ref::into_mut`] to get a `&mut Self` with the same lifetime.
2338+
/// This method returns both a reference to the first `size_of::<Self>()`
2339+
/// bytes of `bytes` interpreted as `Self`, and a reference to the remaining
2340+
/// bytes. If `bytes.len() < size_of::<Self>()` or `bytes` is not aligned to
2341+
/// `align_of::<Self>()`, this returns `None`.
23442342
///
23452343
/// # Examples
23462344
///
@@ -2360,35 +2358,36 @@ pub unsafe trait FromBytes: FromZeros {
23602358
/// // These are more bytes than are needed to encode a `PacketHeader`.
23612359
/// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
23622360
///
2363-
/// let header = PacketHeader::mut_from_prefix(bytes).unwrap();
2361+
/// let (header, body) = PacketHeader::mut_from_prefix(bytes).unwrap();
23642362
///
23652363
/// assert_eq!(header.src_port, [0, 1]);
23662364
/// assert_eq!(header.dst_port, [2, 3]);
23672365
/// assert_eq!(header.length, [4, 5]);
23682366
/// assert_eq!(header.checksum, [6, 7]);
2367+
/// assert_eq!(body, &[8, 9][..]);
23692368
///
23702369
/// header.checksum = [0, 0];
2370+
/// body.fill(1);
23712371
///
2372-
/// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 8, 9]);
2372+
/// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 1, 1]);
23732373
/// ```
23742374
#[must_use = "has no side effects"]
23752375
#[inline]
2376-
fn mut_from_prefix(bytes: &mut [u8]) -> Option<&mut Self>
2376+
fn mut_from_prefix(bytes: &mut [u8]) -> Option<(&mut Self, &mut [u8])>
23772377
where
23782378
Self: IntoBytes + KnownLayout + NoCell,
23792379
{
23802380
Ref::<&mut [u8], Self>::bikeshed_new_from_prefix_known_layout(bytes)
2381-
.map(|(r, _)| r.into_mut())
2381+
.map(|(r, s)| (r.into_mut(), s))
23822382
}
23832383

2384-
/// Interprets the suffix of the given `bytes` as a `&mut Self` without copying.
2385-
///
2386-
/// `mut_from_suffix` returns a reference to the last `size_of::<Self>()`
2387-
/// bytes of `bytes`. If `bytes.len() < size_of::<Self>()` or the suffix of
2388-
/// `bytes` is not aligned to `align_of::<Self>()`, this returns `None`.
2384+
/// Interprets the suffix of the given `bytes` as a `&mut Self` without
2385+
/// copying.
23892386
///
2390-
/// To also access the suffix bytes, use [`Ref::new_from_suffix`]. Then,
2391-
/// use [`Ref::into_mut`] to get a `&mut Self` with the same lifetime.
2387+
/// This method returns both a reference to the last `size_of::<Self>()`
2388+
/// bytes of `bytes` interpreted as `Self`, and a reference to the preceding
2389+
/// bytes. If `bytes.len() < size_of::<Self>()` or the suffix of `bytes` is
2390+
/// not aligned to `align_of::<Self>()`, this returns `None`.
23922391
///
23932392
/// # Examples
23942393
///
@@ -2405,34 +2404,35 @@ pub unsafe trait FromBytes: FromZeros {
24052404
/// // These are more bytes than are needed to encode a `PacketTrailer`.
24062405
/// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
24072406
///
2408-
/// let trailer = PacketTrailer::mut_from_suffix(bytes).unwrap();
2407+
/// let (prefix, trailer) = PacketTrailer::mut_from_suffix(bytes).unwrap();
24092408
///
2409+
/// assert_eq!(prefix, &[0u8, 1, 2, 3, 4, 5][..]);
24102410
/// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
24112411
///
2412-
/// trailer.frame_check_sequence = [0, 0, 0, 0];
2412+
/// prefix.fill(0);
2413+
/// trailer.frame_check_sequence.fill(1);
24132414
///
2414-
/// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 0, 0]);
2415+
/// assert_eq!(bytes, [0, 0, 0, 0, 0, 0, 1, 1, 1, 1]);
24152416
/// ```
24162417
#[must_use = "has no side effects"]
24172418
#[inline]
2418-
fn mut_from_suffix(bytes: &mut [u8]) -> Option<&mut Self>
2419+
fn mut_from_suffix(bytes: &mut [u8]) -> Option<(&mut [u8], &mut Self)>
24192420
where
24202421
Self: IntoBytes + KnownLayout + NoCell,
24212422
{
24222423
Ref::<&mut [u8], Self>::bikeshed_new_from_suffix_known_layout(bytes)
2423-
.map(|(_, r)| r.into_mut())
2424+
.map(|(p, r)| (p, r.into_mut()))
24242425
}
24252426

24262427
/// Interprets the prefix of the given `bytes` as a `&[Self]` with length
24272428
/// equal to `count` without copying.
24282429
///
2429-
/// This method verifies that `bytes.len() >= size_of::<T>() * count`
2430-
/// and that `bytes` is aligned to `align_of::<T>()`. It consumes the
2431-
/// first `size_of::<T>() * count` bytes from `bytes` to construct a
2432-
/// `&[Self]`, and returns the remaining bytes to the caller. It also
2433-
/// ensures that `sizeof::<T>() * count` does not overflow a `usize`.
2434-
/// If any of the length, alignment, or overflow checks fail, it returns
2435-
/// `None`.
2430+
/// This method verifies that `bytes.len() >= size_of::<T>() * count` and
2431+
/// that `bytes` is aligned to `align_of::<T>()`. It reinterprets the first
2432+
/// `size_of::<T>() * count` bytes from `bytes` to construct a `&[Self]`,
2433+
/// and returns the remaining bytes to the caller. It also ensures that
2434+
/// `sizeof::<T>() * count` does not overflow a `usize`. If any of the
2435+
/// length, alignment, or overflow checks fail, it returns `None`.
24362436
///
24372437
/// # Panics
24382438
///
@@ -2478,13 +2478,12 @@ pub unsafe trait FromBytes: FromZeros {
24782478
/// Interprets the suffix of the given `bytes` as a `&[Self]` with length
24792479
/// equal to `count` without copying.
24802480
///
2481-
/// This method verifies that `bytes.len() >= size_of::<T>() * count`
2482-
/// and that `bytes` is aligned to `align_of::<T>()`. It consumes the
2483-
/// last `size_of::<T>() * count` bytes from `bytes` to construct a
2484-
/// `&[Self]`, and returns the preceding bytes to the caller. It also
2485-
/// ensures that `sizeof::<T>() * count` does not overflow a `usize`.
2486-
/// If any of the length, alignment, or overflow checks fail, it returns
2487-
/// `None`.
2481+
/// This method verifies that `bytes.len() >= size_of::<T>() * count` and
2482+
/// that `bytes` is aligned to `align_of::<T>()`. It reinterprets the last
2483+
/// `size_of::<T>() * count` bytes from `bytes` to construct a `&[Self]`,
2484+
/// and returns the preceding bytes to the caller. It also ensures that
2485+
/// `sizeof::<T>() * count` does not overflow a `usize`. If any of the
2486+
/// length, alignment, or overflow checks fail, it returns `None`.
24882487
///
24892488
/// # Panics
24902489
///
@@ -2579,16 +2578,15 @@ pub unsafe trait FromBytes: FromZeros {
25792578
Ref::<_, [Self]>::new(bytes).map(|r| r.into_mut())
25802579
}
25812580

2582-
/// Interprets the prefix of the given `bytes` as a `&mut [Self]` with length
2583-
/// equal to `count` without copying.
2581+
/// Interprets the prefix of the given `bytes` as a `&mut [Self]` with
2582+
/// length equal to `count` without copying.
25842583
///
2585-
/// This method verifies that `bytes.len() >= size_of::<T>() * count`
2586-
/// and that `bytes` is aligned to `align_of::<T>()`. It consumes the
2587-
/// first `size_of::<T>() * count` bytes from `bytes` to construct a
2588-
/// `&[Self]`, and returns the remaining bytes to the caller. It also
2589-
/// ensures that `sizeof::<T>() * count` does not overflow a `usize`.
2590-
/// If any of the length, alignment, or overflow checks fail, it returns
2591-
/// `None`.
2584+
/// This method verifies that `bytes.len() >= size_of::<T>() * count` and
2585+
/// that `bytes` is aligned to `align_of::<T>()`. It reinterprets the first
2586+
/// `size_of::<T>() * count` bytes from `bytes` to construct a `&[Self]`,
2587+
/// and returns the remaining bytes to the caller. It also ensures that
2588+
/// `sizeof::<T>() * count` does not overflow a `usize`. If any of the
2589+
/// length, alignment, or overflow checks fail, it returns `None`.
25922590
///
25932591
/// # Panics
25942592
///
@@ -2623,8 +2621,9 @@ pub unsafe trait FromBytes: FromZeros {
26232621
/// assert_eq!(rest, &[8, 9]);
26242622
///
26252623
/// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
2624+
/// rest.fill(1);
26262625
///
2627-
/// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0, 8, 9]);
2626+
/// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0, 1, 1]);
26282627
/// ```
26292628
#[must_use = "has no side effects"]
26302629
#[inline]
@@ -2638,13 +2637,12 @@ pub unsafe trait FromBytes: FromZeros {
26382637
/// Interprets the suffix of the given `bytes` as a `&mut [Self]` with length
26392638
/// equal to `count` without copying.
26402639
///
2641-
/// This method verifies that `bytes.len() >= size_of::<T>() * count`
2642-
/// and that `bytes` is aligned to `align_of::<T>()`. It consumes the
2643-
/// last `size_of::<T>() * count` bytes from `bytes` to construct a
2644-
/// `&[Self]`, and returns the preceding bytes to the caller. It also
2645-
/// ensures that `sizeof::<T>() * count` does not overflow a `usize`.
2646-
/// If any of the length, alignment, or overflow checks fail, it returns
2647-
/// `None`.
2640+
/// This method verifies that `bytes.len() >= size_of::<T>() * count` and
2641+
/// that `bytes` is aligned to `align_of::<T>()`. It reinterprets the last
2642+
/// `size_of::<T>() * count` bytes from `bytes` to construct a `&[Self]`,
2643+
/// and returns the preceding bytes to the caller. It also ensures that
2644+
/// `sizeof::<T>() * count` does not overflow a `usize`. If any of the
2645+
/// length, alignment, or overflow checks fail, it returns `None`.
26482646
///
26492647
/// # Panics
26502648
///
@@ -2678,9 +2676,10 @@ pub unsafe trait FromBytes: FromZeros {
26782676
/// Pixel { r: 6, g: 7, b: 8, a: 9 },
26792677
/// ]);
26802678
///
2679+
/// rest.fill(9);
26812680
/// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
26822681
///
2683-
/// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 0, 0]);
2682+
/// assert_eq!(bytes, [9, 9, 2, 3, 4, 5, 0, 0, 0, 0]);
26842683
/// ```
26852684
#[must_use = "has no side effects"]
26862685
#[inline]
@@ -7846,12 +7845,21 @@ mod tests {
78467845
suffix.0 = 0x0101010101010101;
78477846
// The `[u8:9]` is a non-half size of the full buffer, which would catch
78487847
// `from_prefix` having the same implementation as `from_suffix` (issues #506, #511).
7849-
assert_eq!(<[u8; 9]>::ref_from_suffix(&buf.t[..]).unwrap(), &[7u8, 1, 1, 1, 1, 1, 1, 1, 1]);
7850-
let suffix = AU64::mut_from_suffix(&mut buf.t[1..]).unwrap();
7848+
assert_eq!(
7849+
<[u8; 9]>::ref_from_suffix(&buf.t[..]).unwrap(),
7850+
(&[0, 1, 2, 3, 4, 5, 6][..], &[7u8, 1, 1, 1, 1, 1, 1, 1, 1])
7851+
);
7852+
let (prefix, suffix) = AU64::mut_from_suffix(&mut buf.t[1..]).unwrap();
7853+
assert_eq!(prefix, &mut [1u8, 2, 3, 4, 5, 6, 7][..]);
78517854
suffix.0 = 0x0202020202020202;
7852-
<[u8; 10]>::mut_from_suffix(&mut buf.t[..]).unwrap()[0] = 42;
7853-
assert_eq!(<[u8; 9]>::ref_from_prefix(&buf.t[..]).unwrap(), &[0, 1, 2, 3, 4, 5, 42, 7, 2]);
7854-
<[u8; 2]>::mut_from_prefix(&mut buf.t[..]).unwrap()[1] = 30;
7855+
let (prefix, suffix) = <[u8; 10]>::mut_from_suffix(&mut buf.t[..]).unwrap();
7856+
assert_eq!(prefix, &mut [0u8, 1, 2, 3, 4, 5][..]);
7857+
suffix[0] = 42;
7858+
assert_eq!(
7859+
<[u8; 9]>::ref_from_prefix(&buf.t[..]).unwrap(),
7860+
(&[0u8, 1, 2, 3, 4, 5, 42, 7, 2], &[2u8, 2, 2, 2, 2, 2, 2][..])
7861+
);
7862+
<[u8; 2]>::mut_from_prefix(&mut buf.t[..]).unwrap().0[1] = 30;
78557863
assert_eq!(buf.t, [0, 30, 2, 3, 4, 5, 42, 7, 2, 2, 2, 2, 2, 2, 2, 2]);
78567864
}
78577865

0 commit comments

Comments
 (0)