1 // SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT 2 // 3 // Copyright 2024 The Fuchsia Authors 4 // 5 // Licensed under the 2-Clause BSD License <LICENSE-BSD or 6 // https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0 7 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT 8 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. 9 // This file may not be copied, modified, or distributed except according to 10 // those terms. 11 use super::*; 12 use crate::pointer::{ 13 BecauseMutationCompatible, BecauseSharedCompatible, MutationCompatible, TransmuteFromPtr, 14 }; 15 16 mod def { 17 use core::marker::PhantomData; 18 19 use crate::{ 20 ByteSlice, ByteSliceMut, CloneableByteSlice, CopyableByteSlice, IntoByteSlice, 21 IntoByteSliceMut, KnownLayout, PointerMetadata, 22 }; 23 24 /// A typed reference derived from a byte slice. 25 /// 26 /// A `Ref<B, T>` is a reference to a `T` which is stored in a byte slice, `B`. 27 /// Unlike a native reference (`&T` or `&mut T`), `Ref<B, T>` has the same 28 /// mutability as the byte slice it was constructed from (`B`). 29 /// 30 /// # Examples 31 /// 32 /// `Ref` can be used to treat a sequence of bytes as a structured type, and 33 /// to read and write the fields of that type as if the byte slice reference 34 /// were simply a reference to that type. 35 /// 36 /// ```rust 37 /// use zerocopy::*; 38 /// # use zerocopy_derive::*; 39 /// 40 /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] 41 /// #[repr(C)] 42 /// struct UdpHeader { 43 /// src_port: [u8; 2], 44 /// dst_port: [u8; 2], 45 /// length: [u8; 2], 46 /// checksum: [u8; 2], 47 /// } 48 /// 49 /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] 50 /// #[repr(C, packed)] 51 /// struct UdpPacket { 52 /// header: UdpHeader, 53 /// body: [u8], 54 /// } 55 /// 56 /// impl UdpPacket { 57 /// pub fn parse<B: ByteSlice>(bytes: B) -> Option<Ref<B, UdpPacket>> { 58 /// Ref::from_bytes(bytes).ok() 59 /// } 60 /// } 61 /// ``` 62 pub struct Ref<B, T: ?Sized> { 63 // INVARIANTS: 64 // - The referent (via `.deref`, `.deref_mut`, `.into`) byte slice is 65 // aligned to `T`'s alignment, and its size is valid for `T`. 66 // - If `T: KnownLayout`, let `metadata` be 67 // `T::PointerMetadata::from_elem_count` applied to `elem_count`. 68 // Then `T::size_for_metadata(metadata)` is `Some(referent.len())`. 69 bytes: B, 70 // Ignored when `T` does not implement `KnownLayout`. 71 elem_count: usize, 72 _marker: PhantomData<T>, 73 } 74 75 impl<B, T> Ref<B, T> { 76 /// Constructs a new `Ref` to a sized `T`. 77 /// 78 /// # Safety 79 /// 80 /// `bytes` dereferences (via [`deref`], [`deref_mut`], and [`into`]) to 81 /// a byte slice which is aligned to `T`'s alignment and whose size is 82 /// `size_of::<T>()`. 83 /// 84 /// [`deref`]: core::ops::Deref::deref 85 /// [`deref_mut`]: core::ops::DerefMut::deref_mut 86 /// [`into`]: core::convert::Into::into 87 pub(super) unsafe fn new_sized_unchecked(bytes: B) -> Ref<B, T> { 88 // INVARIANTS: The caller has promised that `bytes`'s referent is 89 // validly aligned and has size `size_of::<T>()`. If `T: 90 // KnownLayout`, then, since `T` is sized, `T::PointerMetadata` is 91 // `()`. `from_elem_count` returns `()` for any element count, and 92 // `T::size_for_metadata(()) == Some(size_of::<T>())`. `size_of` 93 // reports this size in bytes [1]. 94 // 95 // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: 96 // 97 // Returns the size of a type in bytes. 98 Ref { bytes, elem_count: 0, _marker: PhantomData } 99 } 100 } 101 102 impl<B, T: KnownLayout + ?Sized> Ref<B, T> { 103 /// Constructs a new `Ref`. 104 /// 105 /// # Safety 106 /// 107 /// `bytes` dereferences (via [`deref`], [`deref_mut`], and [`into`]) to 108 /// a byte slice which is aligned to `T`'s alignment and satisfies 109 /// `T::size_for_metadata(metadata) == Some(referent.len())`. 110 /// 111 /// [`deref`]: core::ops::Deref::deref 112 /// [`deref_mut`]: core::ops::DerefMut::deref_mut 113 /// [`into`]: core::convert::Into::into 114 pub(super) unsafe fn new_unchecked(bytes: B, metadata: T::PointerMetadata) -> Ref<B, T> { 115 // INVARIANTS: The caller has promised that `bytes`'s referent is 116 // validly aligned and has exactly the size described by `metadata`. 117 // `KnownLayout::PointerMetadata` is `()` for sized types and 118 // `usize` for slice DSTs. For both permitted metadata types, 119 // `from_elem_count(metadata.to_elem_count()) == metadata`: `()` 120 // round-trips through zero, while `usize` round-trips through 121 // itself. Thus, storing the element count preserves the metadata 122 // whose size the caller validated. This agrees with Rust's 123 // language-level definition of slice pointer metadata [1]. 124 // 125 // [1] Per https://doc.rust-lang.org/1.56.0/reference/dynamically-sized-types.html: 126 // 127 // Pointers to slices also store the number of elements of the 128 // slice. 129 Ref { bytes, elem_count: metadata.to_elem_count(), _marker: PhantomData } 130 } 131 132 /// Gets the pointer metadata represented by this `Ref`. 133 #[inline(always)] 134 pub(super) fn pointer_metadata(&self) -> T::PointerMetadata { 135 // INVARIANTS: `KnownLayout::PointerMetadata` is either `()` or 136 // `usize`. For `()`, `from_elem_count` ignores the element count; 137 // for `usize`, it returns the element count unchanged. 138 T::PointerMetadata::from_elem_count(self.elem_count) 139 } 140 } 141 142 impl<B: ByteSlice, T: ?Sized> Ref<B, T> { 143 /// Access the byte slice as a [`ByteSlice`]. 144 /// 145 /// # Safety 146 /// 147 /// The caller promises not to call methods on the returned 148 /// [`ByteSlice`] other than `ByteSlice` methods (for example, via 149 /// `Any::downcast_ref`). 150 /// 151 /// `as_byte_slice` promises to return a `ByteSlice` whose referent is 152 /// validly aligned for `T` and has a valid size for `T`. If `T: 153 /// KnownLayout`, then `T::size_for_metadata(self.pointer_metadata())` 154 /// returns `Some(referent.len())`. 155 pub(crate) unsafe fn as_byte_slice(&self) -> &impl ByteSlice { 156 // INVARIANTS: The caller promises not to call methods other than 157 // those on `ByteSlice`. Since `B: ByteSlice`, dereference stability 158 // guarantees that calling `ByteSlice` methods will not change the 159 // address or length of `self.bytes`'s referent. 160 // 161 // SAFETY: By invariant on `self`, the alignment, size, and metadata 162 // postconditions are upheld. 163 &self.bytes 164 } 165 } 166 167 impl<B: ByteSliceMut, T: ?Sized> Ref<B, T> { 168 /// Access the byte slice as a [`ByteSliceMut`]. 169 /// 170 /// # Safety 171 /// 172 /// The caller promises not to call methods on the returned 173 /// [`ByteSliceMut`] other than `ByteSliceMut` methods (for example, via 174 /// `Any::downcast_mut`). 175 /// 176 /// `as_byte_slice_mut` promises to return a `ByteSliceMut` whose 177 /// referent is validly aligned for `T` and has a valid size for `T`. If 178 /// `T: KnownLayout`, then 179 /// `T::size_for_metadata(self.pointer_metadata())` returns 180 /// `Some(referent.len())`. 181 pub(crate) unsafe fn as_byte_slice_mut(&mut self) -> &mut impl ByteSliceMut { 182 // INVARIANTS: The caller promises not to call methods other than 183 // those on `ByteSliceMut`. Since `B: ByteSlice`, dereference 184 // stability guarantees that calling `ByteSlice` methods will not 185 // change the address or length of `self.bytes`'s referent. 186 // 187 // SAFETY: By invariant on `self`, the alignment, size, and metadata 188 // postconditions are upheld. 189 &mut self.bytes 190 } 191 } 192 193 impl<'a, B: IntoByteSlice<'a>, T: ?Sized> Ref<B, T> { 194 /// Access the byte slice as an [`IntoByteSlice`]. 195 /// 196 /// # Safety 197 /// 198 /// The caller promises not to call methods on the returned 199 /// [`IntoByteSlice`] other than `IntoByteSlice` methods (for example, 200 /// via `Any::downcast_ref`). 201 /// 202 /// `into_byte_slice` promises to return an `IntoByteSlice` whose 203 /// referent is validly aligned for `T` and has a valid size for `T`. If 204 /// `T: KnownLayout`, then 205 /// `T::size_for_metadata(self.pointer_metadata())` returns 206 /// `Some(referent.len())`. 207 pub(crate) unsafe fn into_byte_slice(self) -> impl IntoByteSlice<'a> { 208 // INVARIANTS: The caller promises not to call methods other than 209 // those on `IntoByteSlice`. Since `B: ByteSlice`, dereference 210 // stability guarantees that calling `ByteSlice` methods will not 211 // change the address or length of `self.bytes`'s referent. 212 // 213 // SAFETY: By invariant on `self`, the alignment, size, and metadata 214 // postconditions are upheld. 215 self.bytes 216 } 217 } 218 219 impl<'a, B: IntoByteSliceMut<'a>, T: ?Sized> Ref<B, T> { 220 /// Access the byte slice as an [`IntoByteSliceMut`]. 221 /// 222 /// # Safety 223 /// 224 /// The caller promises not to call methods on the returned 225 /// [`IntoByteSliceMut`] other than `IntoByteSliceMut` methods (for 226 /// example, via `Any::downcast_mut`). 227 /// 228 /// `into_byte_slice_mut` promises to return an `IntoByteSliceMut` whose 229 /// referent is validly aligned for `T` and has a valid size for `T`. If 230 /// `T: KnownLayout`, then 231 /// `T::size_for_metadata(self.pointer_metadata())` returns 232 /// `Some(referent.len())`. 233 pub(crate) unsafe fn into_byte_slice_mut(self) -> impl IntoByteSliceMut<'a> { 234 // INVARIANTS: The caller promises not to call methods other than 235 // those on `IntoByteSliceMut`. Since `B: ByteSlice`, dereference 236 // stability guarantees that calling `ByteSlice` methods will not 237 // change the address or length of `self.bytes`'s referent. 238 // 239 // SAFETY: By invariant on `self`, the alignment, size, and metadata 240 // postconditions are upheld. 241 self.bytes 242 } 243 } 244 245 impl<B: CloneableByteSlice + Clone, T: ?Sized> Clone for Ref<B, T> { 246 #[inline] 247 fn clone(&self) -> Ref<B, T> { 248 // INVARIANTS: Since `B: CloneableByteSlice`, `self.bytes.clone()` has 249 // the same address and length as `self.bytes`. We copy 250 // `self.elem_count`, so the clone also has the same metadata. Since 251 // `self` upholds the field invariants, so does the clone. 252 Ref { bytes: self.bytes.clone(), elem_count: self.elem_count, _marker: PhantomData } 253 } 254 } 255 256 // INVARIANTS: Since `B: CopyableByteSlice`, the copied `Ref`'s `bytes` has the 257 // same address and length as the original `Ref`'s `bytes`. The copied 258 // `elem_count` has the same metadata. Since the original upholds the field 259 // invariants, so does the copy. 260 impl<B: CopyableByteSlice + Copy, T: ?Sized> Copy for Ref<B, T> {} 261 } 262 263 #[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain. 264 pub use def::Ref; 265 266 use crate::pointer::{ 267 invariant::{Aligned, BecauseExclusive, Initialized, Safe, Unaligned}, 268 BecauseRead, PtrInner, 269 }; 270 271 impl<B, T> Ref<B, T> 272 where 273 B: ByteSlice, 274 { 275 #[must_use = "has no side effects"] 276 pub(crate) fn sized_from(bytes: B) -> Result<Ref<B, T>, CastError<B, T>> { 277 if bytes.len() != mem::size_of::<T>() { 278 return Err(SizeError::new(bytes).into()); 279 } 280 if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { 281 return Err(err.with_src(bytes).into()); 282 } 283 284 // SAFETY: `size_of` returns `T`'s size in bytes [1]. The equality check 285 // above therefore establishes that `bytes` has exactly that byte 286 // length, and `validate_aligned_to` establishes alignment. 287 // 288 // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: 289 // 290 // Returns the size of a type in bytes. 291 Ok(unsafe { Ref::new_sized_unchecked(bytes) }) 292 } 293 } 294 295 impl<B, T> Ref<B, T> 296 where 297 B: SplitByteSlice, 298 { 299 #[must_use = "has no side effects"] 300 pub(crate) fn sized_from_prefix(bytes: B) -> Result<(Ref<B, T>, B), CastError<B, T>> { 301 if bytes.len() < mem::size_of::<T>() { 302 return Err(SizeError::new(bytes).into()); 303 } 304 if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { 305 return Err(err.with_src(bytes).into()); 306 } 307 let (bytes, suffix) = bytes.split_at(mem::size_of::<T>()).map_err( 308 #[inline(always)] 309 |b| SizeError::new(b).into(), 310 )?; 311 // SAFETY: We just validated alignment and that `bytes` is at least as 312 // large as `T`. `bytes.split_at(mem::size_of::<T>())?` ensures that the 313 // new `bytes` is exactly the size of `T`, measured in bytes as specified 314 // for `size_of` [1]. By safety postcondition on 315 // `SplitByteSlice::split_at` we can rely on `split_at` to produce the 316 // correct `bytes` and `suffix`. 317 // 318 // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: 319 // 320 // Returns the size of a type in bytes. 321 let r = unsafe { Ref::new_sized_unchecked(bytes) }; 322 Ok((r, suffix)) 323 } 324 325 #[must_use = "has no side effects"] 326 pub(crate) fn sized_from_suffix(bytes: B) -> Result<(B, Ref<B, T>), CastError<B, T>> { 327 let bytes_len = bytes.len(); 328 let split_at = if let Some(split_at) = bytes_len.checked_sub(mem::size_of::<T>()) { 329 split_at 330 } else { 331 return Err(SizeError::new(bytes).into()); 332 }; 333 let (prefix, bytes) = bytes.split_at(split_at).map_err(|b| SizeError::new(b).into())?; 334 if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) { 335 return Err(err.with_src(bytes).into()); 336 } 337 // SAFETY: Since `split_at` is defined as `bytes_len - size_of::<T>()`, 338 // the `bytes` which results from `let (prefix, bytes) = 339 // bytes.split_at(split_at)?` has length `size_of::<T>()`, measured in 340 // bytes as specified for `size_of` [1]. After constructing `bytes`, we 341 // validate that it has the proper alignment. By safety postcondition on 342 // `SplitByteSlice::split_at` we can rely on `split_at` to produce the 343 // correct `prefix` and `bytes`. 344 // 345 // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: 346 // 347 // Returns the size of a type in bytes. 348 let r = unsafe { Ref::new_sized_unchecked(bytes) }; 349 Ok((prefix, r)) 350 } 351 } 352 353 impl<B, T> Ref<B, T> 354 where 355 B: ByteSlice, 356 T: KnownLayout + Immutable + ?Sized, 357 { 358 /// Constructs a `Ref` from a byte slice. 359 /// 360 /// If the length of `source` is not a [valid size of `T`][valid-size], or 361 /// if `source` is not appropriately aligned for `T`, this returns `Err`. If 362 /// [`T: Unaligned`][t-unaligned], you can [infallibly discard the alignment 363 /// error][size-error-from]. 364 /// 365 /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. 366 /// 367 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size 368 /// [t-unaligned]: crate::Unaligned 369 /// [size-error-from]: error/struct.SizeError.html#method.from-1 370 /// [slice-dst]: KnownLayout#dynamically-sized-types 371 /// 372 /// # Compile-Time Assertions 373 /// 374 /// This method cannot yet be used on unsized types whose dynamically-sized 375 /// component is zero-sized. Attempting to use this method on such types 376 /// results in a compile-time assertion error; e.g.: 377 /// 378 /// ```compile_fail,E0080 379 /// use zerocopy::*; 380 /// # use zerocopy_derive::*; 381 /// 382 /// #[derive(Immutable, KnownLayout)] 383 /// #[repr(C)] 384 /// struct ZSTy { 385 /// leading_sized: u16, 386 /// trailing_dst: [()], 387 /// } 388 /// 389 /// let _ = Ref::<_, ZSTy>::from_bytes(&b"UU"[..]); // ⚠ Compile Error! 390 /// ``` 391 /// 392 #[doc = codegen_section!( 393 header = "h5", 394 bench = "ref_type_from_bytes", 395 format = "coco", 396 arity = 3, 397 [ 398 open 399 @index 1 400 @title "Sized" 401 @variant "static_size" 402 ], 403 [ 404 @index 2 405 @title "Unsized" 406 @variant "dynamic_size" 407 ], 408 [ 409 @index 3 410 @title "Dynamically Padded" 411 @variant "dynamic_padding" 412 ] 413 )] 414 #[must_use = "has no side effects"] 415 #[inline] 416 pub fn from_bytes(source: B) -> Result<Ref<B, T>, CastError<B, T>> { 417 static_assert_dst_is_not_zst!(T); 418 let metadata = match Ptr::from_ref(source.deref()) 419 .try_cast_into_no_leftover::<T, BecauseImmutable>(None) 420 { 421 Ok(ptr) => T::pointer_to_metadata(ptr.as_inner().as_ptr()), 422 Err(e) => return Err(e.with_src(()).with_src(source)), 423 }; 424 // SAFETY: By its safety postcondition, `try_cast_into_no_leftover` 425 // returned a `Ptr<T>` aligned as required for references [2], over the 426 // same byte range as `source.deref()`. `pointer_to_metadata` returns 427 // the metadata stored in that pointer, and `size_for_metadata` computes 428 // the corresponding dynamically-known byte size [1]. Thus, 429 // `T::size_for_metadata(metadata)` is `Some(source.len())`. 430 // `ByteSlice` and its applicable subtraits guarantee that the stored 431 // `source` continues to dereference or convert to that address and 432 // length. These facts establish both preconditions of `new_unchecked`. 433 // 434 // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html: 435 // 436 // Returns the size of the pointed-to value in bytes. 437 // 438 // ... when `T` has no statically-known size ... `size_of_val` can 439 // be used to get the dynamically-known size. 440 // 441 // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html: 442 // 443 // Returns the ABI-required minimum alignment of the type of the 444 // value that `val` points to. 445 // 446 // Every reference to a value of the type `T` must be a multiple of 447 // this number. 448 Ok(unsafe { Ref::new_unchecked(source, metadata) }) 449 } 450 } 451 452 impl<B, T> Ref<B, T> 453 where 454 B: SplitByteSlice, 455 T: KnownLayout + Immutable + ?Sized, 456 { 457 /// Constructs a `Ref` from the prefix of a byte slice. 458 /// 459 /// This method computes the [largest possible size of `T`][valid-size] that 460 /// can fit in the leading bytes of `source`, then attempts to return both a 461 /// `Ref` to those bytes, and a reference to the remaining bytes. If there 462 /// are insufficient bytes, or if `source` is not appropriately aligned, 463 /// this returns `Err`. If [`T: Unaligned`][t-unaligned], you can 464 /// [infallibly discard the alignment error][size-error-from]. 465 /// 466 /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. 467 /// 468 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size 469 /// [t-unaligned]: crate::Unaligned 470 /// [size-error-from]: error/struct.SizeError.html#method.from-1 471 /// [slice-dst]: KnownLayout#dynamically-sized-types 472 /// 473 /// # Compile-Time Assertions 474 /// 475 /// This method cannot yet be used on unsized types whose dynamically-sized 476 /// component is zero-sized. Attempting to use this method on such types 477 /// results in a compile-time assertion error; e.g.: 478 /// 479 /// ```compile_fail,E0080 480 /// use zerocopy::*; 481 /// # use zerocopy_derive::*; 482 /// 483 /// #[derive(Immutable, KnownLayout)] 484 /// #[repr(C)] 485 /// struct ZSTy { 486 /// leading_sized: u16, 487 /// trailing_dst: [()], 488 /// } 489 /// 490 /// let _ = Ref::<_, ZSTy>::from_prefix(&b"UU"[..]); // ⚠ Compile Error! 491 /// ``` 492 /// 493 #[doc = codegen_section!( 494 header = "h5", 495 bench = "ref_type_from_prefix", 496 format = "coco", 497 arity = 3, 498 [ 499 open 500 @index 1 501 @title "Sized" 502 @variant "static_size" 503 ], 504 [ 505 @index 2 506 @title "Unsized" 507 @variant "dynamic_size" 508 ], 509 [ 510 @index 3 511 @title "Dynamically Padded" 512 @variant "dynamic_padding" 513 ] 514 )] 515 #[must_use = "has no side effects"] 516 #[inline] 517 pub fn from_prefix(source: B) -> Result<(Ref<B, T>, B), CastError<B, T>> { 518 static_assert_dst_is_not_zst!(T); 519 let (metadata, remainder) = match Ptr::from_ref(source.deref()) 520 .try_cast_into::<T, BecauseImmutable>(CastType::Prefix, None) 521 { 522 Ok((ptr, remainder)) => (T::pointer_to_metadata(ptr.as_inner().as_ptr()), remainder), 523 Err(e) => { 524 return Err(e.with_src(()).with_src(source)); 525 } 526 }; 527 528 // SAFETY: `remainder` is constructed as a subset of `source`, and so it 529 // cannot have a larger size than `source`. Both of their `len` methods 530 // measure bytes (`source` deref's to `[u8]`, and `remainder` is a 531 // `Ptr<[u8]>`), so `source.len() >= remainder.len()`. Thus, this cannot 532 // underflow. 533 #[allow(unstable_name_collisions)] 534 let split_at = unsafe { source.len().unchecked_sub(remainder.len()) }; 535 let (bytes, suffix) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?; 536 // SAFETY: By its safety postcondition, `try_cast_into` returned an 537 // `Ptr<T>` aligned as required for references [2], and a remainder 538 // which are non-overlapping, cover `source.deref()`, and place the 539 // `Ptr<T>` at `source.deref()`'s address. 540 // Therefore, `split_at` is the typed pointer's byte length. By the 541 // safety postcondition of `SplitByteSlice::split_at`, `bytes` has that 542 // length and address. `pointer_to_metadata` returns the metadata stored 543 // in the typed pointer, and `size_for_metadata` computes the 544 // corresponding dynamically-known byte size [1]. Thus, 545 // `T::size_for_metadata(metadata)` is `Some(bytes.len())`. The 546 // `SplitByteSlice` and `ByteSlice` contracts preserve the established 547 // address and length, satisfying both preconditions of 548 // `new_unchecked`. 549 // 550 // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html: 551 // 552 // Returns the size of the pointed-to value in bytes. 553 // 554 // ... when `T` has no statically-known size ... `size_of_val` can 555 // be used to get the dynamically-known size. 556 // 557 // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html: 558 // 559 // Returns the ABI-required minimum alignment of the type of the 560 // value that `val` points to. 561 // 562 // Every reference to a value of the type `T` must be a multiple of 563 // this number. 564 let r = unsafe { Ref::new_unchecked(bytes, metadata) }; 565 Ok((r, suffix)) 566 } 567 568 /// Constructs a `Ref` from the suffix of a byte slice. 569 /// 570 /// This method computes the [largest possible size of `T`][valid-size] that 571 /// can fit in the trailing bytes of `source`, then attempts to return both 572 /// a `Ref` to those bytes, and a reference to the preceding bytes. If there 573 /// are insufficient bytes, or if that suffix of `source` is not 574 /// appropriately aligned, this returns `Err`. If [`T: 575 /// Unaligned`][t-unaligned], you can [infallibly discard the alignment 576 /// error][size-error-from]. 577 /// 578 /// `T` may be a sized type, a slice, or a [slice DST][slice-dst]. 579 /// 580 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size 581 /// [t-unaligned]: crate::Unaligned 582 /// [size-error-from]: error/struct.SizeError.html#method.from-1 583 /// [slice-dst]: KnownLayout#dynamically-sized-types 584 /// 585 /// # Compile-Time Assertions 586 /// 587 /// This method cannot yet be used on unsized types whose dynamically-sized 588 /// component is zero-sized. Attempting to use this method on such types 589 /// results in a compile-time assertion error; e.g.: 590 /// 591 /// ```compile_fail,E0080 592 /// use zerocopy::*; 593 /// # use zerocopy_derive::*; 594 /// 595 /// #[derive(Immutable, KnownLayout)] 596 /// #[repr(C)] 597 /// struct ZSTy { 598 /// leading_sized: u16, 599 /// trailing_dst: [()], 600 /// } 601 /// 602 /// let _ = Ref::<_, ZSTy>::from_suffix(&b"UU"[..]); // ⚠ Compile Error! 603 /// ``` 604 /// 605 #[doc = codegen_section!( 606 header = "h5", 607 bench = "ref_type_from_suffix", 608 format = "coco", 609 arity = 3, 610 [ 611 open 612 @index 1 613 @title "Sized" 614 @variant "static_size" 615 ], 616 [ 617 @index 2 618 @title "Unsized" 619 @variant "dynamic_size" 620 ], 621 [ 622 @index 3 623 @title "Dynamically Padded" 624 @variant "dynamic_padding" 625 ] 626 )] 627 #[must_use = "has no side effects"] 628 #[inline] 629 pub fn from_suffix(source: B) -> Result<(B, Ref<B, T>), CastError<B, T>> { 630 static_assert_dst_is_not_zst!(T); 631 let (metadata, remainder) = match Ptr::from_ref(source.deref()) 632 .try_cast_into::<T, BecauseImmutable>(CastType::Suffix, None) 633 { 634 Ok((ptr, remainder)) => (T::pointer_to_metadata(ptr.as_inner().as_ptr()), remainder), 635 Err(e) => { 636 let e = e.with_src(()); 637 return Err(e.with_src(source)); 638 } 639 }; 640 641 let split_at = remainder.len(); 642 let (prefix, bytes) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?; 643 // SAFETY: By its safety postcondition, `try_cast_into` returned an 644 // `Ptr<T>` aligned as required for references [2], and a remainder 645 // which are non-overlapping, cover `source.deref()`, and place the 646 // remainder at `source.deref()`'s address. More precisely, 647 // `PtrInner::try_cast_into` constructs the typed suffix from the 648 // `r_slice` produced by `split_at_unchecked(split_at)` and returns its 649 // `l_slice` as `remainder`. Thus, even when `T` is zero-sized, the typed 650 // pointer and the `bytes` produced by splitting `source` at 651 // `remainder.len()` have the same address and length. By the safety 652 // postcondition of `SplitByteSlice::split_at`, `bytes` retains that 653 // address and length. `pointer_to_metadata` returns the metadata stored 654 // in the typed pointer, and `size_for_metadata` computes the 655 // corresponding dynamically-known byte size [1]. Thus, 656 // `T::size_for_metadata(metadata)` is `Some(bytes.len())`. The 657 // `SplitByteSlice` and `ByteSlice` contracts preserve the established 658 // address and length, satisfying both preconditions of 659 // `new_unchecked`. 660 // 661 // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html: 662 // 663 // Returns the size of the pointed-to value in bytes. 664 // 665 // ... when `T` has no statically-known size ... `size_of_val` can 666 // be used to get the dynamically-known size. 667 // 668 // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html: 669 // 670 // Returns the ABI-required minimum alignment of the type of the 671 // value that `val` points to. 672 // 673 // Every reference to a value of the type `T` must be a multiple of 674 // this number. 675 let r = unsafe { Ref::new_unchecked(bytes, metadata) }; 676 Ok((prefix, r)) 677 } 678 } 679 680 impl<B, T> Ref<B, T> 681 where 682 B: ByteSlice, 683 T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized, 684 { 685 /// Constructs a `Ref` from the given bytes with DST length equal to `count` 686 /// without copying. 687 /// 688 /// This method attempts to return a `Ref` to the prefix of `source` 689 /// interpreted as a `T` with `count` trailing elements, and a reference to 690 /// the remaining bytes. If the length of `source` is not equal to the size 691 /// of `Self` with `count` elements, or if `source` is not appropriately 692 /// aligned, this returns `Err`. If [`T: Unaligned`][t-unaligned], you can 693 /// [infallibly discard the alignment error][size-error-from]. 694 /// 695 /// [t-unaligned]: crate::Unaligned 696 /// [size-error-from]: error/struct.SizeError.html#method.from-1 697 /// 698 /// # Compile-Time Assertions 699 /// 700 /// This method cannot yet be used on unsized types whose dynamically-sized 701 /// component is zero-sized. Attempting to use this method on such types 702 /// results in a compile-time assertion error; e.g.: 703 /// 704 /// ```compile_fail,E0080 705 /// use zerocopy::*; 706 /// # use zerocopy_derive::*; 707 /// 708 /// #[derive(Immutable, KnownLayout)] 709 /// #[repr(C)] 710 /// struct ZSTy { 711 /// leading_sized: u16, 712 /// trailing_dst: [()], 713 /// } 714 /// 715 /// let _ = Ref::<_, ZSTy>::from_bytes_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! 716 /// ``` 717 /// 718 #[doc = codegen_section!( 719 header = "h5", 720 bench = "ref_type_from_bytes_with_elems", 721 format = "coco", 722 arity = 2, 723 [ 724 open 725 @index 1 726 @title "Unsized" 727 @variant "dynamic_size" 728 ], 729 [ 730 @index 2 731 @title "Dynamically Padded" 732 @variant "dynamic_padding" 733 ] 734 )] 735 #[inline] 736 pub fn from_bytes_with_elems(source: B, count: usize) -> Result<Ref<B, T>, CastError<B, T>> { 737 static_assert_dst_is_not_zst!(T); 738 let expected_len = match T::size_for_metadata(count) { 739 Some(len) => len, 740 None => return Err(SizeError::new(source).into()), 741 }; 742 if source.len() != expected_len { 743 return Err(SizeError::new(source).into()); 744 } 745 if let Err(e) = Ptr::from_ref(source.deref()) 746 .try_cast_into_no_leftover::<T, BecauseImmutable>(Some(count)) 747 { 748 return Err(e.with_src(()).with_src(source)); 749 } 750 // SAFETY: `size_for_metadata(count)` returned `expected_len`, and the 751 // equality check established that this is `source.len()`. This is the 752 // dynamically-known byte size described by `size_of_val` [1]. By its 753 // safety postcondition, `try_cast_into_no_leftover(Some(count))` only 754 // succeeded after producing a `Ptr<T>` aligned as required for 755 // references [2], with that metadata over the same byte range as 756 // `source.deref()`. `ByteSlice` and its applicable subtraits guarantee 757 // that the stored `source` continues to dereference or convert to that 758 // address and length. These facts establish both preconditions of 759 // `new_unchecked`. 760 // 761 // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of_val.html: 762 // 763 // Returns the size of the pointed-to value in bytes. 764 // 765 // ... when `T` has no statically-known size ... `size_of_val` can 766 // be used to get the dynamically-known size. 767 // 768 // [2] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.align_of_val.html: 769 // 770 // Returns the ABI-required minimum alignment of the type of the 771 // value that `val` points to. 772 // 773 // Every reference to a value of the type `T` must be a multiple of 774 // this number. 775 Ok(unsafe { Ref::new_unchecked(source, count) }) 776 } 777 } 778 779 impl<B, T> Ref<B, T> 780 where 781 B: SplitByteSlice, 782 T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized, 783 { 784 /// Constructs a `Ref` from the prefix of the given bytes with DST 785 /// length equal to `count` without copying. 786 /// 787 /// This method attempts to return a `Ref` to the prefix of `source` 788 /// interpreted as a `T` with `count` trailing elements, and a reference to 789 /// the remaining bytes. If there are insufficient bytes, or if `source` is 790 /// not appropriately aligned, this returns `Err`. If [`T: 791 /// Unaligned`][t-unaligned], you can [infallibly discard the alignment 792 /// error][size-error-from]. 793 /// 794 /// [t-unaligned]: crate::Unaligned 795 /// [size-error-from]: error/struct.SizeError.html#method.from-1 796 /// 797 /// # Compile-Time Assertions 798 /// 799 /// This method cannot yet be used on unsized types whose dynamically-sized 800 /// component is zero-sized. Attempting to use this method on such types 801 /// results in a compile-time assertion error; e.g.: 802 /// 803 /// ```compile_fail,E0080 804 /// use zerocopy::*; 805 /// # use zerocopy_derive::*; 806 /// 807 /// #[derive(Immutable, KnownLayout)] 808 /// #[repr(C)] 809 /// struct ZSTy { 810 /// leading_sized: u16, 811 /// trailing_dst: [()], 812 /// } 813 /// 814 /// let _ = Ref::<_, ZSTy>::from_prefix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! 815 /// ``` 816 /// 817 #[doc = codegen_section!( 818 header = "h5", 819 bench = "ref_type_from_prefix_with_elems", 820 format = "coco", 821 arity = 2, 822 [ 823 open 824 @index 1 825 @title "Unsized" 826 @variant "dynamic_size" 827 ], 828 [ 829 @index 2 830 @title "Dynamically Padded" 831 @variant "dynamic_padding" 832 ] 833 )] 834 #[inline] 835 pub fn from_prefix_with_elems( 836 source: B, 837 count: usize, 838 ) -> Result<(Ref<B, T>, B), CastError<B, T>> { 839 static_assert_dst_is_not_zst!(T); 840 let expected_len = match T::size_for_metadata(count) { 841 Some(len) => len, 842 None => return Err(SizeError::new(source).into()), 843 }; 844 let (prefix, bytes) = source.split_at(expected_len).map_err(SizeError::new)?; 845 Self::from_bytes_with_elems(prefix, count).map(move |l| (l, bytes)) 846 } 847 848 /// Constructs a `Ref` from the suffix of the given bytes with DST length 849 /// equal to `count` without copying. 850 /// 851 /// This method attempts to return a `Ref` to the suffix of `source` 852 /// interpreted as a `T` with `count` trailing elements, and a reference to 853 /// the preceding bytes. If there are insufficient bytes, or if that suffix 854 /// of `source` is not appropriately aligned, this returns `Err`. If [`T: 855 /// Unaligned`][t-unaligned], you can [infallibly discard the alignment 856 /// error][size-error-from]. 857 /// 858 /// [t-unaligned]: crate::Unaligned 859 /// [size-error-from]: error/struct.SizeError.html#method.from-1 860 /// 861 /// # Compile-Time Assertions 862 /// 863 /// This method cannot yet be used on unsized types whose dynamically-sized 864 /// component is zero-sized. Attempting to use this method on such types 865 /// results in a compile-time assertion error; e.g.: 866 /// 867 /// ```compile_fail,E0080 868 /// use zerocopy::*; 869 /// # use zerocopy_derive::*; 870 /// 871 /// #[derive(Immutable, KnownLayout)] 872 /// #[repr(C)] 873 /// struct ZSTy { 874 /// leading_sized: u16, 875 /// trailing_dst: [()], 876 /// } 877 /// 878 /// let _ = Ref::<_, ZSTy>::from_suffix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error! 879 /// ``` 880 /// 881 #[doc = codegen_section!( 882 header = "h5", 883 bench = "ref_type_from_suffix_with_elems", 884 format = "coco", 885 arity = 2, 886 [ 887 open 888 @index 1 889 @title "Unsized" 890 @variant "dynamic_size" 891 ], 892 [ 893 @index 2 894 @title "Dynamically Padded" 895 @variant "dynamic_padding" 896 ] 897 )] 898 #[inline] 899 pub fn from_suffix_with_elems( 900 source: B, 901 count: usize, 902 ) -> Result<(B, Ref<B, T>), CastError<B, T>> { 903 static_assert_dst_is_not_zst!(T); 904 let expected_len = match T::size_for_metadata(count) { 905 Some(len) => len, 906 None => return Err(SizeError::new(source).into()), 907 }; 908 let split_at = if let Some(split_at) = source.len().checked_sub(expected_len) { 909 split_at 910 } else { 911 return Err(SizeError::new(source).into()); 912 }; 913 // SAFETY: The preceding `source.len().checked_sub(expected_len)` 914 // guarantees that `split_at` is in-bounds. 915 let (bytes, suffix) = unsafe { source.split_at_unchecked(split_at) }; 916 Self::from_bytes_with_elems(suffix, count).map(move |l| (bytes, l)) 917 } 918 } 919 920 impl<'a, B, T> Ref<B, T> 921 where 922 B: 'a + IntoByteSlice<'a>, 923 T: FromBytes + KnownLayout + Immutable + ?Sized, 924 { 925 /// Converts this `Ref` into a reference. 926 /// 927 /// `into_ref` consumes the `Ref`, and returns a reference to `T`. 928 /// 929 /// Note: this is an associated function, which means that you have to call 930 /// it as `Ref::into_ref(r)` instead of `r.into_ref()`. This is so that 931 /// there is no conflict with a method on the inner type. 932 /// 933 #[doc = codegen_section!( 934 header = "h5", 935 bench = "ref_type_into_ref", 936 format = "coco", 937 arity = 3, 938 [ 939 open 940 @index 1 941 @title "Sized" 942 @variant "static_size" 943 ], 944 [ 945 @index 2 946 @title "Unsized" 947 @variant "dynamic_size" 948 ], 949 [ 950 @index 3 951 @title "Dynamically Padded" 952 @variant "dynamic_padding" 953 ] 954 )] 955 #[must_use = "has no side effects"] 956 #[inline(always)] 957 pub fn into_ref(r: Self) -> &'a T { 958 // Presumably unreachable, since we've guarded each constructor of `Ref`. 959 static_assert_dst_is_not_zst!(T); 960 961 let metadata = r.pointer_metadata(); 962 963 // SAFETY: We don't call any methods on `b` other than those provided by 964 // `IntoByteSlice`. 965 let b = unsafe { r.into_byte_slice() }; 966 let b = b.into_byte_slice(); 967 968 if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { 969 let ptr = Ptr::from_ref(b); 970 // SAFETY: We just checked that `T: Sized`. By invariant on `r`, 971 // `b`'s size is equal to `size_of::<T>()`. 972 let ptr = unsafe { cast_for_sized::<T, _, _, _>(ptr) }; 973 974 // SAFETY: None of the preceding transformations modifies the 975 // address of the pointer, and by invariant on `r`, we know that it 976 // is validly-aligned. 977 let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; 978 return ptr.as_ref(); 979 } 980 981 // PANICS: By post-condition on `into_byte_slice`, `b` is aligned for 982 // `T`, and its size is exactly the size encoded by `metadata`. By 983 // post-condition, `b.into_byte_slice()` produces a byte slice with 984 // identical address and length to that produced by `b.deref()`. 985 let ptr = Ptr::from_ref(b.into_byte_slice()) 986 .try_cast_into_no_leftover::<T, BecauseImmutable>(Some(metadata)) 987 .expect("zerocopy internal error: into_ref should be infallible"); 988 let ptr = ptr.recall_validity(); 989 ptr.as_ref() 990 } 991 } 992 993 impl<'a, B, T> Ref<B, T> 994 where 995 B: 'a + IntoByteSliceMut<'a>, 996 T: FromBytes + IntoBytes + KnownLayout + ?Sized, 997 { 998 /// Converts this `Ref` into a mutable reference. 999 /// 1000 /// `into_mut` consumes the `Ref`, and returns a mutable reference to `T`. 1001 /// 1002 /// Note: this is an associated function, which means that you have to call 1003 /// it as `Ref::into_mut(r)` instead of `r.into_mut()`. This is so that 1004 /// there is no conflict with a method on the inner type. 1005 /// 1006 #[doc = codegen_section!( 1007 header = "h5", 1008 bench = "ref_type_into_mut", 1009 format = "coco", 1010 arity = 2, 1011 [ 1012 open 1013 @index 1 1014 @title "Sized" 1015 @variant "static_size" 1016 ], 1017 [ 1018 @index 2 1019 @title "Unsized" 1020 @variant "dynamic_size" 1021 ] 1022 )] 1023 #[must_use = "has no side effects"] 1024 #[inline(always)] 1025 pub fn into_mut(r: Self) -> &'a mut T { 1026 // Presumably unreachable, since we've guarded each constructor of `Ref`. 1027 static_assert_dst_is_not_zst!(T); 1028 1029 let metadata = r.pointer_metadata(); 1030 1031 // SAFETY: We don't call any methods on `b` other than those provided by 1032 // `IntoByteSliceMut`. 1033 let b = unsafe { r.into_byte_slice_mut() }; 1034 let b = b.into_byte_slice_mut(); 1035 1036 if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { 1037 let ptr = Ptr::from_mut(b); 1038 // SAFETY: We just checked that `T: Sized`. By invariant on `r`, 1039 // `b`'s size is equal to `size_of::<T>()`. 1040 let ptr = unsafe { 1041 cast_for_sized::< 1042 T, 1043 _, 1044 (BecauseRead, BecauseExclusive), 1045 (BecauseMutationCompatible, BecauseSharedCompatible), 1046 >(ptr) 1047 }; 1048 1049 // SAFETY: None of the preceding transformations modifies the 1050 // address of the pointer, and by invariant on `r`, we know that it 1051 // is validly-aligned. 1052 let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; 1053 return ptr.as_mut(); 1054 } 1055 1056 // PANICS: By post-condition on `into_byte_slice_mut`, `b` is aligned 1057 // for `T`, and its size is exactly the size encoded by `metadata`. By 1058 // post-condition, `b.into_byte_slice_mut()` produces a byte slice with 1059 // identical address and length to that produced by `b.deref_mut()`. 1060 let ptr = Ptr::from_mut(b.into_byte_slice_mut()) 1061 .try_cast_into_no_leftover::<T, BecauseExclusive>(Some(metadata)) 1062 .expect("zerocopy internal error: into_mut should be infallible"); 1063 let ptr = ptr.recall_validity::<_, (_, (_, _))>(); 1064 ptr.as_mut() 1065 } 1066 } 1067 1068 impl<B, T> Ref<B, T> 1069 where 1070 B: ByteSlice, 1071 T: ?Sized, 1072 { 1073 /// Gets the underlying bytes. 1074 /// 1075 /// Note: this is an associated function, which means that you have to call 1076 /// it as `Ref::bytes(r)` instead of `r.bytes()`. This is so that there is 1077 /// no conflict with a method on the inner type. 1078 /// 1079 #[doc = codegen_section!( 1080 header = "h5", 1081 bench = "ref_type_bytes", 1082 format = "coco", 1083 arity = 3, 1084 [ 1085 open 1086 @index 1 1087 @title "Sized" 1088 @variant "static_size" 1089 ], 1090 [ 1091 @index 2 1092 @title "Unsized" 1093 @variant "dynamic_size" 1094 ], 1095 [ 1096 @index 3 1097 @title "Dynamically Padded" 1098 @variant "dynamic_padding" 1099 ] 1100 )] 1101 #[inline] 1102 pub fn bytes(r: &Self) -> &[u8] { 1103 // SAFETY: We don't call any methods on `b` other than those provided by 1104 // `ByteSlice`. 1105 unsafe { r.as_byte_slice().deref() } 1106 } 1107 } 1108 1109 impl<B, T> Ref<B, T> 1110 where 1111 B: ByteSliceMut, 1112 T: ?Sized, 1113 { 1114 /// Gets the underlying bytes mutably. 1115 /// 1116 /// Note: this is an associated function, which means that you have to call 1117 /// it as `Ref::bytes_mut(r)` instead of `r.bytes_mut()`. This is so that 1118 /// there is no conflict with a method on the inner type. 1119 /// 1120 #[doc = codegen_section!( 1121 header = "h5", 1122 bench = "ref_type_bytes_mut", 1123 format = "coco", 1124 arity = 3, 1125 [ 1126 open 1127 @index 1 1128 @title "Sized" 1129 @variant "static_size" 1130 ], 1131 [ 1132 @index 2 1133 @title "Unsized" 1134 @variant "dynamic_size" 1135 ], 1136 [ 1137 @index 3 1138 @title "Dynamically Padded" 1139 @variant "dynamic_padding" 1140 ] 1141 )] 1142 #[inline] 1143 pub fn bytes_mut(r: &mut Self) -> &mut [u8] { 1144 // SAFETY: We don't call any methods on `b` other than those provided by 1145 // `ByteSliceMut`. 1146 unsafe { r.as_byte_slice_mut().deref_mut() } 1147 } 1148 } 1149 1150 impl<B, T> Ref<B, T> 1151 where 1152 B: ByteSlice, 1153 T: FromBytes, 1154 { 1155 /// Reads a copy of `T`. 1156 /// 1157 /// Note: this is an associated function, which means that you have to call 1158 /// it as `Ref::read(r)` instead of `r.read()`. This is so that there is no 1159 /// conflict with a method on the inner type. 1160 /// 1161 #[doc = codegen_section!( 1162 header = "h5", 1163 bench = "ref_type_read_static_size", 1164 format = "coco_static_size", 1165 )] 1166 #[must_use = "has no side effects"] 1167 #[inline] 1168 pub fn read(r: &Self) -> T { 1169 // SAFETY: We don't call any methods on `b` other than those provided by 1170 // `ByteSlice`. 1171 let b = unsafe { r.as_byte_slice() }; 1172 1173 // SAFETY: By postcondition on `as_byte_slice`, we know that `b` is a 1174 // valid size and alignment for `T`. By safety invariant on `ByteSlice`, 1175 // we know that this is preserved via `.deref()`. Because `T: 1176 // FromBytes`, it is sound to interpret these bytes as a `T`. 1177 unsafe { ptr::read(b.deref().as_ptr().cast::<T>()) } 1178 } 1179 } 1180 1181 impl<B, T> Ref<B, T> 1182 where 1183 B: ByteSliceMut, 1184 T: IntoBytes, 1185 { 1186 /// Writes the bytes of `t` and then forgets `t`. 1187 /// 1188 /// Note: this is an associated function, which means that you have to call 1189 /// it as `Ref::write(r, t)` instead of `r.write(t)`. This is so that there 1190 /// is no conflict with a method on the inner type. 1191 /// 1192 #[doc = codegen_section!( 1193 header = "h5", 1194 bench = "ref_type_write_static_size", 1195 format = "coco_static_size", 1196 )] 1197 #[inline] 1198 pub fn write(r: &mut Self, t: T) { 1199 // SAFETY: We don't call any methods on `b` other than those provided by 1200 // `ByteSliceMut`. 1201 let b = unsafe { r.as_byte_slice_mut() }; 1202 1203 // SAFETY: By postcondition on `as_byte_slice_mut`, we know that `b` is a 1204 // valid size and alignment for `T`. By safety invariant on 1205 // `ByteSlice`, we know that this is preserved via `.deref()`. Writing 1206 // `t` to the buffer will allow all of the bytes of `t` to be accessed 1207 // as a `[u8]`, but because `T: IntoBytes`, we know that this is sound. 1208 unsafe { ptr::write(b.deref_mut().as_mut_ptr().cast::<T>(), t) } 1209 } 1210 } 1211 1212 impl<B, T> Deref for Ref<B, T> 1213 where 1214 B: ByteSlice, 1215 T: FromBytes + KnownLayout + Immutable + ?Sized, 1216 { 1217 type Target = T; 1218 1219 /// Dereferences the value. 1220 /// 1221 #[doc = codegen_section!( 1222 header = "h5", 1223 bench = "ref_type_deref", 1224 format = "coco", 1225 arity = 3, 1226 [ 1227 open 1228 @index 1 1229 @title "Sized" 1230 @variant "static_size" 1231 ], 1232 [ 1233 @index 2 1234 @title "Unsized" 1235 @variant "dynamic_size" 1236 ], 1237 [ 1238 @index 3 1239 @title "Dynamically Padded" 1240 @variant "dynamic_padding" 1241 ] 1242 )] 1243 #[inline] 1244 fn deref(&self) -> &T { 1245 // Presumably unreachable, since we've guarded each constructor of `Ref`. 1246 static_assert_dst_is_not_zst!(T); 1247 1248 let metadata = self.pointer_metadata(); 1249 1250 // SAFETY: We don't call any methods on `b` other than those provided by 1251 // `ByteSlice`. 1252 let b = unsafe { self.as_byte_slice() }; 1253 let b = b.deref(); 1254 1255 if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { 1256 let ptr = Ptr::from_ref(b); 1257 // SAFETY: We just checked that `T: Sized`. By invariant on `r`, 1258 // `b`'s size is equal to `size_of::<T>()`. 1259 let ptr = unsafe { cast_for_sized::<T, _, _, _>(ptr) }; 1260 1261 // SAFETY: None of the preceding transformations modifies the 1262 // address of the pointer, and by invariant on `r`, we know that it 1263 // is validly-aligned. 1264 let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; 1265 return ptr.as_ref(); 1266 } 1267 1268 // PANICS: By postcondition on `as_byte_slice`, `b` is aligned for `T`, 1269 // and its size is exactly the size encoded by `metadata`. By invariant 1270 // on `ByteSlice`, these are preserved through `.deref()`, so this 1271 // `unwrap` will not panic. 1272 let ptr = Ptr::from_ref(b) 1273 .try_cast_into_no_leftover::<T, BecauseImmutable>(Some(metadata)) 1274 .expect("zerocopy internal error: Deref::deref should be infallible"); 1275 let ptr = ptr.recall_validity(); 1276 ptr.as_ref() 1277 } 1278 } 1279 1280 impl<B, T> DerefMut for Ref<B, T> 1281 where 1282 B: ByteSliceMut, 1283 // FIXME(#251): We can't remove `Immutable` here because it's required by 1284 // the impl of `Deref`, which is a super-trait of `DerefMut`. Maybe we can 1285 // add a separate inherent method for this? 1286 T: FromBytes + IntoBytes + KnownLayout + Immutable + ?Sized, 1287 { 1288 /// Mutably dereferences the value. 1289 /// 1290 #[doc = codegen_section!( 1291 header = "h5", 1292 bench = "ref_type_deref_mut", 1293 format = "coco", 1294 arity = 2, 1295 [ 1296 open 1297 @index 1 1298 @title "Sized" 1299 @variant "static_size" 1300 ], 1301 [ 1302 @index 2 1303 @title "Unsized" 1304 @variant "dynamic_size" 1305 ] 1306 )] 1307 #[inline] 1308 fn deref_mut(&mut self) -> &mut T { 1309 // Presumably unreachable, since we've guarded each constructor of `Ref`. 1310 static_assert_dst_is_not_zst!(T); 1311 1312 let metadata = self.pointer_metadata(); 1313 1314 // SAFETY: We don't call any methods on `b` other than those provided by 1315 // `ByteSliceMut`. 1316 let b = unsafe { self.as_byte_slice_mut() }; 1317 let b = b.deref_mut(); 1318 1319 if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info { 1320 let ptr = Ptr::from_mut(b); 1321 // SAFETY: We just checked that `T: Sized`. By invariant on `r`, 1322 // `b`'s size is equal to `size_of::<T>()`. 1323 let ptr = unsafe { 1324 cast_for_sized::< 1325 T, 1326 _, 1327 (BecauseRead, BecauseExclusive), 1328 (BecauseMutationCompatible, BecauseSharedCompatible), 1329 >(ptr) 1330 }; 1331 1332 // SAFETY: None of the preceding transformations modifies the 1333 // address of the pointer, and by invariant on `r`, we know that it 1334 // is validly-aligned. 1335 let ptr = unsafe { ptr.assume_alignment::<Aligned>() }; 1336 return ptr.as_mut(); 1337 } 1338 1339 // PANICS: By postcondition on `as_byte_slice_mut`, `b` is aligned for 1340 // `T`, and its size is exactly the size encoded by `metadata`. By 1341 // invariant on `ByteSlice`, these are preserved through `.deref_mut()`, 1342 // so this `unwrap` will not panic. 1343 let ptr = Ptr::from_mut(b) 1344 .try_cast_into_no_leftover::<T, BecauseExclusive>(Some(metadata)) 1345 .expect("zerocopy internal error: DerefMut::deref_mut should be infallible"); 1346 let ptr = ptr.recall_validity::<_, (_, (_, BecauseExclusive))>(); 1347 ptr.as_mut() 1348 } 1349 } 1350 1351 impl<T, B> Display for Ref<B, T> 1352 where 1353 B: ByteSlice, 1354 T: FromBytes + Display + KnownLayout + Immutable + ?Sized, 1355 { 1356 #[inline] 1357 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { 1358 let inner: &T = self; 1359 inner.fmt(fmt) 1360 } 1361 } 1362 1363 impl<T, B> Debug for Ref<B, T> 1364 where 1365 B: ByteSlice, 1366 T: FromBytes + Debug + KnownLayout + Immutable + ?Sized, 1367 { 1368 #[inline] 1369 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { 1370 let inner: &T = self; 1371 fmt.debug_tuple("Ref").field(&inner).finish() 1372 } 1373 } 1374 1375 impl<T, B> Eq for Ref<B, T> 1376 where 1377 B: ByteSlice, 1378 T: FromBytes + Eq + KnownLayout + Immutable + ?Sized, 1379 { 1380 } 1381 1382 impl<T, B> PartialEq for Ref<B, T> 1383 where 1384 B: ByteSlice, 1385 T: FromBytes + PartialEq + KnownLayout + Immutable + ?Sized, 1386 { 1387 #[inline] 1388 fn eq(&self, other: &Self) -> bool { 1389 self.deref().eq(other.deref()) 1390 } 1391 } 1392 1393 impl<T, B> Ord for Ref<B, T> 1394 where 1395 B: ByteSlice, 1396 T: FromBytes + Ord + KnownLayout + Immutable + ?Sized, 1397 { 1398 #[inline] 1399 fn cmp(&self, other: &Self) -> Ordering { 1400 let inner: &T = self; 1401 let other_inner: &T = other; 1402 inner.cmp(other_inner) 1403 } 1404 } 1405 1406 impl<T, B> PartialOrd for Ref<B, T> 1407 where 1408 B: ByteSlice, 1409 T: FromBytes + PartialOrd + KnownLayout + Immutable + ?Sized, 1410 { 1411 #[inline] 1412 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 1413 let inner: &T = self; 1414 let other_inner: &T = other; 1415 inner.partial_cmp(other_inner) 1416 } 1417 } 1418 1419 /// # Safety 1420 /// 1421 /// `T: Sized` and `ptr`'s referent must have size `size_of::<T>()`. 1422 #[inline(always)] 1423 unsafe fn cast_for_sized<'a, T, A, R, S>( 1424 ptr: Ptr<'a, [u8], (A, Aligned, Safe)>, 1425 ) -> Ptr<'a, T, (A, Unaligned, Safe)> 1426 where 1427 T: FromBytes + KnownLayout + ?Sized, 1428 A: crate::invariant::Aliasing, 1429 [u8]: MutationCompatible<T, A, Initialized, Initialized, R>, 1430 T: TransmuteFromPtr<T, A, Initialized, Safe, crate::pointer::cast::IdCast, S>, 1431 { 1432 use crate::pointer::cast::{Cast, Project}; 1433 1434 enum CastForSized {} 1435 1436 // SAFETY: `CastForSized` is only used below with the input `ptr`, which the 1437 // caller promises has size `size_of::<T>()`. Thus, the referent produced in 1438 // this cast has the same size as `ptr`'s referent. All operations preserve 1439 // provenance. 1440 unsafe impl<T: ?Sized + KnownLayout> Project<[u8], T> for CastForSized { 1441 #[inline(always)] 1442 fn project(src: PtrInner<'_, [u8]>) -> *mut T { 1443 T::raw_from_ptr_len( 1444 src.as_non_null().cast(), 1445 <T::PointerMetadata as crate::PointerMetadata>::from_elem_count(0), 1446 ) 1447 .as_ptr() 1448 } 1449 } 1450 1451 // SAFETY: The `Project::project` impl preserves referent address. 1452 unsafe impl<T: ?Sized + KnownLayout> Cast<[u8], T> for CastForSized {} 1453 1454 ptr.recall_validity::<Initialized, (_, (_, _))>() 1455 .cast::<_, CastForSized, _>() 1456 .recall_validity::<Safe, _>() 1457 } 1458 1459 #[cfg(test)] 1460 #[allow(clippy::assertions_on_result_states)] 1461 mod tests { 1462 use core::convert::TryInto as _; 1463 1464 use super::*; 1465 use crate::util::testutil::*; 1466 1467 #[test] 1468 fn test_mut_slice_into_ref() { 1469 // Prior to #1260/#1299, calling `into_ref` on a `&mut [u8]`-backed 1470 // `Ref` was not supported. 1471 let mut buf = [0u8]; 1472 let r = Ref::<&mut [u8], u8>::from_bytes(&mut buf).unwrap(); 1473 assert_eq!(Ref::into_ref(r), &0); 1474 } 1475 1476 #[test] 1477 fn test_address() { 1478 // Test that the `Deref` and `DerefMut` implementations return a 1479 // reference which points to the right region of memory. 1480 1481 let buf = [0]; 1482 let r = Ref::<_, u8>::from_bytes(&buf[..]).unwrap(); 1483 let buf_ptr = buf.as_ptr(); 1484 let deref_ptr: *const u8 = r.deref(); 1485 assert_eq!(buf_ptr, deref_ptr); 1486 1487 let buf = [0]; 1488 let r = Ref::<_, [u8]>::from_bytes(&buf[..]).unwrap(); 1489 let buf_ptr = buf.as_ptr(); 1490 let deref_ptr = r.deref().as_ptr(); 1491 assert_eq!(buf_ptr, deref_ptr); 1492 } 1493 1494 #[test] 1495 #[allow(clippy::clone_on_copy)] // Exercise `Ref`'s manual `Clone` impl. 1496 fn test_with_elems_preserves_ambiguous_metadata() { 1497 #[derive(FromBytes, Immutable, KnownLayout)] 1498 #[repr(C, align(8))] 1499 struct Frame { 1500 header: [u8; 8], 1501 body: [u8], 1502 } 1503 1504 #[derive(FromBytes, Immutable, KnownLayout)] 1505 #[repr(C, align(8))] 1506 struct OddHeader { 1507 header: [u8; 7], 1508 body: [u8], 1509 } 1510 1511 // Dynamic trailing padding makes these pairs of distinct element 1512 // counts produce the same total byte size. Thus, the byte length alone 1513 // cannot recover the count supplied to a `*_with_elems` constructor. 1514 assert_eq!(Frame::size_for_metadata(1), Some(16)); 1515 assert_eq!(Frame::size_for_metadata(8), Some(16)); 1516 assert_eq!(OddHeader::size_for_metadata(0), Some(8)); 1517 assert_eq!(OddHeader::size_for_metadata(1), Some(8)); 1518 1519 let bytes = Align::<[u8; 32], AU64>::default(); 1520 1521 let whole = Ref::<_, Frame>::from_bytes_with_elems(&bytes.t[..16], 1).unwrap(); 1522 assert_eq!(whole.body.len(), 1); 1523 assert_eq!(Ref::bytes(&whole).len(), 16); 1524 assert_eq!(whole.clone().body.len(), 1); 1525 let copied = whole; 1526 assert_eq!(copied.body.len(), 1); 1527 assert_eq!(Ref::into_ref(whole).body.len(), 1); 1528 1529 let (prefix, rest) = Ref::<_, Frame>::from_prefix_with_elems(&bytes.t[..], 1).unwrap(); 1530 assert_eq!(prefix.body.len(), 1); 1531 assert_eq!(rest.len(), 16); 1532 1533 let (before, suffix) = Ref::<_, Frame>::from_suffix_with_elems(&bytes.t[..24], 1).unwrap(); 1534 assert_eq!(before.len(), 8); 1535 assert_eq!(suffix.body.len(), 1); 1536 1537 // Zero is real metadata, not a sentinel for "infer from the bytes". 1538 let empty = Ref::<_, OddHeader>::from_bytes_with_elems(&bytes.t[..8], 0).unwrap(); 1539 assert!(empty.body.is_empty()); 1540 assert!(Ref::into_ref(empty).body.is_empty()); 1541 1542 // The implicit constructors still choose the largest fitting count, 1543 // and retain the metadata selected during their validating cast. 1544 let inferred = Ref::<_, Frame>::from_bytes(&bytes.t[..16]).unwrap(); 1545 assert_eq!(inferred.body.len(), 8); 1546 let (inferred, rest) = Ref::<_, Frame>::from_prefix(&bytes.t[..16]).unwrap(); 1547 assert_eq!(inferred.body.len(), 8); 1548 assert!(rest.is_empty()); 1549 let (before, inferred) = Ref::<_, Frame>::from_suffix(&bytes.t[..16]).unwrap(); 1550 assert!(before.is_empty()); 1551 assert_eq!(inferred.body.len(), 8); 1552 } 1553 1554 // Verify that values written to a `Ref` are properly shared between the 1555 // typed and untyped representations, that reads via `deref` and `read` 1556 // behave the same, and that writes via `deref_mut` and `write` behave the 1557 // same. 1558 fn test_new_helper(mut r: Ref<&mut [u8], AU64>) { 1559 // assert that the value starts at 0 1560 assert_eq!(*r, AU64(0)); 1561 assert_eq!(Ref::read(&r), AU64(0)); 1562 1563 // Assert that values written to the typed value are reflected in the 1564 // byte slice. 1565 const VAL1: AU64 = AU64(0xFF00FF00FF00FF00); 1566 *r = VAL1; 1567 assert_eq!(Ref::bytes(&r), &VAL1.to_bytes()); 1568 *r = AU64(0); 1569 Ref::write(&mut r, VAL1); 1570 assert_eq!(Ref::bytes(&r), &VAL1.to_bytes()); 1571 1572 // Assert that values written to the byte slice are reflected in the 1573 // typed value. 1574 const VAL2: AU64 = AU64(!VAL1.0); // different from `VAL1` 1575 Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.to_bytes()[..]); 1576 assert_eq!(*r, VAL2); 1577 assert_eq!(Ref::read(&r), VAL2); 1578 } 1579 1580 // Verify that values written to a `Ref` are properly shared between the 1581 // typed and untyped representations; pass a value with `typed_len` `AU64`s 1582 // backed by an array of `typed_len * 8` bytes. 1583 fn test_new_helper_slice(mut r: Ref<&mut [u8], [AU64]>, typed_len: usize) { 1584 // Assert that the value starts out zeroed. 1585 assert_eq!(&*r, vec![AU64(0); typed_len].as_slice()); 1586 1587 // Check the backing storage is the exact same slice. 1588 let untyped_len = typed_len * 8; 1589 assert_eq!(Ref::bytes(&r).len(), untyped_len); 1590 assert_eq!(Ref::bytes(&r).as_ptr(), r.as_ptr().cast::<u8>()); 1591 1592 // Assert that values written to the typed value are reflected in the 1593 // byte slice. 1594 const VAL1: AU64 = AU64(0xFF00FF00FF00FF00); 1595 for typed in &mut *r { 1596 *typed = VAL1; 1597 } 1598 assert_eq!(Ref::bytes(&r), VAL1.0.to_ne_bytes().repeat(typed_len).as_slice()); 1599 1600 // Assert that values written to the byte slice are reflected in the 1601 // typed value. 1602 const VAL2: AU64 = AU64(!VAL1.0); // different from VAL1 1603 Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.0.to_ne_bytes().repeat(typed_len)); 1604 assert!(r.iter().copied().all(|x| x == VAL2)); 1605 } 1606 1607 #[test] 1608 fn test_new_aligned_sized() { 1609 // Test that a properly-aligned, properly-sized buffer works for new, 1610 // new_from_prefix, and new_from_suffix, and that new_from_prefix and 1611 // new_from_suffix return empty slices. Test that a properly-aligned 1612 // buffer whose length is a multiple of the element size works for 1613 // new_slice. 1614 1615 // A buffer with an alignment of 8. 1616 let mut buf = Align::<[u8; 8], AU64>::default(); 1617 // `buf.t` should be aligned to 8, so this should always succeed. 1618 test_new_helper(Ref::<_, AU64>::from_bytes(&mut buf.t[..]).unwrap()); 1619 { 1620 // In a block so that `r` and `suffix` don't live too long. 1621 buf.set_default(); 1622 let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap(); 1623 assert!(suffix.is_empty()); 1624 test_new_helper(r); 1625 } 1626 { 1627 buf.set_default(); 1628 let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap(); 1629 assert!(prefix.is_empty()); 1630 test_new_helper(r); 1631 } 1632 1633 // A buffer with alignment 8 and length 24. We choose this length very 1634 // intentionally: if we instead used length 16, then the prefix and 1635 // suffix lengths would be identical. In the past, we used length 16, 1636 // which resulted in this test failing to discover the bug uncovered in 1637 // #506. 1638 let mut buf = Align::<[u8; 24], AU64>::default(); 1639 // `buf.t` should be aligned to 8 and have a length which is a multiple 1640 // of `size_of::<AU64>()`, so this should always succeed. 1641 test_new_helper_slice(Ref::<_, [AU64]>::from_bytes(&mut buf.t[..]).unwrap(), 3); 1642 buf.set_default(); 1643 let r = Ref::<_, [AU64]>::from_bytes_with_elems(&mut buf.t[..], 3).unwrap(); 1644 test_new_helper_slice(r, 3); 1645 1646 let ascending: [u8; 24] = (0..24).collect::<Vec<_>>().try_into().unwrap(); 1647 // 16 ascending bytes followed by 8 zeros. 1648 let mut ascending_prefix = ascending; 1649 ascending_prefix[16..].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); 1650 // 8 zeros followed by 16 ascending bytes. 1651 let mut ascending_suffix = ascending; 1652 ascending_suffix[..8].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); 1653 { 1654 buf.t = ascending_suffix; 1655 let (r, suffix) = Ref::<_, [AU64]>::from_prefix_with_elems(&mut buf.t[..], 1).unwrap(); 1656 assert_eq!(suffix, &ascending[8..]); 1657 test_new_helper_slice(r, 1); 1658 } 1659 { 1660 buf.t = ascending_prefix; 1661 let (prefix, r) = Ref::<_, [AU64]>::from_suffix_with_elems(&mut buf.t[..], 1).unwrap(); 1662 assert_eq!(prefix, &ascending[..16]); 1663 test_new_helper_slice(r, 1); 1664 } 1665 } 1666 1667 #[test] 1668 fn test_new_oversized() { 1669 // Test that a properly-aligned, overly-sized buffer works for 1670 // `new_from_prefix` and `new_from_suffix`, and that they return the 1671 // remainder and prefix of the slice respectively. 1672 1673 let mut buf = Align::<[u8; 16], AU64>::default(); 1674 { 1675 // In a block so that `r` and `suffix` don't live too long. `buf.t` 1676 // should be aligned to 8, so this should always succeed. 1677 let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap(); 1678 assert_eq!(suffix.len(), 8); 1679 test_new_helper(r); 1680 } 1681 { 1682 buf.set_default(); 1683 // `buf.t` should be aligned to 8, so this should always succeed. 1684 let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap(); 1685 assert_eq!(prefix.len(), 8); 1686 test_new_helper(r); 1687 } 1688 } 1689 1690 #[test] 1691 #[allow(clippy::cognitive_complexity)] 1692 fn test_new_error() { 1693 // Fail because the buffer is too large. 1694 1695 // A buffer with an alignment of 8. 1696 let buf = Align::<[u8; 16], AU64>::default(); 1697 // `buf.t` should be aligned to 8, so only the length check should fail. 1698 assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err()); 1699 1700 // Fail because the buffer is too small. 1701 1702 // A buffer with an alignment of 8. 1703 let buf = Align::<[u8; 4], AU64>::default(); 1704 // `buf.t` should be aligned to 8, so only the length check should fail. 1705 assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err()); 1706 assert!(Ref::<_, AU64>::from_prefix(&buf.t[..]).is_err()); 1707 assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err()); 1708 1709 // Fail because the length is not a multiple of the element size. 1710 1711 let buf = Align::<[u8; 12], AU64>::default(); 1712 // `buf.t` has length 12, but element size is 8. 1713 assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[..]).is_err()); 1714 1715 // Fail because the buffer is too short. 1716 let buf = Align::<[u8; 12], AU64>::default(); 1717 // `buf.t` has length 12, but the element size is 8 (and we're expecting 1718 // two of them). For each function, we test with a length that would 1719 // cause the size to overflow `usize`, and with a normal length that 1720 // will fail thanks to the buffer being too short; these are different 1721 // error paths, and while the error types are the same, the distinction 1722 // shows up in code coverage metrics. 1723 let n = (usize::MAX / mem::size_of::<AU64>()) + 1; 1724 assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], n).is_err()); 1725 assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], 2).is_err()); 1726 assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], n).is_err()); 1727 assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], 2).is_err()); 1728 assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], n).is_err()); 1729 assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], 2).is_err()); 1730 1731 // Fail because the alignment is insufficient. 1732 1733 // A buffer with an alignment of 8. An odd buffer size is chosen so that 1734 // the last byte of the buffer has odd alignment. 1735 let buf = Align::<[u8; 13], AU64>::default(); 1736 // Slicing from 1, we get a buffer with size 12 (so the length check 1737 // should succeed) but an alignment of only 1, which is insufficient. 1738 assert!(Ref::<_, AU64>::from_bytes(&buf.t[1..]).is_err()); 1739 assert!(Ref::<_, AU64>::from_prefix(&buf.t[1..]).is_err()); 1740 assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[1..]).is_err()); 1741 assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[1..], 1).is_err()); 1742 assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[1..], 1).is_err()); 1743 assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[1..], 1).is_err()); 1744 // Slicing is unnecessary here because `new_from_suffix` uses the suffix 1745 // of the slice, which has odd alignment. 1746 assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err()); 1747 1748 // Fail due to arithmetic overflow. 1749 1750 let buf = Align::<[u8; 16], AU64>::default(); 1751 let unreasonable_len = usize::MAX / mem::size_of::<AU64>() + 1; 1752 assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], unreasonable_len).is_err()); 1753 assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], unreasonable_len).is_err()); 1754 } 1755 1756 #[test] 1757 #[allow(unstable_name_collisions)] 1758 #[allow(clippy::as_conversions)] 1759 fn test_into_ref_mut() { 1760 #[allow(unused)] 1761 use crate::util::AsAddress as _; 1762 1763 let mut buf = Align::<[u8; 8], u64>::default(); 1764 let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap(); 1765 let rf = Ref::into_ref(r); 1766 assert_eq!(rf, &0u64); 1767 let buf_addr = (&buf.t as *const [u8; 8]).addr(); 1768 assert_eq!((rf as *const u64).addr(), buf_addr); 1769 1770 let r = Ref::<_, u64>::from_bytes(&mut buf.t[..]).unwrap(); 1771 let rf = Ref::into_mut(r); 1772 assert_eq!(rf, &mut 0u64); 1773 assert_eq!((rf as *mut u64).addr(), buf_addr); 1774 1775 *rf = u64::MAX; 1776 assert_eq!(buf.t, [0xFF; 8]); 1777 1778 // Exercise the unsized `into_mut` route, which must use the metadata 1779 // retained by the constructor rather than infer fresh metadata. 1780 let mut buf = Align::<[u8; 8], u16>::default(); 1781 let r = Ref::<_, [u16]>::from_bytes_with_elems(&mut buf.t[..], 4).unwrap(); 1782 let rf = Ref::into_mut(r); 1783 assert_eq!(rf.len(), 4); 1784 } 1785 1786 #[test] 1787 fn test_display_debug() { 1788 let buf = Align::<[u8; 8], u64>::default(); 1789 let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap(); 1790 assert_eq!(format!("{}", r), "0"); 1791 assert_eq!(format!("{:?}", r), "Ref(0)"); 1792 1793 let buf = Align::<[u8; 8], u64>::default(); 1794 let r = Ref::<_, [u64]>::from_bytes(&buf.t[..]).unwrap(); 1795 assert_eq!(format!("{:?}", r), "Ref([0])"); 1796 } 1797 1798 #[test] 1799 fn test_eq() { 1800 let buf1 = 0_u64; 1801 let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); 1802 let buf2 = 0_u64; 1803 let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); 1804 assert_eq!(r1, r2); 1805 } 1806 1807 #[test] 1808 fn test_ne() { 1809 let buf1 = 0_u64; 1810 let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); 1811 let buf2 = 1_u64; 1812 let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); 1813 assert_ne!(r1, r2); 1814 } 1815 1816 #[test] 1817 fn test_ord() { 1818 let buf1 = 0_u64; 1819 let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap(); 1820 let buf2 = 1_u64; 1821 let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap(); 1822 assert!(r1 < r2); 1823 assert_eq!(PartialOrd::partial_cmp(&r1, &r2), Some(Ordering::Less)); 1824 assert_eq!(Ord::cmp(&r1, &r2), Ordering::Less); 1825 } 1826 } 1827 1828 #[cfg(all(test, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS))] 1829 mod benches { 1830 use test::{self, Bencher}; 1831 1832 use super::*; 1833 use crate::util::testutil::*; 1834 1835 #[bench] 1836 fn bench_from_bytes_sized(b: &mut Bencher) { 1837 let buf = Align::<[u8; 8], AU64>::default(); 1838 // `buf.t` should be aligned to 8, so this should always succeed. 1839 let bytes = &buf.t[..]; 1840 b.iter(|| test::black_box(Ref::<_, AU64>::from_bytes(test::black_box(bytes)).unwrap())); 1841 } 1842 1843 #[bench] 1844 fn bench_into_ref_sized(b: &mut Bencher) { 1845 let buf = Align::<[u8; 8], AU64>::default(); 1846 let bytes = &buf.t[..]; 1847 let r = Ref::<_, AU64>::from_bytes(bytes).unwrap(); 1848 b.iter(|| test::black_box(Ref::into_ref(test::black_box(r)))); 1849 } 1850 1851 #[bench] 1852 fn bench_into_mut_sized(b: &mut Bencher) { 1853 let mut buf = Align::<[u8; 8], AU64>::default(); 1854 let buf = &mut buf.t[..]; 1855 let _ = Ref::<_, AU64>::from_bytes(&mut *buf).unwrap(); 1856 b.iter(move || { 1857 // SAFETY: The preceding `from_bytes` succeeded, and so we know that 1858 // `buf` is validly aligned and has the `size_of::<AU64>()` byte 1859 // length required by `new_sized_unchecked` [1]. 1860 // 1861 // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: 1862 // 1863 // Returns the size of a type in bytes. 1864 let r = unsafe { Ref::<&mut [u8], AU64>::new_sized_unchecked(&mut *buf) }; 1865 test::black_box(Ref::into_mut(test::black_box(r))); 1866 }); 1867 } 1868 1869 #[bench] 1870 fn bench_deref_sized(b: &mut Bencher) { 1871 let buf = Align::<[u8; 8], AU64>::default(); 1872 let bytes = &buf.t[..]; 1873 let r = Ref::<_, AU64>::from_bytes(bytes).unwrap(); 1874 b.iter(|| { 1875 let temp = test::black_box(r); 1876 test::black_box(temp.deref()); 1877 }); 1878 } 1879 1880 #[bench] 1881 fn bench_deref_mut_sized(b: &mut Bencher) { 1882 let mut buf = Align::<[u8; 8], AU64>::default(); 1883 let buf = &mut buf.t[..]; 1884 let _ = Ref::<_, AU64>::from_bytes(&mut *buf).unwrap(); 1885 b.iter(|| { 1886 // SAFETY: The preceding `from_bytes` succeeded, and so we know that 1887 // `buf` is validly aligned and has the `size_of::<AU64>()` byte 1888 // length required by `new_sized_unchecked` [1]. 1889 // 1890 // [1] Per https://doc.rust-lang.org/1.56.0/core/mem/fn.size_of.html: 1891 // 1892 // Returns the size of a type in bytes. 1893 let r = unsafe { Ref::<&mut [u8], AU64>::new_sized_unchecked(&mut *buf) }; 1894 let mut temp = test::black_box(r); 1895 test::black_box(temp.deref_mut()); 1896 }); 1897 } 1898 } 1899