Skip to content

Commit

Permalink
Add copy_unsafe feature
Browse files Browse the repository at this point in the history
  • Loading branch information
djkoloski committed May 7, 2021
1 parent eb465fb commit a753588
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 6 deletions.
1 change: 1 addition & 0 deletions rkyv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ archive_be = ["rend", "rkyv_derive/archive_be"]
archive_le = ["rend", "rkyv_derive/archive_le"]
const_generics = []
copy = []
copy_unsafe = []
size_64 = []
std = ["bytecheck/std", "seahash", "rend/std"]
strict = ["rkyv_derive/strict"]
Expand Down
24 changes: 22 additions & 2 deletions rkyv/src/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ use core::sync::atomic::{
/// This trait is similar to `Copy` in that it's automatically implemented for all types composed
/// entirely of other `ArchiveCopy` types. `Copy` is necessary, but not sufficient for `ArchiveCopy`
/// as some `Copy` type representations may vary from platform to platform.
#[rustc_unsafe_specialization_marker]
pub auto trait ArchiveCopy {}

// (), PhantomData, PhantomPinned, bool, i8, u8, NonZeroI8, and NonZeroU8 are always ArchiveCopy
Expand Down Expand Up @@ -112,7 +111,6 @@ impl !ArchiveCopy for crate::RawRelPtr {}
///
/// These types are always safe to `memcpy` around because they will never contain uninitialized
/// padding.
#[rustc_unsafe_specialization_marker]
pub unsafe trait ArchiveCopySafe: ArchiveCopy + Sized {}

// (), PhantomData, PhantomPinned, bool, i8, u8, NonZeroI8, and NonZeroU8 are always ArchiveCopySafe
Expand Down Expand Up @@ -178,3 +176,25 @@ macro_rules! impl_tuple {
impl_tuple!(T, T, T, T, T, T, T, T, T, T, T,);

unsafe impl<T: ArchiveCopySafe, const N: usize> ArchiveCopySafe for [T; N] {}

/// Types that are may be copy optimized.
///
/// By default, only [`ArchiveCopySafe`] types may be copy optimized. By enabling the `copy_unsafe`
/// feature, all types that are [`ArchiveCopy`] may be copy optimized.
#[cfg(not(feature = "copy_unsafe"))]
#[rustc_unsafe_specialization_marker]
pub trait ArchiveCopyOptimize: ArchiveCopySafe {}

#[cfg(not(feature = "copy_unsafe"))]
impl<T: ArchiveCopySafe> ArchiveCopyOptimize for T {}

/// Types that are may be copy optimized.
///
/// By default, only [`ArchiveCopySafe`] types may be copy optimized. By enabling the `copy_unsafe`
/// feature, all types that are [`ArchiveCopy`] may be copy optimized.
#[cfg(feature = "copy_unsafe")]
#[rustc_unsafe_specialization_marker]
pub trait ArchiveCopyOptimize: ArchiveCopy {}

#[cfg(feature = "copy_unsafe")]
impl<T: ArchiveCopy> ArchiveCopyOptimize for T {}
8 changes: 4 additions & 4 deletions rkyv/src/core_impl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
Deserialize, DeserializeUnsized, Fallible, FixedUsize, Serialize, SerializeUnsized,
};
#[cfg(feature = "copy")]
use crate::copy::ArchiveCopySafe;
use crate::copy::ArchiveCopyOptimize;
use core::{
alloc, cmp,
hash::{Hash, Hasher},
Expand Down Expand Up @@ -302,7 +302,7 @@ impl<T: Archive<Resolver = ()> + Serialize<S>, S: Serializer + ?Sized> Serialize
}

#[cfg(all(not(feature = "std"), feature = "copy"))]
impl<T: Archive<Resolver = ()> + Serialize<S> + crate::copy::ArchiveCopySafe, S: Serializer + ?Sized> SerializeUnsized<S> for [T] {
impl<T: Archive<Resolver = ()> + Serialize<S> + crate::copy::ArchiveCopyOptimize, S: Serializer + ?Sized> SerializeUnsized<S> for [T] {
#[inline]
fn serialize_unsized(&self, serializer: &mut S) -> Result<usize, S::Error> {
if self.is_empty() || core::mem::size_of::<T::Archived>() == 0 {
Expand Down Expand Up @@ -358,7 +358,7 @@ impl<T: Serialize<S>, S: Serializer + ?Sized> SerializeUnsized<S> for [T] {
}

#[cfg(all(feature = "std", feature = "copy"))]
impl<T: Serialize<S> + crate::copy::ArchiveCopySafe, S: Serializer + ?Sized> SerializeUnsized<S> for [T] {
impl<T: Serialize<S> + crate::copy::ArchiveCopyOptimize, S: Serializer + ?Sized> SerializeUnsized<S> for [T] {
#[inline]
fn serialize_unsized(&self, serializer: &mut S) -> Result<usize, S::Error> {
if self.is_empty() || core::mem::size_of::<T::Archived>() == 0 {
Expand Down Expand Up @@ -411,7 +411,7 @@ impl<T: Deserialize<U, D>, U, D: Deserializer + ?Sized>
}

#[cfg(feature = "copy")]
impl<T: Deserialize<U, D>, U: ArchiveCopySafe, D: Deserializer + ?Sized>
impl<T: Deserialize<U, D>, U: ArchiveCopyOptimize, D: Deserializer + ?Sized>
DeserializeUnsized<[U], D> for [T]
{
#[inline]
Expand Down
1 change: 1 addition & 0 deletions rkyv_test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ archive_be = ["rkyv/archive_be"]
archive_le = ["rkyv/archive_le"]
const_generics = ["rkyv/const_generics"]
copy = ["rkyv/copy"]
copy_unsafe = ["rkyv/copy_unsafe"]
size_64 = ["rkyv/size_64"]
std = ["rkyv/std"]
strict = ["rkyv/strict"]
Expand Down

0 comments on commit a753588

Please sign in to comment.