Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/triomphe/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/triomphe/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"3d22669254499496ef7984f900e71d128fd20a9593f98b2bd5c243dc2c661004","LICENSE-APACHE":"a6b7260485462860838b76ad1846d21f1605e6d239141c3aa949a601d992676c","LICENSE-MIT":"15656cc11a8331f28c0986b8ab97220d3e76f98e60ed388b5ffad37dfac4710c","README.md":"31f2d36aba753938cca35a0770f87b14215d6b367a1cd173f183d49242890258","src/arc.rs":"f257f159041c7e7b1bdde3942eea81e364a3a7fb4a1a38f771e8df79a266788d","src/arc_borrow.rs":"a560a837d4976a5e388d2ee49b751a0077607e29fb063fffa7cccbe8fa28d1d6","src/arc_swap_support.rs":"54213ddea959fec13f1af4efb94271a9b85c531c06649899ddf8d6b939615d05","src/arc_union.rs":"b623adb5bf6f0911b5230658ad4e054d76569dc0e75fbccf41fa666112775766","src/header.rs":"0a7ead5c03d3ebf3fe20fde20eced35489f3d8c53c179a53169e68c0090b6bdb","src/iterator_as_exact_size_iterator.rs":"cae199c33fb172eb63455c0290a70ac72a7a9f6d26cf30d691560470b08524a4","src/lib.rs":"66c33fbe65220852ca04347b36da3040411d39a03ca5bec6001f5358cf56af72","src/offset_arc.rs":"86ea6733383d9024bae4e8383ed7c2dcf835615b3bd17f763148e08000cd93ef","src/thin_arc.rs":"456b43ee92d94c6cfd1b3c14f96b68bfd3501d5395b7941f0f23588ed36a50e0","src/unique_arc.rs":"0731c864a37f89f4708fda530572ba6f563da56ad1b70a2f54dc5baa434e1a0d"},"package":"859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3"}
|
||||
55
third-party/vendor/triomphe/Cargo.toml
vendored
Normal file
55
third-party/vendor/triomphe/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
name = "triomphe"
|
||||
version = "0.1.11"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "A fork of std::sync::Arc with some extra functionality and without weak references (originally servo_arc)"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"arc",
|
||||
"ffi",
|
||||
"sync",
|
||||
"data-structure",
|
||||
]
|
||||
categories = [
|
||||
"concurrency",
|
||||
"data-structures",
|
||||
]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/Manishearth/triomphe"
|
||||
|
||||
[dependencies.arc-swap]
|
||||
version = "1.3.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.stable_deref_trait]
|
||||
version = "1.1.1"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.unsize]
|
||||
version = "1.1"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = [
|
||||
"serde",
|
||||
"stable_deref_trait",
|
||||
"std",
|
||||
]
|
||||
std = []
|
||||
201
third-party/vendor/triomphe/LICENSE-APACHE
vendored
Normal file
201
third-party/vendor/triomphe/LICENSE-APACHE
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
27
third-party/vendor/triomphe/LICENSE-MIT
vendored
Normal file
27
third-party/vendor/triomphe/LICENSE-MIT
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Manish Goregaokar
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS 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. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
13
third-party/vendor/triomphe/README.md
vendored
Normal file
13
third-party/vendor/triomphe/README.md
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Triomphe
|
||||
|
||||
Fork of Arc. This has the following advantages over std::sync::Arc:
|
||||
|
||||
* `triomphe::Arc` doesn't support weak references: we save space by excluding the weak reference count, and we don't do extra read-modify-update operations to handle the possibility of weak references.
|
||||
* `triomphe::UniqueArc` allows one to construct a temporarily-mutable `Arc` which can be converted to a regular `triomphe::Arc` later
|
||||
* `triomphe::OffsetArc` can be used transparently from C++ code and is compatible with (and can be converted to/from) `triomphe::Arc`
|
||||
* `triomphe::ArcBorrow` is functionally similar to `&triomphe::Arc<T>`, however in memory it's simply `&T`. This makes it more flexible for FFI; the source of the borrow need not be an `Arc` pinned on the stack (and can instead be a pointer from C++, or an `OffsetArc`). Additionally, this helps avoid pointer-chasing.
|
||||
* `triomphe::Arc` has can be constructed for dynamically-sized types via `from_header_and_iter`
|
||||
* `triomphe::ThinArc` provides thin-pointer `Arc`s to dynamically sized types
|
||||
* `triomphe::ArcUnion` is union of two `triomphe:Arc`s which fits inside one word of memory
|
||||
|
||||
This crate is a version of `servo_arc` meant for general community use.
|
||||
1039
third-party/vendor/triomphe/src/arc.rs
vendored
Normal file
1039
third-party/vendor/triomphe/src/arc.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
118
third-party/vendor/triomphe/src/arc_borrow.rs
vendored
Normal file
118
third-party/vendor/triomphe/src/arc_borrow.rs
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
use core::mem;
|
||||
use core::mem::ManuallyDrop;
|
||||
use core::ops::Deref;
|
||||
use core::ptr;
|
||||
|
||||
use super::Arc;
|
||||
|
||||
/// A "borrowed `Arc`". This is a pointer to
|
||||
/// a T that is known to have been allocated within an
|
||||
/// `Arc`.
|
||||
///
|
||||
/// This is equivalent in guarantees to `&Arc<T>`, however it is
|
||||
/// a bit more flexible. To obtain an `&Arc<T>` you must have
|
||||
/// an `Arc<T>` instance somewhere pinned down until we're done with it.
|
||||
/// It's also a direct pointer to `T`, so using this involves less pointer-chasing
|
||||
///
|
||||
/// However, C++ code may hand us refcounted things as pointers to T directly,
|
||||
/// so we have to conjure up a temporary `Arc` on the stack each time. The
|
||||
/// same happens for when the object is managed by a `OffsetArc`.
|
||||
///
|
||||
/// `ArcBorrow` lets us deal with borrows of known-refcounted objects
|
||||
/// without needing to worry about where the `Arc<T>` is.
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[repr(transparent)]
|
||||
pub struct ArcBorrow<'a, T: ?Sized + 'a>(pub(crate) &'a T);
|
||||
|
||||
impl<'a, T> Copy for ArcBorrow<'a, T> {}
|
||||
impl<'a, T> Clone for ArcBorrow<'a, T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ArcBorrow<'a, T> {
|
||||
/// Clone this as an `Arc<T>`. This bumps the refcount.
|
||||
#[inline]
|
||||
pub fn clone_arc(&self) -> Arc<T> {
|
||||
let arc = unsafe { Arc::from_raw(self.0) };
|
||||
// addref it!
|
||||
mem::forget(arc.clone());
|
||||
arc
|
||||
}
|
||||
|
||||
/// For constructing from a reference known to be Arc-backed,
|
||||
/// e.g. if we obtain such a reference over FFI
|
||||
/// TODO: should from_ref be relaxed to unsized types? It can't be
|
||||
/// converted back to an Arc right now for unsized types.
|
||||
/// # Safety
|
||||
/// - The reference to `T` must have come from a Triomphe Arc, UniqueArc, or ArcBorrow.
|
||||
#[inline]
|
||||
pub unsafe fn from_ref(r: &'a T) -> Self {
|
||||
ArcBorrow(r)
|
||||
}
|
||||
|
||||
/// Compare two `ArcBorrow`s via pointer equality. Will only return
|
||||
/// true if they come from the same allocation
|
||||
#[inline]
|
||||
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
|
||||
ptr::eq(this.0 as *const T, other.0 as *const T)
|
||||
}
|
||||
|
||||
/// Temporarily converts |self| into a bonafide Arc and exposes it to the
|
||||
/// provided callback. The refcount is not modified.
|
||||
#[inline]
|
||||
pub fn with_arc<F, U>(&self, f: F) -> U
|
||||
where
|
||||
F: FnOnce(&Arc<T>) -> U,
|
||||
T: 'static,
|
||||
{
|
||||
// Synthesize transient Arc, which never touches the refcount.
|
||||
let transient = unsafe { ManuallyDrop::new(Arc::from_raw(self.0)) };
|
||||
|
||||
// Expose the transient Arc to the callback, which may clone it if it wants
|
||||
// and forward the result to the user
|
||||
f(&transient)
|
||||
}
|
||||
|
||||
/// Similar to deref, but uses the lifetime |a| rather than the lifetime of
|
||||
/// self, which is incompatible with the signature of the Deref trait.
|
||||
#[inline]
|
||||
pub fn get(&self) -> &'a T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for ArcBorrow<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
// Safety:
|
||||
// This implementation must guarantee that it is sound to call replace_ptr with an unsized variant
|
||||
// of the pointer retuned in `as_sized_ptr`. We leverage unsizing the contained reference. This
|
||||
// continues to point to the data of an ArcInner. The reference count remains untouched which is
|
||||
// correct since the number of owners did not change. This implies the returned instance fulfills
|
||||
// its safety invariants.
|
||||
#[cfg(feature = "unsize")]
|
||||
unsafe impl<'lt, T: 'lt, U: ?Sized + 'lt> unsize::CoerciblePtr<U> for ArcBorrow<'lt, T> {
|
||||
type Pointee = T;
|
||||
type Output = ArcBorrow<'lt, U>;
|
||||
|
||||
fn as_sized_ptr(&mut self) -> *mut T {
|
||||
// Returns a pointer to the inner data. We do not need to care about any particular
|
||||
// provenance here, only the pointer value, which we need to reconstruct the new pointer.
|
||||
self.0 as *const T as *mut T
|
||||
}
|
||||
|
||||
unsafe fn replace_ptr(self, new: *mut U) -> ArcBorrow<'lt, U> {
|
||||
let inner = ManuallyDrop::new(self);
|
||||
// Safety: backed by the same Arc that backed `self`.
|
||||
ArcBorrow(inner.0.replace_ptr(new))
|
||||
}
|
||||
}
|
||||
42
third-party/vendor/triomphe/src/arc_swap_support.rs
vendored
Normal file
42
third-party/vendor/triomphe/src/arc_swap_support.rs
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use arc_swap::RefCnt;
|
||||
|
||||
use crate::{Arc, ThinArc};
|
||||
use core::ffi::c_void;
|
||||
|
||||
unsafe impl<H, T> RefCnt for ThinArc<H, T> {
|
||||
type Base = c_void;
|
||||
|
||||
#[inline]
|
||||
fn into_ptr(me: Self) -> *mut Self::Base {
|
||||
ThinArc::into_raw(me) as *mut _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(me: &Self) -> *mut Self::Base {
|
||||
ThinArc::as_ptr(me) as *mut _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: *const Self::Base) -> Self {
|
||||
ThinArc::from_raw(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> RefCnt for Arc<T> {
|
||||
type Base = T;
|
||||
|
||||
#[inline]
|
||||
fn into_ptr(me: Self) -> *mut Self::Base {
|
||||
Arc::into_raw(me) as *mut _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(me: &Self) -> *mut Self::Base {
|
||||
Arc::as_ptr(me) as *mut _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: *const Self::Base) -> Self {
|
||||
Arc::from_raw(ptr)
|
||||
}
|
||||
}
|
||||
139
third-party/vendor/triomphe/src/arc_union.rs
vendored
Normal file
139
third-party/vendor/triomphe/src/arc_union.rs
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
use core::ptr;
|
||||
use core::usize;
|
||||
|
||||
use super::{Arc, ArcBorrow};
|
||||
|
||||
/// A tagged union that can represent `Arc<A>` or `Arc<B>` while only consuming a
|
||||
/// single word. The type is also `NonNull`, and thus can be stored in an Option
|
||||
/// without increasing size.
|
||||
///
|
||||
/// This is functionally equivalent to
|
||||
/// `enum ArcUnion<A, B> { First(Arc<A>), Second(Arc<B>)` but only takes up
|
||||
/// up a single word of stack space.
|
||||
///
|
||||
/// This could probably be extended to support four types if necessary.
|
||||
pub struct ArcUnion<A, B> {
|
||||
p: ptr::NonNull<()>,
|
||||
phantom_a: PhantomData<A>,
|
||||
phantom_b: PhantomData<B>,
|
||||
}
|
||||
|
||||
unsafe impl<A: Sync + Send, B: Send + Sync> Send for ArcUnion<A, B> {}
|
||||
unsafe impl<A: Sync + Send, B: Send + Sync> Sync for ArcUnion<A, B> {}
|
||||
|
||||
impl<A: PartialEq, B: PartialEq> PartialEq for ArcUnion<A, B> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
use crate::ArcUnionBorrow::*;
|
||||
match (self.borrow(), other.borrow()) {
|
||||
(First(x), First(y)) => x == y,
|
||||
(Second(x), Second(y)) => x == y,
|
||||
(_, _) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This represents a borrow of an `ArcUnion`.
|
||||
#[derive(Debug)]
|
||||
pub enum ArcUnionBorrow<'a, A: 'a, B: 'a> {
|
||||
First(ArcBorrow<'a, A>),
|
||||
Second(ArcBorrow<'a, B>),
|
||||
}
|
||||
|
||||
impl<A, B> ArcUnion<A, B> {
|
||||
unsafe fn new(ptr: *mut ()) -> Self {
|
||||
ArcUnion {
|
||||
p: ptr::NonNull::new_unchecked(ptr),
|
||||
phantom_a: PhantomData,
|
||||
phantom_b: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the two values are pointer-equal.
|
||||
#[inline]
|
||||
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
|
||||
this.p == other.p
|
||||
}
|
||||
|
||||
/// Returns an enum representing a borrow of either A or B.
|
||||
pub fn borrow(&self) -> ArcUnionBorrow<A, B> {
|
||||
if self.is_first() {
|
||||
let ptr = self.p.as_ptr() as *const A;
|
||||
let borrow = unsafe { ArcBorrow::from_ref(&*ptr) };
|
||||
ArcUnionBorrow::First(borrow)
|
||||
} else {
|
||||
let ptr = ((self.p.as_ptr() as usize) & !0x1) as *const B;
|
||||
let borrow = unsafe { ArcBorrow::from_ref(&*ptr) };
|
||||
ArcUnionBorrow::Second(borrow)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an `ArcUnion` from an instance of the first type.
|
||||
#[inline]
|
||||
pub fn from_first(other: Arc<A>) -> Self {
|
||||
unsafe { Self::new(Arc::into_raw(other) as *mut _) }
|
||||
}
|
||||
|
||||
/// Creates an `ArcUnion` from an instance of the second type.
|
||||
#[inline]
|
||||
pub fn from_second(other: Arc<B>) -> Self {
|
||||
unsafe { Self::new(((Arc::into_raw(other) as usize) | 0x1) as *mut _) }
|
||||
}
|
||||
|
||||
/// Returns true if this `ArcUnion` contains the first type.
|
||||
#[inline]
|
||||
pub fn is_first(&self) -> bool {
|
||||
self.p.as_ptr() as usize & 0x1 == 0
|
||||
}
|
||||
|
||||
/// Returns true if this `ArcUnion` contains the second type.
|
||||
#[inline]
|
||||
pub fn is_second(&self) -> bool {
|
||||
!self.is_first()
|
||||
}
|
||||
|
||||
/// Returns a borrow of the first type if applicable, otherwise `None`.
|
||||
pub fn as_first(&self) -> Option<ArcBorrow<A>> {
|
||||
match self.borrow() {
|
||||
ArcUnionBorrow::First(x) => Some(x),
|
||||
ArcUnionBorrow::Second(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a borrow of the second type if applicable, otherwise None.
|
||||
pub fn as_second(&self) -> Option<ArcBorrow<B>> {
|
||||
match self.borrow() {
|
||||
ArcUnionBorrow::First(_) => None,
|
||||
ArcUnionBorrow::Second(x) => Some(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> Clone for ArcUnion<A, B> {
|
||||
fn clone(&self) -> Self {
|
||||
match self.borrow() {
|
||||
ArcUnionBorrow::First(x) => ArcUnion::from_first(x.clone_arc()),
|
||||
ArcUnionBorrow::Second(x) => ArcUnion::from_second(x.clone_arc()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> Drop for ArcUnion<A, B> {
|
||||
fn drop(&mut self) {
|
||||
match self.borrow() {
|
||||
ArcUnionBorrow::First(x) => unsafe {
|
||||
let _ = Arc::from_raw(&*x);
|
||||
},
|
||||
ArcUnionBorrow::Second(x) => unsafe {
|
||||
let _ = Arc::from_raw(&*x);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: fmt::Debug, B: fmt::Debug> fmt::Debug for ArcUnion<A, B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.borrow(), f)
|
||||
}
|
||||
}
|
||||
391
third-party/vendor/triomphe/src/header.rs
vendored
Normal file
391
third-party/vendor/triomphe/src/header.rs
vendored
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
use alloc::alloc::Layout;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use core::cmp::Ordering;
|
||||
use core::iter::{ExactSizeIterator, Iterator};
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::{self, ManuallyDrop};
|
||||
use core::ptr::{self, addr_of_mut};
|
||||
use core::usize;
|
||||
|
||||
use super::{Arc, ArcInner};
|
||||
|
||||
/// Structure to allow Arc-managing some fixed-sized data and a variably-sized
|
||||
/// slice in a single allocation.
|
||||
#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
|
||||
#[repr(C)]
|
||||
pub struct HeaderSlice<H, T: ?Sized> {
|
||||
/// The fixed-sized data.
|
||||
pub header: H,
|
||||
|
||||
/// The dynamically-sized data.
|
||||
pub slice: T,
|
||||
}
|
||||
|
||||
impl<H, T> Arc<HeaderSlice<H, [T]>> {
|
||||
/// Creates an Arc for a HeaderSlice using the given header struct and
|
||||
/// iterator to generate the slice. The resulting Arc will be fat.
|
||||
pub fn from_header_and_iter<I>(header: H, mut items: I) -> Self
|
||||
where
|
||||
I: Iterator<Item = T> + ExactSizeIterator,
|
||||
{
|
||||
assert_ne!(mem::size_of::<T>(), 0, "Need to think about ZST");
|
||||
|
||||
let num_items = items.len();
|
||||
|
||||
let inner = Arc::allocate_for_header_and_slice(num_items);
|
||||
|
||||
unsafe {
|
||||
// Write the data.
|
||||
//
|
||||
// Note that any panics here (i.e. from the iterator) are safe, since
|
||||
// we'll just leak the uninitialized memory.
|
||||
ptr::write(&mut ((*inner.as_ptr()).data.header), header);
|
||||
if num_items != 0 {
|
||||
let mut current = (*inner.as_ptr()).data.slice.as_mut_ptr();
|
||||
for _ in 0..num_items {
|
||||
ptr::write(
|
||||
current,
|
||||
items
|
||||
.next()
|
||||
.expect("ExactSizeIterator over-reported length"),
|
||||
);
|
||||
current = current.offset(1);
|
||||
}
|
||||
assert!(
|
||||
items.next().is_none(),
|
||||
"ExactSizeIterator under-reported length"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
items.next().is_none(),
|
||||
"ExactSizeIterator under-reported length"
|
||||
);
|
||||
}
|
||||
|
||||
// Safety: ptr is valid & the inner structure is fully initialized
|
||||
Arc {
|
||||
p: inner,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an Arc for a HeaderSlice using the given header struct and
|
||||
/// iterator to generate the slice. The resulting Arc will be fat.
|
||||
pub fn from_header_and_slice(header: H, items: &[T]) -> Self
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
assert_ne!(mem::size_of::<T>(), 0, "Need to think about ZST");
|
||||
|
||||
let num_items = items.len();
|
||||
|
||||
let inner = Arc::allocate_for_header_and_slice(num_items);
|
||||
|
||||
unsafe {
|
||||
// Write the data.
|
||||
ptr::write(&mut ((*inner.as_ptr()).data.header), header);
|
||||
let dst = (*inner.as_ptr()).data.slice.as_mut_ptr();
|
||||
ptr::copy_nonoverlapping(items.as_ptr(), dst, num_items);
|
||||
}
|
||||
|
||||
// Safety: ptr is valid & the inner structure is fully initialized
|
||||
Arc {
|
||||
p: inner,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an Arc for a HeaderSlice using the given header struct and
|
||||
/// vec to generate the slice. The resulting Arc will be fat.
|
||||
pub fn from_header_and_vec(header: H, mut v: Vec<T>) -> Self {
|
||||
let len = v.len();
|
||||
|
||||
let inner = Arc::allocate_for_header_and_slice(len);
|
||||
|
||||
unsafe {
|
||||
// Safety: inner is a valid pointer, so this can't go out of bounds
|
||||
let dst = addr_of_mut!((*inner.as_ptr()).data.header);
|
||||
|
||||
// Safety: `dst` is valid for writes (just allocated)
|
||||
ptr::write(dst, header);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let src = v.as_mut_ptr();
|
||||
|
||||
// Safety: inner is a valid pointer, so this can't go out of bounds
|
||||
let dst = addr_of_mut!((*inner.as_ptr()).data.slice) as *mut T;
|
||||
|
||||
// Safety:
|
||||
// - `src` is valid for reads for `len` (got from `Vec`)
|
||||
// - `dst` is valid for writes for `len` (just allocated, with layout for appropriate slice)
|
||||
// - `src` and `dst` don't overlap (separate allocations)
|
||||
ptr::copy_nonoverlapping(src, dst, len);
|
||||
|
||||
// Deallocate vec without dropping `T`
|
||||
//
|
||||
// Safety: 0..0 elements are always initialized, 0 <= cap for any cap
|
||||
v.set_len(0);
|
||||
}
|
||||
|
||||
// Safety: ptr is valid & the inner structure is fully initialized
|
||||
Arc {
|
||||
p: inner,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<H> Arc<HeaderSlice<H, str>> {
|
||||
/// Creates an Arc for a HeaderSlice using the given header struct and
|
||||
/// a str slice to generate the slice. The resulting Arc will be fat.
|
||||
pub fn from_header_and_str(header: H, string: &str) -> Self {
|
||||
let bytes = Arc::from_header_and_slice(header, string.as_bytes());
|
||||
|
||||
// Safety: `ArcInner` and `HeaderSlice` are `repr(C)`, `str` has the same layout as `[u8]`,
|
||||
// thus it's ok to "transmute" between `Arc<HeaderSlice<H, [u8]>>` and `Arc<HeaderSlice<H, str>>`.
|
||||
//
|
||||
// `bytes` are a valid string since we've just got them from a valid `str`.
|
||||
unsafe { Arc::from_raw_inner(Arc::into_raw_inner(bytes) as _) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Header data with an inline length. Consumers that use HeaderWithLength as the
|
||||
/// Header type in HeaderSlice can take advantage of ThinArc.
|
||||
#[derive(Debug, Eq, PartialEq, Hash)]
|
||||
#[repr(C)]
|
||||
pub struct HeaderWithLength<H> {
|
||||
/// The fixed-sized data.
|
||||
pub header: H,
|
||||
|
||||
/// The slice length.
|
||||
pub length: usize,
|
||||
}
|
||||
|
||||
impl<H> HeaderWithLength<H> {
|
||||
/// Creates a new HeaderWithLength.
|
||||
#[inline]
|
||||
pub fn new(header: H, length: usize) -> Self {
|
||||
HeaderWithLength { header, length }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> From<Arc<HeaderSlice<(), T>>> for Arc<T> {
|
||||
fn from(this: Arc<HeaderSlice<(), T>>) -> Self {
|
||||
debug_assert_eq!(
|
||||
Layout::for_value::<HeaderSlice<(), T>>(&this),
|
||||
Layout::for_value::<T>(&this.slice)
|
||||
);
|
||||
|
||||
// Safety: `HeaderSlice<(), T>` and `T` has the same layout
|
||||
unsafe { Arc::from_raw_inner(Arc::into_raw_inner(this) as _) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> From<Arc<T>> for Arc<HeaderSlice<(), T>> {
|
||||
fn from(this: Arc<T>) -> Self {
|
||||
// Safety: `T` and `HeaderSlice<(), T>` has the same layout
|
||||
unsafe { Arc::from_raw_inner(Arc::into_raw_inner(this) as _) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> From<&[T]> for Arc<[T]> {
|
||||
fn from(slice: &[T]) -> Self {
|
||||
Arc::from_header_and_slice((), slice).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Arc<str> {
|
||||
fn from(s: &str) -> Self {
|
||||
Arc::from_header_and_str((), s).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Arc<str> {
|
||||
fn from(s: String) -> Self {
|
||||
Self::from(&s[..])
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: once `pointer::with_metadata_of` is stable or
|
||||
// implementable on stable without assuming ptr layout
|
||||
// this will be able to accept `T: ?Sized`.
|
||||
impl<T> From<Box<T>> for Arc<T> {
|
||||
fn from(b: Box<T>) -> Self {
|
||||
let layout = Layout::for_value::<T>(&b);
|
||||
|
||||
// Safety: the closure only changes the type of the pointer
|
||||
let inner = unsafe { Self::allocate_for_layout(layout, |mem| mem as *mut ArcInner<T>) };
|
||||
|
||||
unsafe {
|
||||
let src = Box::into_raw(b);
|
||||
|
||||
// Safety: inner is a valid pointer, so this can't go out of bounds
|
||||
let dst = addr_of_mut!((*inner.as_ptr()).data);
|
||||
|
||||
// Safety:
|
||||
// - `src` is valid for reads (got from `Box`)
|
||||
// - `dst` is valid for writes (just allocated)
|
||||
// - `src` and `dst` don't overlap (separate allocations)
|
||||
ptr::copy_nonoverlapping(src, dst, 1);
|
||||
|
||||
// Deallocate box without dropping `T`
|
||||
//
|
||||
// Safety:
|
||||
// - `src` has been got from `Box::into_raw`
|
||||
// - `ManuallyDrop<T>` is guaranteed to have the same layout as `T`
|
||||
drop(Box::<ManuallyDrop<T>>::from_raw(src as _));
|
||||
}
|
||||
|
||||
Arc {
|
||||
p: inner,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Vec<T>> for Arc<[T]> {
|
||||
fn from(v: Vec<T>) -> Self {
|
||||
Arc::from_header_and_vec((), v).into()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type HeaderSliceWithLength<H, T> = HeaderSlice<HeaderWithLength<H>, T>;
|
||||
|
||||
impl<H: PartialOrd, T: ?Sized + PartialOrd> PartialOrd for HeaderSliceWithLength<H, T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
(&self.header.header, &self.slice).partial_cmp(&(&other.header.header, &other.slice))
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: Ord, T: ?Sized + Ord> Ord for HeaderSliceWithLength<H, T> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
(&self.header.header, &self.slice).cmp(&(&other.header.header, &other.slice))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec;
|
||||
use core::iter;
|
||||
|
||||
use crate::{Arc, HeaderSlice};
|
||||
|
||||
#[test]
|
||||
fn from_header_and_iter_smoke() {
|
||||
let arc = Arc::from_header_and_iter(
|
||||
(42u32, 17u8),
|
||||
IntoIterator::into_iter([1u16, 2, 3, 4, 5, 6, 7]),
|
||||
);
|
||||
|
||||
assert_eq!(arc.header, (42, 17));
|
||||
assert_eq!(arc.slice, [1, 2, 3, 4, 5, 6, 7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_header_and_slice_smoke() {
|
||||
let arc = Arc::from_header_and_slice((42u32, 17u8), &[1u16, 2, 3, 4, 5, 6, 7]);
|
||||
|
||||
assert_eq!(arc.header, (42, 17));
|
||||
assert_eq!(arc.slice, [1u16, 2, 3, 4, 5, 6, 7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_header_and_vec_smoke() {
|
||||
let arc = Arc::from_header_and_vec((42u32, 17u8), vec![1u16, 2, 3, 4, 5, 6, 7]);
|
||||
|
||||
assert_eq!(arc.header, (42, 17));
|
||||
assert_eq!(arc.slice, [1u16, 2, 3, 4, 5, 6, 7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_header_and_iter_empty() {
|
||||
let arc = Arc::from_header_and_iter((42u32, 17u8), iter::empty::<u16>());
|
||||
|
||||
assert_eq!(arc.header, (42, 17));
|
||||
assert_eq!(arc.slice, []);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_header_and_slice_empty() {
|
||||
let arc = Arc::from_header_and_slice((42u32, 17u8), &[1u16; 0]);
|
||||
|
||||
assert_eq!(arc.header, (42, 17));
|
||||
assert_eq!(arc.slice, []);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_header_and_vec_empty() {
|
||||
let arc = Arc::from_header_and_vec((42u32, 17u8), vec![1u16; 0]);
|
||||
|
||||
assert_eq!(arc.header, (42, 17));
|
||||
assert_eq!(arc.slice, []);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_13_empty() {
|
||||
crate::Arc::from_header_and_iter((), iter::empty::<usize>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_13_consumption() {
|
||||
let s: &[u8] = &[0u8; 255];
|
||||
crate::Arc::from_header_and_iter((), s.iter().copied());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_header_and_str_smoke() {
|
||||
let a = Arc::from_header_and_str(
|
||||
42,
|
||||
"The answer to the ultimate question of life, the universe, and everything",
|
||||
);
|
||||
assert_eq!(a.header, 42);
|
||||
assert_eq!(
|
||||
&a.slice,
|
||||
"The answer to the ultimate question of life, the universe, and everything"
|
||||
);
|
||||
|
||||
let empty = Arc::from_header_and_str((), "");
|
||||
assert_eq!(empty.header, ());
|
||||
assert_eq!(&empty.slice, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn erase_and_create_from_thin_air_header() {
|
||||
let a: Arc<HeaderSlice<(), [u32]>> = Arc::from_header_and_slice((), &[12, 17, 16]);
|
||||
let b: Arc<[u32]> = a.into();
|
||||
|
||||
assert_eq!(&*b, [12, 17, 16]);
|
||||
|
||||
let c: Arc<HeaderSlice<(), [u32]>> = b.into();
|
||||
|
||||
assert_eq!(&c.slice, [12, 17, 16]);
|
||||
assert_eq!(c.header, ());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_box_and_vec() {
|
||||
let b = Box::new(String::from("xxx"));
|
||||
let b = Arc::<String>::from(b);
|
||||
assert_eq!(&*b, "xxx");
|
||||
|
||||
let v = vec![String::from("1"), String::from("2"), String::from("3")];
|
||||
let v = Arc::<[_]>::from(v);
|
||||
assert_eq!(
|
||||
&*v,
|
||||
[String::from("1"), String::from("2"), String::from("3")]
|
||||
);
|
||||
|
||||
let mut v = vec![String::from("1"), String::from("2"), String::from("3")];
|
||||
v.reserve(10);
|
||||
let v = Arc::<[_]>::from(v);
|
||||
assert_eq!(
|
||||
&*v,
|
||||
[String::from("1"), String::from("2"), String::from("3")]
|
||||
);
|
||||
}
|
||||
}
|
||||
47
third-party/vendor/triomphe/src/iterator_as_exact_size_iterator.rs
vendored
Normal file
47
third-party/vendor/triomphe/src/iterator_as_exact_size_iterator.rs
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/// Wrap an iterator and implement `ExactSizeIterator`
|
||||
/// assuming the underlying iterator reports lower bound equal to upper bound.
|
||||
///
|
||||
/// It does not check the size is reported correctly (except in debug mode).
|
||||
pub(crate) struct IteratorAsExactSizeIterator<I> {
|
||||
iter: I,
|
||||
}
|
||||
|
||||
impl<I: Iterator> IteratorAsExactSizeIterator<I> {
|
||||
#[inline]
|
||||
pub(crate) fn new(iter: I) -> Self {
|
||||
let (lower, upper) = iter.size_hint();
|
||||
debug_assert_eq!(
|
||||
Some(lower),
|
||||
upper,
|
||||
"IteratorAsExactSizeIterator requires size hint lower == upper"
|
||||
);
|
||||
IteratorAsExactSizeIterator { iter }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Iterator> Iterator for IteratorAsExactSizeIterator<I> {
|
||||
type Item = I::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Iterator> ExactSizeIterator for IteratorAsExactSizeIterator<I> {
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
let (lower, upper) = self.iter.size_hint();
|
||||
debug_assert_eq!(
|
||||
Some(lower),
|
||||
upper,
|
||||
"IteratorAsExactSizeIterator requires size hint lower == upper"
|
||||
);
|
||||
lower
|
||||
}
|
||||
}
|
||||
95
third-party/vendor/triomphe/src/lib.rs
vendored
Normal file
95
third-party/vendor/triomphe/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Fork of Arc. This has the following advantages over std::sync::Arc:
|
||||
//!
|
||||
//! * `triomphe::Arc` doesn't support weak references: we save space by excluding the weak reference count, and we don't do extra read-modify-update operations to handle the possibility of weak references.
|
||||
//! * `triomphe::UniqueArc` allows one to construct a temporarily-mutable `Arc` which can be converted to a regular `triomphe::Arc` later
|
||||
//! * `triomphe::OffsetArc` can be used transparently from C++ code and is compatible with (and can be converted to/from) `triomphe::Arc`
|
||||
//! * `triomphe::ArcBorrow` is functionally similar to `&triomphe::Arc<T>`, however in memory it's simply `&T`. This makes it more flexible for FFI; the source of the borrow need not be an `Arc` pinned on the stack (and can instead be a pointer from C++, or an `OffsetArc`). Additionally, this helps avoid pointer-chasing.
|
||||
//! * `triomphe::Arc` has can be constructed for dynamically-sized types via `from_header_and_iter`
|
||||
//! * `triomphe::ThinArc` provides thin-pointer `Arc`s to dynamically sized types
|
||||
//! * `triomphe::ArcUnion` is union of two `triomphe:Arc`s which fits inside one word of memory
|
||||
|
||||
#![allow(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate core;
|
||||
|
||||
#[cfg(feature = "arc-swap")]
|
||||
extern crate arc_swap;
|
||||
#[cfg(feature = "serde")]
|
||||
extern crate serde;
|
||||
#[cfg(feature = "stable_deref_trait")]
|
||||
extern crate stable_deref_trait;
|
||||
#[cfg(feature = "unsize")]
|
||||
extern crate unsize;
|
||||
|
||||
/// Calculates the offset of the specified field from the start of the named struct.
|
||||
/// This macro is impossible to be const until feature(const_ptr_offset_from) is stable.
|
||||
macro_rules! offset_of {
|
||||
($ty: path, $field: tt) => {{
|
||||
// ensure the type is a named struct
|
||||
// ensure the field exists and is accessible
|
||||
let $ty { $field: _, .. };
|
||||
|
||||
let uninit = <::core::mem::MaybeUninit<$ty>>::uninit(); // const since 1.36
|
||||
|
||||
let base_ptr: *const $ty = uninit.as_ptr(); // const since 1.59
|
||||
|
||||
#[allow(unused_unsafe)]
|
||||
let field_ptr = unsafe { ::core::ptr::addr_of!((*base_ptr).$field) }; // since 1.51
|
||||
|
||||
// // the const version requires feature(const_ptr_offset_from)
|
||||
// // https://github.com/rust-lang/rust/issues/92980
|
||||
// #[allow(unused_unsafe)]
|
||||
// unsafe { (field_ptr as *const u8).offset_from(base_ptr as *const u8) as usize }
|
||||
|
||||
(field_ptr as usize) - (base_ptr as usize)
|
||||
}};
|
||||
}
|
||||
|
||||
mod arc;
|
||||
mod arc_borrow;
|
||||
#[cfg(feature = "arc-swap")]
|
||||
mod arc_swap_support;
|
||||
mod arc_union;
|
||||
mod header;
|
||||
mod iterator_as_exact_size_iterator;
|
||||
mod offset_arc;
|
||||
mod thin_arc;
|
||||
mod unique_arc;
|
||||
|
||||
pub use arc::*;
|
||||
pub use arc_borrow::*;
|
||||
pub use arc_union::*;
|
||||
pub use header::*;
|
||||
pub use offset_arc::*;
|
||||
pub use thin_arc::*;
|
||||
pub use unique_arc::*;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::process::abort;
|
||||
|
||||
// `no_std`-compatible abort by forcing a panic while already panicking.
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[cold]
|
||||
fn abort() -> ! {
|
||||
struct PanicOnDrop;
|
||||
impl Drop for PanicOnDrop {
|
||||
fn drop(&mut self) {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
let _double_panicer = PanicOnDrop;
|
||||
panic!();
|
||||
}
|
||||
138
third-party/vendor/triomphe/src/offset_arc.rs
vendored
Normal file
138
third-party/vendor/triomphe/src/offset_arc.rs
vendored
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::ManuallyDrop;
|
||||
use core::ops::Deref;
|
||||
use core::ptr;
|
||||
|
||||
use super::{Arc, ArcBorrow};
|
||||
|
||||
/// An `Arc`, except it holds a pointer to the T instead of to the
|
||||
/// entire ArcInner.
|
||||
///
|
||||
/// An `OffsetArc<T>` has the same layout and ABI as a non-null
|
||||
/// `const T*` in C, and may be used in FFI function signatures.
|
||||
///
|
||||
/// ```text
|
||||
/// Arc<T> OffsetArc<T>
|
||||
/// | |
|
||||
/// v v
|
||||
/// ---------------------
|
||||
/// | RefCount | T (data) | [ArcInner<T>]
|
||||
/// ---------------------
|
||||
/// ```
|
||||
///
|
||||
/// This means that this is a direct pointer to
|
||||
/// its contained data (and can be read from by both C++ and Rust),
|
||||
/// but we can also convert it to a "regular" `Arc<T>` by removing the offset.
|
||||
///
|
||||
/// This is very useful if you have an Arc-containing struct shared between Rust and C++,
|
||||
/// and wish for C++ to be able to read the data behind the `Arc` without incurring
|
||||
/// an FFI call overhead.
|
||||
#[derive(Eq)]
|
||||
#[repr(transparent)]
|
||||
pub struct OffsetArc<T> {
|
||||
pub(crate) ptr: ptr::NonNull<T>,
|
||||
pub(crate) phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T: Sync + Send> Send for OffsetArc<T> {}
|
||||
unsafe impl<T: Sync + Send> Sync for OffsetArc<T> {}
|
||||
|
||||
impl<T> Deref for OffsetArc<T> {
|
||||
type Target = T;
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &*self.ptr.as_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for OffsetArc<T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
Arc::into_raw_offset(self.clone_arc())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for OffsetArc<T> {
|
||||
fn drop(&mut self) {
|
||||
let _ = Arc::from_raw_offset(OffsetArc {
|
||||
ptr: self.ptr,
|
||||
phantom: PhantomData,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug> fmt::Debug for OffsetArc<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq> PartialEq for OffsetArc<T> {
|
||||
fn eq(&self, other: &OffsetArc<T>) -> bool {
|
||||
*(*self) == *(*other)
|
||||
}
|
||||
|
||||
#[allow(clippy::partialeq_ne_impl)]
|
||||
fn ne(&self, other: &OffsetArc<T>) -> bool {
|
||||
*(*self) != *(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OffsetArc<T> {
|
||||
/// Temporarily converts |self| into a bonafide Arc and exposes it to the
|
||||
/// provided callback. The refcount is not modified.
|
||||
#[inline]
|
||||
pub fn with_arc<F, U>(&self, f: F) -> U
|
||||
where
|
||||
F: FnOnce(&Arc<T>) -> U,
|
||||
{
|
||||
// Synthesize transient Arc, which never touches the refcount of the ArcInner.
|
||||
let transient = unsafe { ManuallyDrop::new(Arc::from_raw(self.ptr.as_ptr())) };
|
||||
|
||||
// Expose the transient Arc to the callback, which may clone it if it wants
|
||||
// and forward the result to the user
|
||||
f(&transient)
|
||||
}
|
||||
|
||||
/// If uniquely owned, provide a mutable reference
|
||||
/// Else create a copy, and mutate that
|
||||
///
|
||||
/// This is functionally the same thing as `Arc::make_mut`
|
||||
#[inline]
|
||||
pub fn make_mut(&mut self) -> &mut T
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
unsafe {
|
||||
// extract the OffsetArc as an owned variable. This does not modify
|
||||
// the refcount and we should be careful to not drop `this`
|
||||
let this = ptr::read(self);
|
||||
// treat it as a real Arc, but wrapped in a ManuallyDrop
|
||||
// in case `Arc::make_mut()` panics in the clone impl
|
||||
let mut arc = ManuallyDrop::new(Arc::from_raw_offset(this));
|
||||
// obtain the mutable reference. Cast away the lifetime since
|
||||
// we have the right lifetime bounds in the parameters.
|
||||
// This may mutate `arc`.
|
||||
let ret = Arc::make_mut(&mut *arc) as *mut _;
|
||||
// Store the possibly-mutated arc back inside, after converting
|
||||
// it to a OffsetArc again. Release the ManuallyDrop.
|
||||
// This also does not modify the refcount or call drop on self
|
||||
ptr::write(self, Arc::into_raw_offset(ManuallyDrop::into_inner(arc)));
|
||||
&mut *ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Clone it as an `Arc`
|
||||
#[inline]
|
||||
pub fn clone_arc(&self) -> Arc<T> {
|
||||
OffsetArc::with_arc(self, |a| a.clone())
|
||||
}
|
||||
|
||||
/// Produce a pointer to the data that can be converted back
|
||||
/// to an `Arc`
|
||||
#[inline]
|
||||
pub fn borrow_arc(&self) -> ArcBorrow<'_, T> {
|
||||
ArcBorrow(&**self)
|
||||
}
|
||||
}
|
||||
451
third-party/vendor/triomphe/src/thin_arc.rs
vendored
Normal file
451
third-party/vendor/triomphe/src/thin_arc.rs
vendored
Normal file
|
|
@ -0,0 +1,451 @@
|
|||
use core::cmp::Ordering;
|
||||
use core::ffi::c_void;
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{ExactSizeIterator, Iterator};
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::ManuallyDrop;
|
||||
use core::ops::Deref;
|
||||
use core::ptr;
|
||||
use core::usize;
|
||||
|
||||
use super::{Arc, ArcInner, HeaderSliceWithLength, HeaderWithLength};
|
||||
|
||||
/// A "thin" `Arc` containing dynamically sized data
|
||||
///
|
||||
/// This is functionally equivalent to `Arc<(H, [T])>`
|
||||
///
|
||||
/// When you create an `Arc` containing a dynamically sized type
|
||||
/// like `HeaderSlice<H, [T]>`, the `Arc` is represented on the stack
|
||||
/// as a "fat pointer", where the length of the slice is stored
|
||||
/// alongside the `Arc`'s pointer. In some situations you may wish to
|
||||
/// have a thin pointer instead, perhaps for FFI compatibility
|
||||
/// or space efficiency.
|
||||
///
|
||||
/// Note that we use `[T; 0]` in order to have the right alignment for `T`.
|
||||
///
|
||||
/// `ThinArc` solves this by storing the length in the allocation itself,
|
||||
/// via `HeaderSliceWithLength`.
|
||||
#[repr(transparent)]
|
||||
pub struct ThinArc<H, T> {
|
||||
ptr: ptr::NonNull<ArcInner<HeaderSliceWithLength<H, [T; 0]>>>,
|
||||
phantom: PhantomData<(H, T)>,
|
||||
}
|
||||
|
||||
unsafe impl<H: Sync + Send, T: Sync + Send> Send for ThinArc<H, T> {}
|
||||
unsafe impl<H: Sync + Send, T: Sync + Send> Sync for ThinArc<H, T> {}
|
||||
|
||||
// Synthesize a fat pointer from a thin pointer.
|
||||
//
|
||||
// See the comment around the analogous operation in from_header_and_iter.
|
||||
#[inline]
|
||||
fn thin_to_thick<H, T>(
|
||||
thin: *mut ArcInner<HeaderSliceWithLength<H, [T; 0]>>,
|
||||
) -> *mut ArcInner<HeaderSliceWithLength<H, [T]>> {
|
||||
let len = unsafe { (*thin).data.header.length };
|
||||
let fake_slice = ptr::slice_from_raw_parts_mut(thin as *mut T, len);
|
||||
|
||||
fake_slice as *mut ArcInner<HeaderSliceWithLength<H, [T]>>
|
||||
}
|
||||
|
||||
impl<H, T> ThinArc<H, T> {
|
||||
/// Temporarily converts |self| into a bonafide Arc and exposes it to the
|
||||
/// provided callback. The refcount is not modified.
|
||||
#[inline]
|
||||
pub fn with_arc<F, U>(&self, f: F) -> U
|
||||
where
|
||||
F: FnOnce(&Arc<HeaderSliceWithLength<H, [T]>>) -> U,
|
||||
{
|
||||
// Synthesize transient Arc, which never touches the refcount of the ArcInner.
|
||||
let transient = unsafe {
|
||||
ManuallyDrop::new(Arc {
|
||||
p: ptr::NonNull::new_unchecked(thin_to_thick(self.ptr.as_ptr())),
|
||||
phantom: PhantomData,
|
||||
})
|
||||
};
|
||||
|
||||
// Expose the transient Arc to the callback, which may clone it if it wants
|
||||
// and forward the result to the user
|
||||
f(&transient)
|
||||
}
|
||||
|
||||
/// Creates a `ThinArc` for a HeaderSlice using the given header struct and
|
||||
/// iterator to generate the slice.
|
||||
pub fn from_header_and_iter<I>(header: H, items: I) -> Self
|
||||
where
|
||||
I: Iterator<Item = T> + ExactSizeIterator,
|
||||
{
|
||||
let header = HeaderWithLength::new(header, items.len());
|
||||
Arc::into_thin(Arc::from_header_and_iter(header, items))
|
||||
}
|
||||
|
||||
/// Creates a `ThinArc` for a HeaderSlice using the given header struct and
|
||||
/// a slice to copy.
|
||||
pub fn from_header_and_slice(header: H, items: &[T]) -> Self
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
let header = HeaderWithLength::new(header, items.len());
|
||||
Arc::into_thin(Arc::from_header_and_slice(header, items))
|
||||
}
|
||||
|
||||
/// Returns the address on the heap of the ThinArc itself -- not the T
|
||||
/// within it -- for memory reporting.
|
||||
#[inline]
|
||||
pub fn ptr(&self) -> *const c_void {
|
||||
self.ptr.as_ptr() as *const ArcInner<T> as *const c_void
|
||||
}
|
||||
|
||||
/// Returns the address on the heap of the Arc itself -- not the T within it -- for memory
|
||||
/// reporting.
|
||||
#[inline]
|
||||
pub fn heap_ptr(&self) -> *const c_void {
|
||||
self.ptr()
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Constructs an ThinArc from a raw pointer.
|
||||
///
|
||||
/// The raw pointer must have been previously returned by a call to
|
||||
/// ThinArc::into_raw.
|
||||
///
|
||||
/// The user of from_raw has to make sure a specific value of T is only dropped once.
|
||||
///
|
||||
/// This function is unsafe because improper use may lead to memory unsafety,
|
||||
/// even if the returned ThinArc is never accessed.
|
||||
#[inline]
|
||||
pub unsafe fn from_raw(ptr: *const c_void) -> Self {
|
||||
Self {
|
||||
ptr: ptr::NonNull::new_unchecked(ptr as *mut c_void).cast(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Consume ThinArc and returned the wrapped pointer.
|
||||
#[inline]
|
||||
pub fn into_raw(self) -> *const c_void {
|
||||
let this = ManuallyDrop::new(self);
|
||||
this.ptr.cast().as_ptr()
|
||||
}
|
||||
|
||||
/// Provides a raw pointer to the data.
|
||||
/// The counts are not affected in any way and the ThinArc is not consumed.
|
||||
/// The pointer is valid for as long as there are strong counts in the ThinArc.
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const c_void {
|
||||
self.ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, T> Deref for ThinArc<H, T> {
|
||||
type Target = HeaderSliceWithLength<H, [T]>;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &(*thin_to_thick(self.ptr.as_ptr())).data }
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, T> Clone for ThinArc<H, T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
ThinArc::with_arc(self, |a| {
|
||||
// Safety: `a` isn't mutable thus the header length remains valid
|
||||
unsafe { Arc::into_thin_unchecked(a.clone()) }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, T> Drop for ThinArc<H, T> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
let _ = Arc::from_thin(ThinArc {
|
||||
ptr: self.ptr,
|
||||
phantom: PhantomData,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, T> Arc<HeaderSliceWithLength<H, [T]>> {
|
||||
/// Converts an `Arc` into a `ThinArc`. This consumes the `Arc`, so the refcount
|
||||
/// is not modified.
|
||||
///
|
||||
/// # Safety
|
||||
/// Assumes that the header length matches the slice length.
|
||||
#[inline]
|
||||
unsafe fn into_thin_unchecked(a: Self) -> ThinArc<H, T> {
|
||||
let a = ManuallyDrop::new(a);
|
||||
debug_assert_eq!(
|
||||
a.header.length,
|
||||
a.slice.len(),
|
||||
"Length needs to be correct for ThinArc to work"
|
||||
);
|
||||
let fat_ptr: *mut ArcInner<HeaderSliceWithLength<H, [T]>> = a.ptr();
|
||||
let thin_ptr = fat_ptr as *mut [usize] as *mut usize;
|
||||
ThinArc {
|
||||
ptr: unsafe {
|
||||
ptr::NonNull::new_unchecked(
|
||||
thin_ptr as *mut ArcInner<HeaderSliceWithLength<H, [T; 0]>>,
|
||||
)
|
||||
},
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts an `Arc` into a `ThinArc`. This consumes the `Arc`, so the refcount
|
||||
/// is not modified.
|
||||
#[inline]
|
||||
pub fn into_thin(a: Self) -> ThinArc<H, T> {
|
||||
assert_eq!(
|
||||
a.header.length,
|
||||
a.slice.len(),
|
||||
"Length needs to be correct for ThinArc to work"
|
||||
);
|
||||
unsafe { Self::into_thin_unchecked(a) }
|
||||
}
|
||||
|
||||
/// Converts a `ThinArc` into an `Arc`. This consumes the `ThinArc`, so the refcount
|
||||
/// is not modified.
|
||||
#[inline]
|
||||
pub fn from_thin(a: ThinArc<H, T>) -> Self {
|
||||
let a = ManuallyDrop::new(a);
|
||||
let ptr = thin_to_thick(a.ptr.as_ptr());
|
||||
unsafe {
|
||||
Arc {
|
||||
p: ptr::NonNull::new_unchecked(ptr),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: PartialEq, T: PartialEq> PartialEq for ThinArc<H, T> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &ThinArc<H, T>) -> bool {
|
||||
ThinArc::with_arc(self, |a| ThinArc::with_arc(other, |b| *a == *b))
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: Eq, T: Eq> Eq for ThinArc<H, T> {}
|
||||
|
||||
impl<H: PartialOrd, T: PartialOrd> PartialOrd for ThinArc<H, T> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &ThinArc<H, T>) -> Option<Ordering> {
|
||||
ThinArc::with_arc(self, |a| ThinArc::with_arc(other, |b| a.partial_cmp(b)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: Ord, T: Ord> Ord for ThinArc<H, T> {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &ThinArc<H, T>) -> Ordering {
|
||||
ThinArc::with_arc(self, |a| ThinArc::with_arc(other, |b| a.cmp(b)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: Hash, T: Hash> Hash for ThinArc<H, T> {
|
||||
fn hash<HSR: Hasher>(&self, state: &mut HSR) {
|
||||
ThinArc::with_arc(self, |a| a.hash(state))
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: fmt::Debug, T: fmt::Debug> fmt::Debug for ThinArc<H, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, T> fmt::Pointer for ThinArc<H, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.ptr(), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{Arc, HeaderWithLength, ThinArc};
|
||||
use alloc::vec;
|
||||
use core::clone::Clone;
|
||||
use core::ops::Drop;
|
||||
use core::sync::atomic;
|
||||
use core::sync::atomic::Ordering::{Acquire, SeqCst};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct Canary(*mut atomic::AtomicUsize);
|
||||
|
||||
impl Drop for Canary {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
(*self.0).fetch_add(1, SeqCst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_thin() {
|
||||
let header = HeaderWithLength::new(100u32, 0);
|
||||
let x = Arc::from_header_and_iter(header, core::iter::empty::<i32>());
|
||||
let y = Arc::into_thin(x.clone());
|
||||
assert_eq!(y.header.header, 100);
|
||||
assert!(y.slice.is_empty());
|
||||
assert_eq!(x.header.header, 100);
|
||||
assert!(x.slice.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn thin_assert_padding() {
|
||||
#[derive(Clone, Default)]
|
||||
#[repr(C)]
|
||||
struct Padded {
|
||||
i: u16,
|
||||
}
|
||||
|
||||
// The header will have more alignment than `Padded`
|
||||
let header = HeaderWithLength::new(0i32, 2);
|
||||
let items = vec![Padded { i: 0xdead }, Padded { i: 0xbeef }];
|
||||
let a = ThinArc::from_header_and_iter(header, items.into_iter());
|
||||
assert_eq!(a.slice.len(), 2);
|
||||
assert_eq!(a.slice[0].i, 0xdead);
|
||||
assert_eq!(a.slice[1].i, 0xbeef);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::redundant_clone, clippy::eq_op)]
|
||||
fn slices_and_thin() {
|
||||
let mut canary = atomic::AtomicUsize::new(0);
|
||||
let c = Canary(&mut canary as *mut atomic::AtomicUsize);
|
||||
let v = vec![5, 6];
|
||||
let header = HeaderWithLength::new(c, v.len());
|
||||
{
|
||||
let x = Arc::into_thin(Arc::from_header_and_slice(header, &v));
|
||||
let y = ThinArc::with_arc(&x, |q| q.clone());
|
||||
let _ = y.clone();
|
||||
let _ = x == x;
|
||||
Arc::from_thin(x.clone());
|
||||
}
|
||||
assert_eq!(canary.load(Acquire), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::redundant_clone, clippy::eq_op)]
|
||||
fn iter_and_thin() {
|
||||
let mut canary = atomic::AtomicUsize::new(0);
|
||||
let c = Canary(&mut canary as *mut atomic::AtomicUsize);
|
||||
let v = vec![5, 6];
|
||||
let header = HeaderWithLength::new(c, v.len());
|
||||
{
|
||||
let x = Arc::into_thin(Arc::from_header_and_iter(header, v.into_iter()));
|
||||
let y = ThinArc::with_arc(&x, |q| q.clone());
|
||||
let _ = y.clone();
|
||||
let _ = x == x;
|
||||
Arc::from_thin(x.clone());
|
||||
}
|
||||
assert_eq!(canary.load(Acquire), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn into_raw_and_from_raw() {
|
||||
let mut canary = atomic::AtomicUsize::new(0);
|
||||
let c = Canary(&mut canary as *mut atomic::AtomicUsize);
|
||||
let v = vec![5, 6];
|
||||
let header = HeaderWithLength::new(c, v.len());
|
||||
{
|
||||
type ThinArcCanary = ThinArc<Canary, u32>;
|
||||
let x: ThinArcCanary = Arc::into_thin(Arc::from_header_and_iter(header, v.into_iter()));
|
||||
let ptr = x.as_ptr();
|
||||
|
||||
assert_eq!(x.into_raw(), ptr);
|
||||
|
||||
let _x = unsafe { ThinArcCanary::from_raw(ptr) };
|
||||
}
|
||||
assert_eq!(canary.load(Acquire), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn thin_eq_and_cmp() {
|
||||
[
|
||||
[("*", &b"AB"[..]), ("*", &b"ab"[..])],
|
||||
[("*", &b"AB"[..]), ("*", &b"a"[..])],
|
||||
[("*", &b"A"[..]), ("*", &b"ab"[..])],
|
||||
[("A", &b"*"[..]), ("a", &b"*"[..])],
|
||||
[("a", &b"*"[..]), ("A", &b"*"[..])],
|
||||
[("AB", &b"*"[..]), ("a", &b"*"[..])],
|
||||
[("A", &b"*"[..]), ("ab", &b"*"[..])],
|
||||
]
|
||||
.iter()
|
||||
.for_each(|[lt @ (lh, ls), rt @ (rh, rs)]| {
|
||||
let l = ThinArc::from_header_and_slice(lh, ls);
|
||||
let r = ThinArc::from_header_and_slice(rh, rs);
|
||||
|
||||
assert_eq!(l, l);
|
||||
assert_eq!(r, r);
|
||||
|
||||
assert_ne!(l, r);
|
||||
assert_ne!(r, l);
|
||||
|
||||
assert_eq!(l <= l, lt <= lt, "{lt:?} <= {lt:?}");
|
||||
assert_eq!(l >= l, lt >= lt, "{lt:?} >= {lt:?}");
|
||||
|
||||
assert_eq!(l < l, lt < lt, "{lt:?} < {lt:?}");
|
||||
assert_eq!(l > l, lt > lt, "{lt:?} > {lt:?}");
|
||||
|
||||
assert_eq!(r <= r, rt <= rt, "{rt:?} <= {rt:?}");
|
||||
assert_eq!(r >= r, rt >= rt, "{rt:?} >= {rt:?}");
|
||||
|
||||
assert_eq!(r < r, rt < rt, "{rt:?} < {rt:?}");
|
||||
assert_eq!(r > r, rt > rt, "{rt:?} > {rt:?}");
|
||||
|
||||
assert_eq!(l < r, lt < rt, "{lt:?} < {rt:?}");
|
||||
assert_eq!(r > l, rt > lt, "{rt:?} > {lt:?}");
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn thin_eq_and_partial_cmp() {
|
||||
[
|
||||
[(0.0, &[0.0, 0.0][..]), (1.0, &[0.0, 0.0][..])],
|
||||
[(1.0, &[0.0, 0.0][..]), (0.0, &[0.0, 0.0][..])],
|
||||
[(0.0, &[0.0][..]), (0.0, &[0.0, 0.0][..])],
|
||||
[(0.0, &[0.0, 0.0][..]), (0.0, &[0.0][..])],
|
||||
[(0.0, &[1.0, 2.0][..]), (0.0, &[10.0, 20.0][..])],
|
||||
]
|
||||
.iter()
|
||||
.for_each(|[lt @ (lh, ls), rt @ (rh, rs)]| {
|
||||
let l = ThinArc::from_header_and_slice(lh, ls);
|
||||
let r = ThinArc::from_header_and_slice(rh, rs);
|
||||
|
||||
assert_eq!(l, l);
|
||||
assert_eq!(r, r);
|
||||
|
||||
assert_ne!(l, r);
|
||||
assert_ne!(r, l);
|
||||
|
||||
assert_eq!(l <= l, lt <= lt, "{lt:?} <= {lt:?}");
|
||||
assert_eq!(l >= l, lt >= lt, "{lt:?} >= {lt:?}");
|
||||
|
||||
assert_eq!(l < l, lt < lt, "{lt:?} < {lt:?}");
|
||||
assert_eq!(l > l, lt > lt, "{lt:?} > {lt:?}");
|
||||
|
||||
assert_eq!(r <= r, rt <= rt, "{rt:?} <= {rt:?}");
|
||||
assert_eq!(r >= r, rt >= rt, "{rt:?} >= {rt:?}");
|
||||
|
||||
assert_eq!(r < r, rt < rt, "{rt:?} < {rt:?}");
|
||||
assert_eq!(r > r, rt > rt, "{rt:?} > {rt:?}");
|
||||
|
||||
assert_eq!(l < r, lt < rt, "{lt:?} < {rt:?}");
|
||||
assert_eq!(r > l, rt > lt, "{rt:?} > {lt:?}");
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
const fn is_partial_ord<T: ?Sized + PartialOrd>() {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
const fn is_ord<T: ?Sized + Ord>() {}
|
||||
|
||||
// compile-time check that PartialOrd/Ord is correctly derived
|
||||
const _: () = is_partial_ord::<ThinArc<f64, f64>>();
|
||||
const _: () = is_partial_ord::<ThinArc<f64, u64>>();
|
||||
const _: () = is_partial_ord::<ThinArc<u64, f64>>();
|
||||
const _: () = is_ord::<ThinArc<u64, u64>>();
|
||||
}
|
||||
276
third-party/vendor/triomphe/src/unique_arc.rs
vendored
Normal file
276
third-party/vendor/triomphe/src/unique_arc.rs
vendored
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
use alloc::vec::Vec;
|
||||
use alloc::{alloc::Layout, boxed::Box};
|
||||
use core::convert::TryFrom;
|
||||
use core::iter::FromIterator;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::{ManuallyDrop, MaybeUninit};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::sync::atomic::AtomicUsize;
|
||||
|
||||
use crate::iterator_as_exact_size_iterator::IteratorAsExactSizeIterator;
|
||||
use crate::HeaderSlice;
|
||||
|
||||
use super::{Arc, ArcInner};
|
||||
|
||||
/// An `Arc` that is known to be uniquely owned
|
||||
///
|
||||
/// When `Arc`s are constructed, they are known to be
|
||||
/// uniquely owned. In such a case it is safe to mutate
|
||||
/// the contents of the `Arc`. Normally, one would just handle
|
||||
/// this by mutating the data on the stack before allocating the
|
||||
/// `Arc`, however it's possible the data is large or unsized
|
||||
/// and you need to heap-allocate it earlier in such a way
|
||||
/// that it can be freely converted into a regular `Arc` once you're
|
||||
/// done.
|
||||
///
|
||||
/// `UniqueArc` exists for this purpose, when constructed it performs
|
||||
/// the same allocations necessary for an `Arc`, however it allows mutable access.
|
||||
/// Once the mutation is finished, you can call `.shareable()` and get a regular `Arc`
|
||||
/// out of it.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use triomphe::UniqueArc;
|
||||
/// let data = [1, 2, 3, 4, 5];
|
||||
/// let mut x = UniqueArc::new(data);
|
||||
/// x[4] = 7; // mutate!
|
||||
/// let y = x.shareable(); // y is an Arc<T>
|
||||
/// ```
|
||||
#[repr(transparent)]
|
||||
pub struct UniqueArc<T: ?Sized>(Arc<T>);
|
||||
|
||||
impl<T> UniqueArc<T> {
|
||||
#[inline]
|
||||
/// Construct a new UniqueArc
|
||||
pub fn new(data: T) -> Self {
|
||||
UniqueArc(Arc::new(data))
|
||||
}
|
||||
|
||||
/// Construct an uninitialized arc
|
||||
#[inline]
|
||||
pub fn new_uninit() -> UniqueArc<MaybeUninit<T>> {
|
||||
unsafe {
|
||||
let layout = Layout::new::<ArcInner<MaybeUninit<T>>>();
|
||||
let ptr = alloc::alloc::alloc(layout);
|
||||
let mut p = NonNull::new(ptr)
|
||||
.unwrap_or_else(|| alloc::alloc::handle_alloc_error(layout))
|
||||
.cast::<ArcInner<MaybeUninit<T>>>();
|
||||
ptr::write(&mut p.as_mut().count, AtomicUsize::new(1));
|
||||
|
||||
UniqueArc(Arc {
|
||||
p,
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the inner value of the unique arc
|
||||
pub fn into_inner(this: Self) -> T {
|
||||
// Wrap the Arc in a `ManuallyDrop` so that its drop routine never runs
|
||||
let this = ManuallyDrop::new(this.0);
|
||||
debug_assert!(
|
||||
this.is_unique(),
|
||||
"attempted to call `.into_inner()` on a `UniqueArc` with a non-zero ref count",
|
||||
);
|
||||
|
||||
// Safety: We have exclusive access to the inner data and the
|
||||
// arc will not perform its drop routine since we've
|
||||
// wrapped it in a `ManuallyDrop`
|
||||
unsafe { Box::from_raw(this.ptr()).data }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> UniqueArc<T> {
|
||||
/// Convert to a shareable `Arc<T>` once we're done mutating it
|
||||
#[inline]
|
||||
pub fn shareable(self) -> Arc<T> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Creates a new [`UniqueArc`] from the given [`Arc`].
|
||||
///
|
||||
/// An unchecked alternative to `Arc::try_unique()`
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The given `Arc` must have a reference count of exactly one
|
||||
///
|
||||
pub(crate) unsafe fn from_arc(arc: Arc<T>) -> Self {
|
||||
debug_assert_eq!(Arc::count(&arc), 1);
|
||||
Self(arc)
|
||||
}
|
||||
|
||||
/// Creates a new `&mut `[`UniqueArc`] from the given `&mut `[`Arc`].
|
||||
///
|
||||
/// An unchecked alternative to `Arc::try_as_unique()`
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The given `Arc` must have a reference count of exactly one
|
||||
pub(crate) unsafe fn from_arc_ref(arc: &mut Arc<T>) -> &mut Self {
|
||||
debug_assert_eq!(Arc::count(arc), 1);
|
||||
|
||||
// Safety: caller guarantees that `arc` is unique,
|
||||
// `UniqueArc` is `repr(transparent)`
|
||||
&mut *(arc as *mut Arc<T> as *mut UniqueArc<T>)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UniqueArc<MaybeUninit<T>> {
|
||||
/// Calls `MaybeUninit::write` on the contained value.
|
||||
pub fn write(&mut self, val: T) -> &mut T {
|
||||
unsafe {
|
||||
// Casting *mut MaybeUninit<T> -> *mut T is always fine
|
||||
let ptr = self.as_mut_ptr() as *mut T;
|
||||
|
||||
// Safety: We have exclusive access to the inner data
|
||||
ptr.write(val);
|
||||
|
||||
// Safety: the pointer was just written to
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtain a mutable pointer to the stored `MaybeUninit<T>`.
|
||||
pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit<T> {
|
||||
unsafe { &mut (*self.0.ptr()).data }
|
||||
}
|
||||
|
||||
/// Convert to an initialized Arc.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is equivalent to `MaybeUninit::assume_init` and has the
|
||||
/// same safety requirements. You are responsible for ensuring that the `T`
|
||||
/// has actually been initialized before calling this method.
|
||||
#[inline]
|
||||
pub unsafe fn assume_init(this: Self) -> UniqueArc<T> {
|
||||
UniqueArc(Arc {
|
||||
p: ManuallyDrop::new(this).0.p.cast(),
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UniqueArc<[MaybeUninit<T>]> {
|
||||
/// Create an Arc contains an array `[MaybeUninit<T>]` of `len`.
|
||||
pub fn new_uninit_slice(len: usize) -> Self {
|
||||
let ptr: NonNull<ArcInner<HeaderSlice<(), [MaybeUninit<T>]>>> =
|
||||
Arc::allocate_for_header_and_slice(len);
|
||||
|
||||
// Safety:
|
||||
// - `ArcInner` is properly allocated and initialized.
|
||||
// - `()` and `[MaybeUninit<T>]` do not require special initialization
|
||||
// - The `Arc` is just created and so -- unique.
|
||||
unsafe {
|
||||
let arc: Arc<HeaderSlice<(), [MaybeUninit<T>]>> = Arc::from_raw_inner(ptr.as_ptr());
|
||||
let arc: Arc<[MaybeUninit<T>]> = arc.into();
|
||||
UniqueArc(arc)
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Must initialize all fields before calling this function.
|
||||
#[inline]
|
||||
pub unsafe fn assume_init_slice(Self(this): Self) -> UniqueArc<[T]> {
|
||||
UniqueArc(this.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> TryFrom<Arc<T>> for UniqueArc<T> {
|
||||
type Error = Arc<T>;
|
||||
|
||||
fn try_from(arc: Arc<T>) -> Result<Self, Self::Error> {
|
||||
Arc::try_unique(arc)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Deref for UniqueArc<T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> DerefMut for UniqueArc<T> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
// We know this to be uniquely owned
|
||||
unsafe { &mut (*self.0.ptr()).data }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> FromIterator<A> for UniqueArc<[A]> {
|
||||
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
|
||||
let iter = iter.into_iter();
|
||||
let (lower, upper) = iter.size_hint();
|
||||
let arc: Arc<[A]> = if Some(lower) == upper {
|
||||
let iter = IteratorAsExactSizeIterator::new(iter);
|
||||
Arc::from_header_and_iter((), iter).into()
|
||||
} else {
|
||||
let vec = iter.collect::<Vec<_>>();
|
||||
Arc::from(vec)
|
||||
};
|
||||
// Safety: We just created an `Arc`, so it's unique.
|
||||
unsafe { UniqueArc::from_arc(arc) }
|
||||
}
|
||||
}
|
||||
|
||||
// Safety:
|
||||
// This leverages the correctness of Arc's CoerciblePtr impl. Additionally, we must ensure that
|
||||
// this can not be used to violate the safety invariants of UniqueArc, which require that we can not
|
||||
// duplicate the Arc, such that replace_ptr returns a valid instance. This holds since it consumes
|
||||
// a unique owner of the contained ArcInner.
|
||||
#[cfg(feature = "unsize")]
|
||||
unsafe impl<T, U: ?Sized> unsize::CoerciblePtr<U> for UniqueArc<T> {
|
||||
type Pointee = T;
|
||||
type Output = UniqueArc<U>;
|
||||
|
||||
fn as_sized_ptr(&mut self) -> *mut T {
|
||||
// Dispatch to the contained field.
|
||||
unsize::CoerciblePtr::<U>::as_sized_ptr(&mut self.0)
|
||||
}
|
||||
|
||||
unsafe fn replace_ptr(self, new: *mut U) -> UniqueArc<U> {
|
||||
// Dispatch to the contained field, work around conflict of destructuring and Drop.
|
||||
let inner = ManuallyDrop::new(self);
|
||||
UniqueArc(ptr::read(&inner.0).replace_ptr(new))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{Arc, UniqueArc};
|
||||
use core::{convert::TryFrom, mem::MaybeUninit};
|
||||
|
||||
#[test]
|
||||
fn unique_into_inner() {
|
||||
let unique = UniqueArc::new(10u64);
|
||||
assert_eq!(UniqueArc::into_inner(unique), 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn try_from_arc() {
|
||||
let x = Arc::new(10_000);
|
||||
let y = x.clone();
|
||||
|
||||
assert!(UniqueArc::try_from(x).is_err());
|
||||
assert_eq!(
|
||||
UniqueArc::into_inner(UniqueArc::try_from(y).unwrap()),
|
||||
10_000,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn maybeuninit_smoke() {
|
||||
let mut arc: UniqueArc<MaybeUninit<_>> = UniqueArc::new_uninit();
|
||||
arc.write(999);
|
||||
|
||||
let arc = unsafe { UniqueArc::assume_init(arc) };
|
||||
assert_eq!(*arc, 999);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue