Skip to content

Commit 6286c3e

Browse files
authored
Add Ref more with_elems Ref constructors (#1258)
While we're here, rename `from` to `from_bytes` so that naming is consistent (otherwise, we'd have to add `from_with_elems` rather than `from_bytes_with_elems`, which is a weird name). Makes progress on #29
1 parent 6659998 commit 6286c3e

File tree

2 files changed

+71
-27
lines changed

2 files changed

+71
-27
lines changed

src/deprecated.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ where
2222
#[must_use = "has no side effects"]
2323
#[inline]
2424
pub fn new(bytes: B) -> Result<Ref<B, T>, CastError<B, T>> {
25-
Self::from(bytes)
25+
Self::from_bytes(bytes)
2626
}
2727
}
2828

@@ -63,7 +63,7 @@ where
6363
#[doc(hidden)]
6464
#[inline]
6565
pub fn new_slice(bytes: B) -> Option<Ref<B, [T]>> {
66-
Self::from(bytes).ok()
66+
Self::from_bytes(bytes).ok()
6767
}
6868
}
6969

src/ref.rs

+69-25
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,9 @@ where
275275
{
276276
/// Constructs a new `Ref` from a byte slice.
277277
///
278-
/// `from` verifies that `bytes.len() == size_of::<T>()` and that `bytes` is
279-
/// aligned to `align_of::<T>()`, and constructs a new `Ref`. If either of
280-
/// these checks fail, it returns `None`.
278+
/// `from_bytes` verifies that `bytes.len() == size_of::<T>()` and that
279+
/// `bytes` is aligned to `align_of::<T>()`, and constructs a new `Ref`. If
280+
/// either of these checks fail, it returns `None`.
281281
///
282282
/// # Compile-Time Assertions
283283
///
@@ -296,11 +296,11 @@ where
296296
/// trailing_dst: [()],
297297
/// }
298298
///
299-
/// let _ = Ref::<_, ZSTy>::from(&b"UU"[..]); // ⚠ Compile Error!
299+
/// let _ = Ref::<_, ZSTy>::from_bytes(&b"UU"[..]); // ⚠ Compile Error!
300300
/// ```
301301
#[must_use = "has no side effects"]
302302
#[inline]
303-
pub fn from(bytes: B) -> Result<Ref<B, T>, CastError<B, T>> {
303+
pub fn from_bytes(bytes: B) -> Result<Ref<B, T>, CastError<B, T>> {
304304
util::assert_dst_is_not_zst::<T>();
305305
if let Err(e) =
306306
Ptr::from_ref(bytes.deref()).try_cast_into_no_leftover::<T, BecauseImmutable>(None)
@@ -429,6 +429,28 @@ where
429429
}
430430
}
431431

432+
impl<B, T> Ref<B, T>
433+
where
434+
B: ByteSlice,
435+
T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized,
436+
{
437+
// TODO(#29), TODO(#871): Pick a name and make this public. Make sure to
438+
// update references to this name in `#[deprecated]` attributes elsewhere.
439+
#[doc(hidden)]
440+
#[inline]
441+
pub fn from_bytes_with_elems(bytes: B, count: usize) -> Result<Ref<B, T>, CastError<B, T>> {
442+
util::assert_dst_is_not_zst::<T>();
443+
let expected_len = match count.size_for_metadata(T::LAYOUT) {
444+
Some(len) => len,
445+
None => return Err(SizeError::new(bytes).into()),
446+
};
447+
if bytes.len() != expected_len {
448+
return Err(SizeError::new(bytes).into());
449+
}
450+
Self::from_bytes(bytes)
451+
}
452+
}
453+
432454
impl<B, T> Ref<B, T>
433455
where
434456
B: SplitByteSlice,
@@ -451,7 +473,7 @@ where
451473
return Err(SizeError::new(bytes).into());
452474
}
453475
let (prefix, bytes) = bytes.split_at(expected_len);
454-
Self::from(prefix).map(move |l| (l, bytes))
476+
Self::from_bytes(prefix).map(move |l| (l, bytes))
455477
}
456478
}
457479

@@ -479,7 +501,7 @@ where
479501
return Err(SizeError::new(bytes).into());
480502
};
481503
let (bytes, suffix) = bytes.split_at(split_at);
482-
Self::from(suffix).map(move |l| (bytes, l))
504+
Self::from_bytes(suffix).map(move |l| (bytes, l))
483505
}
484506
}
485507

