You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

yoke

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

yoke - cargo Package Compare versions

Comparing version
0.7.1
to
0.7.2
+94
src/kinda_sorta_dangling.rs
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
use core::mem::{ManuallyDrop, MaybeUninit};
use core::ops::{Deref, DerefMut};
/// This type is intended to be similar to the type `MaybeDangling<T>`
/// proposed in [RFC 3336].
///
/// The effect of this is that in Rust's safety model, types inside here are not
/// expected to have any memory dependent validity properties (`dereferenceable`, `noalias`).
///
/// See [#3696] for a testcase where `Yoke` fails this under miri's field-retagging mode.
///
/// This has `T: 'static` since we don't need anything
/// else and we don't want to have to think (more) about variance over lifetimes or dropck.
///
/// After [RFC 3336] lands we can use `MaybeDangling` instead.
///
/// Note that a version of this type also exists publicly as the [`maybe_dangling`]
/// crate; which also exports a patched `ManuallyDrop` with similar semantics and
/// does not require `T: 'static`. Consider using this if you need something more general
/// and are okay with adding dependencies.
///
/// [RFC 3336]: https://github.com/rust-lang/rfcs/pull/3336
/// [#3696]: https://github.com/unicode-org/icu4x/issues/3696
/// [`maybe_dangling`](https://docs.rs/maybe-dangling/0.1.0/maybe_dangling/struct.MaybeDangling.html)
#[repr(transparent)]
pub(crate) struct KindaSortaDangling<T: 'static> {
/// Safety invariant: This is always an initialized T, never uninit or other
/// invalid bit patterns. Its drop glue will execute during Drop::drop rather than
/// during the drop glue for KindaSortaDangling, which means that we have to be careful about
/// not touching the values as initialized during `drop` after that, but that's a short period of time.
dangle: MaybeUninit<T>,
}
impl<T: 'static> KindaSortaDangling<T> {
#[inline]
pub(crate) const fn new(dangle: T) -> Self {
KindaSortaDangling {
dangle: MaybeUninit::new(dangle),
}
}
#[inline]
pub(crate) fn into_inner(self) -> T {
// Self has a destructor, we want to avoid having it be called
let manual = ManuallyDrop::new(self);
// Safety:
// We can call assume_init_read() due to the library invariant on this type,
// however since it is a read() we must be careful about data duplication.
// The only code using `self` after this is the drop glue, which we have disabled via
// the ManuallyDrop.
unsafe { manual.dangle.assume_init_read() }
}
}
impl<T: 'static> Deref for KindaSortaDangling<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
// Safety: Safe due to the safety invariant on `dangle`;
// we can always assume initialized
unsafe { self.dangle.assume_init_ref() }
}
}
impl<T: 'static> DerefMut for KindaSortaDangling<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
// Safety: Safe due to the safety invariant on `dangle`;
// we can always assume initialized
unsafe { self.dangle.assume_init_mut() }
}
}
impl<T: 'static> Drop for KindaSortaDangling<T> {
#[inline]
fn drop(&mut self) {
unsafe {
// Safety: We are reading and dropping a valid initialized T.
//
// As `drop_in_place()` is a `read()`-like duplication operation we must be careful that the original value isn't
// used afterwards. It won't be because this is drop and the only
// code that will run after this is `self`'s drop glue, and that drop glue is empty
// because MaybeUninit has no drop.
//
// We use `drop_in_place()` instead of `let _ = ... .assume_init_read()` to avoid creating a move
// of the inner `T` (without `KindaSortaDangling` protection!) type into a local -- we don't want to
// assert any of `T`'s memory-related validity properties here.
self.dangle.as_mut_ptr().drop_in_place();
}
}
}
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
// This test is a duplicate of one of the doctests, but is written separately
// since `cargo miri test` doesn't work on doctests yet
use std::borrow::Cow;
use std::mem;
use std::rc::Rc;
use yoke::{Yoke, Yokeable};
fn load_from_cache(_filename: &str) -> Rc<[u8]> {
// dummy implementation
Rc::new([0x5, 0, 0, 0, 0, 0, 0, 0, 0x68, 0x65, 0x6c, 0x6c, 0x6f])
}
fn load_object(filename: &str) -> Yoke<Bar<'static>, Rc<[u8]>> {
let rc: Rc<[u8]> = load_from_cache(filename);
Yoke::<Bar<'static>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| {
// A real implementation would properly deserialize `Bar` as a whole
Bar {
numbers: Cow::Borrowed(bincode::deserialize(data).unwrap()),
string: Cow::Borrowed(bincode::deserialize(data).unwrap()),
owned: Vec::new(),
}
})
}
// also implements Yokeable
struct Bar<'a> {
numbers: Cow<'a, [u8]>,
string: Cow<'a, str>,
owned: Vec<u8>,
}
unsafe impl<'a> Yokeable<'a> for Bar<'static> {
type Output = Bar<'a>;
#[inline]
fn transform(&'a self) -> &'a Bar<'a> {
self
}
#[inline]
fn transform_owned(self) -> Bar<'a> {
self
}
#[inline]
unsafe fn make(from: Bar<'a>) -> Self {
let ret = mem::transmute_copy(&from);
mem::forget(from);
ret
}
#[inline]
fn transform_mut<F>(&'a mut self, f: F)
where
F: 'static + FnOnce(&'a mut Self::Output),
{
unsafe { f(mem::transmute(self)) }
}
}
#[test]
fn test_load() {
// `load_object()` deserializes an object from a file
let mut bar = load_object("filename.bincode");
assert_eq!(bar.get().string, "hello");
assert!(matches!(bar.get().string, Cow::Borrowed(_)));
assert_eq!(&*bar.get().numbers, &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);
assert!(matches!(bar.get().numbers, Cow::Borrowed(_)));
assert_eq!(&*bar.get().owned, &[]);
bar.with_mut(|bar| {
bar.string.to_mut().push_str(" world");
bar.owned.extend_from_slice(&[1, 4, 1, 5, 9]);
});
assert_eq!(bar.get().string, "hello world");
assert!(matches!(bar.get().string, Cow::Owned(_)));
assert_eq!(&*bar.get().owned, &[1, 4, 1, 5, 9]);
// Unchanged and still Cow::Borrowed
assert_eq!(&*bar.get().numbers, &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);
assert!(matches!(bar.get().numbers, Cow::Borrowed(_)));
}
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
use yoke::Yoke;
// Test for strong protection, should pass under miri with -Zmiri-retag-fields
// See https://github.com/unicode-org/icu4x/issues/3696
fn example(_: Yoke<&'static [u8], Vec<u8>>) {}
#[test]
fn run_test() {
example(Yoke::attach_to_cart(vec![0, 1, 2], |data| data));
}
+1
-1
{
"git": {
"sha1": "cd80fbfd24ecc6e499fb5fc6bb8fcce6b14416f4"
"sha1": "e16ba527854ca0edc36695e4e65fdcbc4dccd188"
},
"path_in_vcs": "utils/yoke"
}

@@ -14,9 +14,12 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO

edition = "2021"
rust-version = "1.66"
name = "yoke"
version = "0.7.1"
version = "0.7.2"
authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
include = [
"data/**/*",
"src/**/*",
"examples/**/*",
"benches/**/*",
"tests/**/*",
"Cargo.toml",

@@ -41,7 +44,7 @@ "LICENSE",

]
license = "Unicode-DFS-2016"
license-file = "LICENSE"
repository = "https://github.com/unicode-org/icu4x"
[package.metadata.workspaces]
independent = true
[package.metadata.cargo-all-features]
max_combination_size = 3

@@ -51,2 +54,5 @@ [package.metadata.docs.rs]

[package.metadata.workspaces]
independent = true
[dependencies.serde]

@@ -62,4 +68,5 @@ version = "1.0"

[dependencies.yoke-derive]
version = "0.7.0"
version = "0.7.1"
optional = true
default-features = false

@@ -91,1 +98,3 @@ [dependencies.zerofrom]

]
serde = ["dep:serde"]
zerofrom = ["dep:zerofrom"]
+32
-39

@@ -1,47 +0,40 @@

UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
UNICODE LICENSE V3
See Terms of Use <https://www.unicode.org/copyright.html>
for definitions of Unicode Inc.’s Data Files and Software.
COPYRIGHT AND PERMISSION NOTICE
NOTICE TO USER: Carefully read the following legal agreement.
BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT.
IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
THE DATA FILES OR SOFTWARE.
Copyright © 2020-2023 Unicode, Inc.
COPYRIGHT AND PERMISSION NOTICE
NOTICE TO USER: Carefully read the following legal agreement. BY
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
Copyright © 1991-2022 Unicode, Inc. All rights reserved.
Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
Permission is hereby granted, free of charge, to any person obtaining a
copy of data files and any associated documentation (the "Data Files") or
software and any associated documentation (the "Software") to deal in the
Data Files or Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, and/or sell
copies of the Data Files or Software, and to permit persons to whom the
Data Files or Software are furnished to do so, provided that either (a)
this copyright and permission notice appear with all copies of the Data
Files or Software, or (b) this copyright and permission notice appear in
associated Documentation.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Unicode data files and any associated documentation
(the "Data Files") or Unicode software and any associated documentation
(the "Software") to deal in the Data Files or Software
without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, and/or sell copies of
the Data Files or Software, and to permit persons to whom the Data Files
or Software are furnished to do so, provided that either
(a) this copyright and permission notice appear with all copies
of the Data Files or Software, or
(b) this copyright and permission notice appear in associated
Documentation.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
THIRD PARTY RIGHTS.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THE DATA FILES OR SOFTWARE.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
FILES OR SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in these Data Files or Software without prior
written authorization of the copyright holder.
Except as contained in this notice, the name of a copyright holder shall
not be used in advertising or otherwise to promote the sale, use or other
dealings in these Data Files or Software without prior written
authorization of the copyright holder.

@@ -48,0 +41,0 @@

# yoke [![crates.io](https://img.shields.io/crates/v/yoke)](https://crates.io/crates/yoke)
<!-- cargo-rdme start -->
This crate provides [`Yoke<Y, C>`][Yoke], which allows one to "yoke" (attach) a zero-copy deserialized

@@ -25,4 +27,6 @@ object (say, a [`Cow<'a, str>`](alloc::borrow::Cow)) to the source it was deserialized from, (say, an [`Rc<[u8]>`](alloc::rc::Rc)),

<!-- cargo-rdme end -->
## More Information
For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x).

@@ -10,3 +10,3 @@ // This file is part of ICU4X. For terms of use, please see the file

//!
//! Available with the `"alloc"` Cargo feature enabled.
//! ✨ *Enabled with the `alloc` Cargo feature.*

@@ -29,3 +29,3 @@ use alloc::boxed::Box;

///
/// Available with the `"alloc"` Cargo feature enabled.
/// ✨ *Enabled with the `alloc` Cargo feature.*
pub type ErasedArcCart = Arc<dyn ErasedDestructor + Send + Sync>;

@@ -36,3 +36,3 @@ /// A type-erased Cart that has `Rc` semantics

///
/// Available with the `"alloc"` Cargo feature enabled.
/// ✨ *Enabled with the `alloc` Cargo feature.*
pub type ErasedRcCart = Rc<dyn ErasedDestructor>;

@@ -43,3 +43,3 @@ /// A type-erased Cart that has `Box` semantics

///
/// Available with the `"alloc"` Cargo feature enabled.
/// ✨ *Enabled with the `alloc` Cargo feature.*
pub type ErasedBoxCart = Box<dyn ErasedDestructor>;

@@ -51,2 +51,3 @@ // This file is part of ICU4X. For terms of use, please see the file

pub mod erased;
mod kinda_sorta_dangling;
mod macro_impls;

@@ -53,0 +54,0 @@ pub mod trait_hack;

@@ -8,2 +8,3 @@ // This file is part of ICU4X. For terms of use, please see the file

use crate::erased::{ErasedArcCart, ErasedBoxCart, ErasedRcCart};
use crate::kinda_sorta_dangling::KindaSortaDangling;
use crate::trait_hack::YokeTraitHack;

@@ -78,10 +79,35 @@ use crate::Yokeable;

/// ```
#[derive(Debug)]
pub struct Yoke<Y: for<'a> Yokeable<'a>, C> {
// must be the first field for drop order
// this will have a 'static lifetime parameter, that parameter is a lie
yokeable: Y,
yokeable: KindaSortaDangling<Y>,
cart: C,
}
// Manual `Debug` implementation, since the derived one would be unsound.
// See https://github.com/unicode-org/icu4x/issues/3685
impl<Y: for<'a> Yokeable<'a>, C: core::fmt::Debug> core::fmt::Debug for Yoke<Y, C>
where
for<'a> <Y as Yokeable<'a>>::Output: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Yoke")
.field("yokeable", self.get())
.field("cart", self.backing_cart())
.finish()
}
}
#[test]
fn test_debug() {
let local_data = "foo".to_owned();
let y1 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(
Rc::new(local_data),
);
assert_eq!(
format!("{y1:?}"),
r#"Yoke { yokeable: "foo", cart: "foo" }"#,
);
}
impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C>

@@ -134,3 +160,3 @@ where

Self {
yokeable: unsafe { Y::make(deserialized) },
yokeable: KindaSortaDangling::new(unsafe { Y::make(deserialized) }),
cart,

@@ -151,3 +177,3 @@ }

Ok(Self {
yokeable: unsafe { Y::make(deserialized) },
yokeable: KindaSortaDangling::new(unsafe { Y::make(deserialized) }),
cart,

@@ -425,3 +451,6 @@ })

pub fn new_always_owned(yokeable: Y) -> Self {
Self { yokeable, cart: () }
Self {
yokeable: KindaSortaDangling::new(yokeable),
cart: (),
}
}

@@ -435,3 +464,3 @@

pub fn into_yokeable(self) -> Y {
self.yokeable
self.yokeable.into_inner()
}

@@ -465,5 +494,5 @@ }

/// ```
pub fn new_owned(yokeable: Y) -> Self {
pub const fn new_owned(yokeable: Y) -> Self {
Self {
yokeable,
yokeable: KindaSortaDangling::new(yokeable),
cart: None,

@@ -480,3 +509,3 @@ }

Some(_) => Err(self),
None => Ok(self.yokeable),
None => Ok(self.yokeable.into_inner()),
}

@@ -527,3 +556,3 @@ }

Yoke {
yokeable: unsafe { Y::make(this_hack.clone().0) },
yokeable: KindaSortaDangling::new(unsafe { Y::make(this_hack.clone().0) }),
cart: self.cart.clone(),

@@ -642,5 +671,5 @@ }