@@ -517,7 +539,7 @@ where
517539
#[inline(always)]
518540
pub fn unaligned_from(bytes: B) -> Result<Ref<B, T>, SizeError<B, T>> {
519541
util::assert_dst_is_not_zst::<T>();
520-
match Ref::from(bytes) {
542+
match Ref::from_bytes(bytes) {
521543
Ok(dst) => Ok(dst),
522544
Err(CastError::Size(e)) => Err(e),
523545
Err(CastError::Alignment(_)) => unreachable!(),
@@ -608,6 +630,28 @@ where
608630
}
609631
}
610632

633+
impl<B, T> Ref<B, T>
634+
where
635+
B: ByteSlice,
636+
T: KnownLayout<PointerMetadata = usize> + Unaligned + Immutable + ?Sized,
637+
{
638+
// TODO(#29), TODO(#871): Pick a name and make this public. Make sure to
639+
// update references to this name in `#[deprecated]` attributes elsewhere.
640+
#[doc(hidden)]
641+
#[inline]
642+
pub fn unaligned_from_bytes_with_elems(
643+
bytes: B,
644+
count: usize,
645+
) -> Result<Ref<B, T>, SizeError<B, T>> {
646+
util::assert_dst_is_not_zst::<T>();
647+
Self::from_bytes_with_elems(bytes, count).map_err(|e| match e {
648+
CastError::Size(e) => e,
649+
CastError::Alignment(_) => unreachable!(),
650+
CastError::Validity(i) => match i {},
651+
})
652+
}
653+
}
654+
611655
impl<B, T> Ref<B, T>
612656
where
613657
B: SplitByteSlice,
@@ -917,13 +961,13 @@ mod tests {
917961
// reference which points to the right region of memory.
918962

919963
let buf = [0];
920-
let r = Ref::<_, u8>::from(&buf[..]).unwrap();
964+
let r = Ref::<_, u8>::from_bytes(&buf[..]).unwrap();
921965
let buf_ptr = buf.as_ptr();
922966
let deref_ptr: *const u8 = r.deref();
923967
assert_eq!(buf_ptr, deref_ptr);
924968

925969
let buf = [0];
926-
let r = Ref::<_, [u8]>::from(&buf[..]).unwrap();
970+
let r = Ref::<_, [u8]>::from_bytes(&buf[..]).unwrap();
927971
let buf_ptr = buf.as_ptr();
928972
let deref_ptr = r.deref().as_ptr();
929973
assert_eq!(buf_ptr, deref_ptr);
@@ -1045,7 +1089,7 @@ mod tests {
10451089
// A buffer with an alignment of 8.
10461090
let mut buf = Align::<[u8; 8], AU64>::default();
10471091
// `buf.t` should be aligned to 8, so this should always succeed.
1048-
test_new_helper(Ref::<_, AU64>::from(&mut buf.t[..]).unwrap());
1092+
test_new_helper(Ref::<_, AU64>::from_bytes(&mut buf.t[..]).unwrap());
10491093
{
10501094
// In a block so that `r` and `suffix` don't live too long.
10511095
buf.set_default();
@@ -1068,7 +1112,7 @@ mod tests {
10681112
let mut buf = Align::<[u8; 24], AU64>::default();
10691113
// `buf.t` should be aligned to 8 and have a length which is a multiple
10701114
// of `size_of::<AU64>()`, so this should always succeed.
1071-
test_new_helper_slice(Ref::<_, [AU64]>::from(&mut buf.t[..]).unwrap(), 3);
1115+
test_new_helper_slice(Ref::<_, [AU64]>::from_bytes(&mut buf.t[..]).unwrap(), 3);
10721116
let ascending: [u8; 24] = (0..24).collect::<Vec<_>>().try_into().unwrap();
10731117
// 16 ascending bytes followed by 8 zeros.
10741118
let mut ascending_prefix = ascending;
@@ -1224,15 +1268,15 @@ mod tests {
12241268
// A buffer with an alignment of 8.
12251269
let buf = Align::<[u8; 16], AU64>::default();
12261270
// `buf.t` should be aligned to 8, so only the length check should fail.
1227-
assert!(Ref::<_, AU64>::from(&buf.t[..]).is_err());
1271+
assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err());
12281272
assert!(Ref::<_, [u8; 8]>::unaligned_from(&buf.t[..]).is_err());
12291273

12301274
// Fail because the buffer is too small.
12311275

12321276
// A buffer with an alignment of 8.
12331277
let buf = Align::<[u8; 4], AU64>::default();
12341278
// `buf.t` should be aligned to 8, so only the length check should fail.
1235-
assert!(Ref::<_, AU64>::from(&buf.t[..]).is_err());
1279+
assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err());
12361280
assert!(Ref::<_, [u8; 8]>::unaligned_from(&buf.t[..]).is_err());
12371281
assert!(Ref::<_, AU64>::from_prefix(&buf.t[..]).is_err());
12381282
assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err());
@@ -1243,7 +1287,7 @@ mod tests {
12431287

12441288
let buf = Align::<[u8; 12], AU64>::default();
12451289
// `buf.t` has length 12, but element size is 8.
1246-
assert!(Ref::<_, [AU64]>::from(&buf.t[..]).is_err());
1290+
assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[..]).is_err());
12471291
assert!(Ref::<_, [[u8; 8]]>::unaligned_from(&buf.t[..]).is_err());
12481292

12491293
// Fail because the buffer is too short.
@@ -1262,9 +1306,9 @@ mod tests {
12621306
let buf = Align::<[u8; 13], AU64>::default();
12631307
// Slicing from 1, we get a buffer with size 12 (so the length check
12641308
// should succeed) but an alignment of only 1, which is insufficient.
1265-
assert!(Ref::<_, AU64>::from(&buf.t[1..]).is_err());
1309+
assert!(Ref::<_, AU64>::from_bytes(&buf.t[1..]).is_err());
12661310
assert!(Ref::<_, AU64>::from_prefix(&buf.t[1..]).is_err());
1267-
assert!(Ref::<_, [AU64]>::from(&buf.t[1..]).is_err());
1311+
assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[1..]).is_err());
12681312
assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[1..], 1).is_err());
12691313
assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[1..], 1).is_err());
12701314
// Slicing is unnecessary here because `new_from_suffix` uses the suffix
@@ -1292,39 +1336,39 @@ mod tests {
12921336
#[test]
12931337
fn test_display_debug() {
12941338
let buf = Align::<[u8; 8], u64>::default();
1295-
let r = Ref::<_, u64>::from(&buf.t[..]).unwrap();
1339+
let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap();
12961340
assert_eq!(format!("{}", r), "0");
12971341
assert_eq!(format!("{:?}", r), "Ref(0)");
12981342

12991343
let buf = Align::<[u8; 8], u64>::default();
1300-
let r = Ref::<_, [u64]>::from(&buf.t[..]).unwrap();
1344+
let r = Ref::<_, [u64]>::from_bytes(&buf.t[..]).unwrap();
13011345
assert_eq!(format!("{:?}", r), "Ref([0])");
13021346
}
13031347

13041348
#[test]
13051349
fn test_eq() {
13061350
let buf1 = 0_u64;
1307-
let r1 = Ref::<_, u64>::from(buf1.as_bytes()).unwrap();
1351+
let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap();
13081352
let buf2 = 0_u64;
1309-
let r2 = Ref::<_, u64>::from(buf2.as_bytes()).unwrap();
1353+
let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap();
13101354
assert_eq!(r1, r2);
13111355
}
13121356

13131357
#[test]
13141358
fn test_ne() {
13151359
let buf1 = 0_u64;
1316-
let r1 = Ref::<_, u64>::from(buf1.as_bytes()).unwrap();
1360+
let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap();
13171361
let buf2 = 1_u64;
1318-
let r2 = Ref::<_, u64>::from(buf2.as_bytes()).unwrap();
1362+
let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap();
13191363
assert_ne!(r1, r2);
13201364
}
13211365

13221366
#[test]
13231367
fn test_ord() {
13241368
let buf1 = 0_u64;
1325-
let r1 = Ref::<_, u64>::from(buf1.as_bytes()).unwrap();
1369+
let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap();
13261370
let buf2 = 1_u64;
1327-
let r2 = Ref::<_, u64>::from(buf2.as_bytes()).unwrap();
1371+
let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap();
13281372
assert!(r1 < r2);
13291373
}
13301374
}

0 commit comments

Comments
 (0)