{
let p = f(self.yokeable.transform_owned(), PhantomData);
let p = f(self.yokeable.into_inner().transform_owned(), PhantomData);
Yoke {
yokeable: unsafe { P::make(p) },
yokeable: KindaSortaDangling::new(unsafe { P::make(p) }),
cart: self.cart,

@@ -666,3 +695,3 @@ }

Yoke {
yokeable: unsafe { P::make(p) },
yokeable: KindaSortaDangling::new(unsafe { P::make(p) }),
cart: self.cart.clone(),

@@ -742,5 +771,5 @@ }

{
let p = f(self.yokeable.transform_owned(), PhantomData)?;
let p = f(self.yokeable.into_inner().transform_owned(), PhantomData)?;
Ok(Yoke {
yokeable: unsafe { P::make(p) },
yokeable: KindaSortaDangling::new(unsafe { P::make(p) }),
cart: self.cart,

@@ -766,3 +795,3 @@ })

Ok(Yoke {
yokeable: unsafe { P::make(p) },
yokeable: KindaSortaDangling::new(unsafe { P::make(p) }),
cart: self.cart.clone(),

@@ -788,5 +817,9 @@ })

{
let p = f(self.yokeable.transform_owned(), capture, PhantomData);
let p = f(
self.yokeable.into_inner().transform_owned(),
capture,
PhantomData,
);
Yoke {
yokeable: unsafe { P::make(p) },
yokeable: KindaSortaDangling::new(unsafe { P::make(p) }),
cart: self.cart,

@@ -816,3 +849,3 @@ }

Yoke {
yokeable: unsafe { P::make(p) },
yokeable: KindaSortaDangling::new(unsafe { P::make(p) }),
cart: self.cart.clone(),

@@ -840,5 +873,9 @@ }

{
let p = f(self.yokeable.transform_owned(), capture, PhantomData)?;
let p = f(
self.yokeable.into_inner().transform_owned(),
capture,
PhantomData,
)?;
Ok(Yoke {
yokeable: unsafe { P::make(p) },
yokeable: KindaSortaDangling::new(unsafe { P::make(p) }),
cart: self.cart,

@@ -869,3 +906,3 @@ })

Ok(Yoke {
yokeable: unsafe { P::make(p) },
yokeable: KindaSortaDangling::new(unsafe { P::make(p) }),
cart: self.cart.clone(),

@@ -890,2 +927,4 @@ })

///
/// ✨ *Enabled with the `alloc` Cargo feature.*
///
/// # Example

@@ -912,4 +951,2 @@ ///

/// ```
///
/// Available with the `"alloc"` Cargo feature enabled.
pub fn erase_rc_cart(self) -> Yoke<Y, ErasedRcCart> {

@@ -938,2 +975,4 @@ unsafe {

///
/// ✨ *Enabled with the `alloc` Cargo feature.*
///
/// # Example

@@ -960,4 +999,2 @@ ///

/// ```
///
/// Available with the `"alloc"` Cargo feature enabled.
pub fn erase_arc_cart(self) -> Yoke<Y, ErasedArcCart> {

@@ -986,2 +1023,4 @@ unsafe {

///
/// ✨ *Enabled with the `alloc` Cargo feature.*
///
/// # Example

@@ -1008,4 +1047,2 @@ ///

/// ```
///
/// Available with the `"alloc"` Cargo feature enabled.
pub fn erase_box_cart(self) -> Yoke<Y, ErasedBoxCart> {

@@ -1025,3 +1062,3 @@ unsafe {

///
/// Available with the `"alloc"` Cargo feature enabled.
/// ✨ *Enabled with the `alloc` Cargo feature.*
#[inline]

@@ -1038,3 +1075,3 @@ pub fn wrap_cart_in_box(self) -> Yoke<Y, Box<C>> {

///
/// Available with the `"alloc"` Cargo feature enabled.
/// ✨ *Enabled with the `alloc` Cargo feature.*
#[inline]

@@ -1051,3 +1088,3 @@ pub fn wrap_cart_in_rc(self) -> Yoke<Y, Rc<C>> {

///
/// Available with the `"alloc"` Cargo feature enabled.
/// ✨ *Enabled with the `alloc` Cargo feature.*
#[inline]

@@ -1054,0 +1091,0 @@ pub fn wrap_cart_in_arc(self) -> Yoke<Y, Arc<C>> {

Sorry, the diff of this file is not supported yet