summaryrefslogtreecommitdiffstats
path: root/vendor/partial_ref
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/partial_ref')
-rw-r--r--vendor/partial_ref/.cargo-checksum.json1
-rw-r--r--vendor/partial_ref/Cargo.toml27
-rw-r--r--vendor/partial_ref/LICENSE-APACHE201
-rw-r--r--vendor/partial_ref/LICENSE-MIT25
-rw-r--r--vendor/partial_ref/README.md109
-rw-r--r--vendor/partial_ref/src/lib.rs964
-rw-r--r--vendor/partial_ref/src/macros.rs154
7 files changed, 1481 insertions, 0 deletions
diff --git a/vendor/partial_ref/.cargo-checksum.json b/vendor/partial_ref/.cargo-checksum.json
new file mode 100644
index 000000000..d0c19e46f
--- /dev/null
+++ b/vendor/partial_ref/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"17538c929310bf1bde80610dc24666ca8ba965e8a6dd70ac931a74ab7aa39c35","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"518718c95bcadbc4796051b0dfe05500fddc5b21cb68dab51857ca85f3fd438d","README.md":"ed6ff3ba7653b64a261ef7a67d64eed553c472d927d01bd0f5e5c80750d63db7","src/lib.rs":"76a74154cebfb150e71ed7692b105029bc72b25e458649ca16b6b04cda5e1ce5","src/macros.rs":"8bebc9f420c18986637034718ee44f2fc7addf52ae9bfacd1dc9d5309f3cc6ab"},"package":"0f728bc9b1479656e40cba507034904a8c44027c0efdbbaf6a4bdc5f2d3a910c"} \ No newline at end of file
diff --git a/vendor/partial_ref/Cargo.toml b/vendor/partial_ref/Cargo.toml
new file mode 100644
index 000000000..f1a680884
--- /dev/null
+++ b/vendor/partial_ref/Cargo.toml
@@ -0,0 +1,27 @@
+# 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 believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "partial_ref"
+version = "0.3.3"
+authors = ["Jannis Harder <me@jix.one>"]
+description = "Type checked partial references"
+readme = "README.md"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/jix/partial_ref"
+[dependencies.partial_ref_derive]
+version = "=0.3.3"
+
+[dev-dependencies]
+[badges.maintenance]
+status = "deprecated"
diff --git a/vendor/partial_ref/LICENSE-APACHE b/vendor/partial_ref/LICENSE-APACHE
new file mode 100644
index 000000000..16fe87b06
--- /dev/null
+++ b/vendor/partial_ref/LICENSE-APACHE
@@ -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.
diff --git a/vendor/partial_ref/LICENSE-MIT b/vendor/partial_ref/LICENSE-MIT
new file mode 100644
index 000000000..90f71a8d7
--- /dev/null
+++ b/vendor/partial_ref/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2018 Jannis Harder
+
+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.
diff --git a/vendor/partial_ref/README.md b/vendor/partial_ref/README.md
new file mode 100644
index 000000000..1b32c91b2
--- /dev/null
+++ b/vendor/partial_ref/README.md
@@ -0,0 +1,109 @@
+# partial_ref - Type checked partial references.
+
+[![crates.io](https://img.shields.io/crates/v/partial_ref.svg)](https://crates.io/crates/partial_ref)
+[![docs.rs](https://docs.rs/partial_ref/badge.svg)](https://docs.rs/partial_ref)
+![](https://img.shields.io/crates/l/partial_ref.svg)
+
+This crate provides type checked partial references for rust. Type checked
+partial references are one solution to solve
+[interprocedural borrowing conflicts][interprocedural-conflicts].
+
+## Soundness Issues
+
+Previous versions had a potential soundness issue regarding internal address
+computations. This was not clear at the time I wrote the first version. Later
+it became clear, but there was no viable alternative, so I added a warning to
+this readme. Now with [`addr_of`] and [`addr_of_mut`] being stabilized since
+Rust 1.51, I updated the implementation to avoid this issue.
+
+[`addr_of`]:https://doc.rust-lang.org/std/ptr/macro.addr_of.html
+[`addr_of_mut`]:https://doc.rust-lang.org/std/ptr/macro.addr_of_mut.html
+
+## Deprecation
+
+I wrote this library for its use in [Varisat]. After making extensive use of
+this, I am not convinced that overall this is a good approach to solve
+interprocedural borrowing conflict issues. In particular I think the
+implementation is way too complex for the functionality it provides.
+
+I am currently working on a new version of this library that implements the
+same essential idea using a slightly simpler API and a much simpler
+implementation. In general I would recommend trying alternative workarounds to
+avoid interprocedural borrowing conflicts, but if you come to the conclusion
+that partial references are the best solution for your use case, my advice
+would be to wait for the new version of this library to be released.
+
+[varisat]: https://crates.io/crates/varisat
+
+## Example
+
+```rust
+use partial_ref::*;
+
+part!(pub Neighbors: Vec<Vec<usize>>);
+part!(pub Colors: Vec<usize>);
+part!(pub Weights: Vec<f32>);
+
+#[derive(PartialRefTarget, Default)]
+pub struct Graph {
+ #[part(Neighbors)]
+ pub neighbors: Vec<Vec<usize>>,
+ #[part(Colors)]
+ pub colors: Vec<usize>,
+ #[part(Weights)]
+ pub weights: Vec<f32>,
+}
+
+let mut g = Graph::default();
+let mut g_ref = g.into_partial_ref_mut();
+
+g_ref.part_mut(Colors).extend(&[0, 1, 0]);
+g_ref.part_mut(Weights).extend(&[0.25, 0.5, 0.75]);
+
+g_ref.part_mut(Neighbors).push(vec![1, 2]);
+g_ref.part_mut(Neighbors).push(vec![0, 2]);
+g_ref.part_mut(Neighbors).push(vec![0, 1]);
+
+pub fn add_color_to_weight(
+ mut g: partial!(Graph, mut Weights, Colors),
+ index: usize,
+) {
+ g.part_mut(Weights)[index] += g.part(Colors)[index] as f32;
+}
+
+let (neighbors, mut g_ref) = g_ref.split_part_mut(Neighbors);
+let (colors, mut g_ref) = g_ref.split_part(Colors);
+
+for (edges, &color) in neighbors.iter_mut().zip(colors.iter()) {
+ edges.retain(|&neighbor| colors[neighbor] != color);
+
+ for &neighbor in edges.iter() {
+ add_color_to_weight(g_ref.borrow(), neighbor);
+ }
+}
+```
+
+## Documentation
+
+ * [Reference and Tutorial][docs]
+
+## License
+
+The partial_ref source code is licensed under either of
+
+ * Apache License, Version 2.0
+ ([LICENSE-APACHE](LICENSE-APACHE) or
+ http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license
+ ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in partial_ref by you, as defined in the Apache-2.0 license,
+shall be dual licensed as above, without any additional terms or conditions.
+
+[docs]:https://docs.rs/partial_ref
+[interprocedural-conflicts]:http://smallcultfollowing.com/babysteps/blog/2018/11/01/after-nll-interprocedural-conflicts/
diff --git a/vendor/partial_ref/src/lib.rs b/vendor/partial_ref/src/lib.rs
new file mode 100644
index 000000000..03d4f01e9
--- /dev/null
+++ b/vendor/partial_ref/src/lib.rs
@@ -0,0 +1,964 @@
+//! Type checked partial references.
+//!
+//! This crate provides type checked partial references for rust. Type checked partial references
+//! are one solution to solve [interprocedural borrowing conflicts][interprocedural-conflicts].
+//!
+//! # Tutorial
+//!
+//! With this crate it is possible to declare typed parts (using the [`part`] macro) and to assign
+//! struct fields to these parts (by [deriving `PartialRefTarget`](partial_ref_derive)).
+//!
+//! ```
+//! use partial_ref::{part, PartialRefTarget};
+//!
+//! part!(pub Neighbors: Vec<Vec<usize>>);
+//! part!(pub Colors: Vec<usize>);
+//! part!(pub Weights: Vec<f32>);
+//!
+//! #[derive(PartialRefTarget, Default)]
+//! pub struct Graph {
+//! #[part(Neighbors)]
+//! pub neighbors: Vec<Vec<usize>>,
+//! #[part(Colors)]
+//! pub colors: Vec<usize>,
+//! #[part(Weights)]
+//! pub weights: Vec<f32>,
+//! }
+//! ```
+//!
+//! It is then possible to convert a reference to a value using the [`IntoPartialRef`] and
+//! [`IntoPartialRefMut`] traits, which are derived alongside PartialRefTarget. Note that a mutable
+//! partial reference must itself be mutable for mutable access.
+//!
+//! ```
+//! # use partial_ref::{part, PartialRefTarget};
+//! # use partial_ref_tests::doctest_helpers::*;
+//! use partial_ref::IntoPartialRefMut;
+//!
+//! let mut g = Graph::default();
+//!
+//! let mut g_ref = g.into_partial_ref_mut();
+//! ```
+//!
+//! You can access parts using the [`part`](PartialRef::part) and [`part_mut`](PartialRef::part_mut)
+//! methods.
+//!
+//! ```
+//! # use partial_ref::{part, PartialRefTarget, IntoPartialRefMut};
+//! # use partial_ref_tests::doctest_helpers::*;
+//! # let mut g = Graph::default();
+//! # let mut g_ref = g.into_partial_ref_mut();
+//! use partial_ref::PartialRef;
+//!
+//! g_ref.part_mut(Colors).extend(&[0, 1, 0]);
+//! g_ref.part_mut(Weights).extend(&[0.25, 0.5, 0.75]);
+//!
+//! g_ref.part_mut(Neighbors).push(vec![1, 2]);
+//! g_ref.part_mut(Neighbors).push(vec![0, 2]);
+//! g_ref.part_mut(Neighbors).push(vec![0, 1]);
+//!
+//! assert_eq!(g_ref.part(Colors).len(), g_ref.part(Neighbors).len());
+//! assert_eq!(g_ref.part(Colors).len(), g_ref.part(Weights).len());
+//! ```
+//!
+//! We can now write a function that takes parts of a reference. The type of such a partial
+//! reference can be written using the [`partial`] macro, which expands to a combination of [`Mut`],
+//! [`Const`] and [`Ref`]. Again the parameter `g` here must be mutable to allow mutable access to
+//! the referenced value. To call such a function we use the [`borrow`](PartialRef::borrow) method,
+//! which will re-borrow just the required parts.
+//!
+//! ```
+//! # use partial_ref::{part, PartialRefTarget, IntoPartialRefMut, PartialRef};
+//! # use partial_ref_tests::doctest_helpers::*;
+//! # let mut g = example_graph();
+//! # let mut g_ref = g.into_partial_ref_mut();
+//! use partial_ref::partial;
+//!
+//! pub fn add_color_to_weight(
+//! mut g: partial!(Graph, mut Weights, Colors),
+//! index: usize,
+//! ) {
+//! g.part_mut(Weights)[index] += g.part(Colors)[index] as f32;
+//! }
+//!
+//! add_color_to_weight(g_ref.borrow(), 1);
+//!
+//! assert_eq!(g_ref.part(Weights)[1], 1.5);
+//! ```
+//!
+//! So far everything could have been written using plain built-in references. This changes as soon
+//! as we want to iterate over the neighbors while invoking our function. Usually we couldn't pass a
+//! mutable reference to the graph while holding the iterator over the neighbors.
+//!
+//! This can be easily done using partial references which support splitting. Splitting means
+//! turning a single reference into two references where each has a subset of parts, so that each
+//! mutably referenced part belongs only to a single reference. This is done by the
+//! [`split_borrow`](PartialRef::borrow) and [`split_part`](PartialRef::split_part) methods.
+//!
+//! ```
+//! # use partial_ref::{part, PartialRefTarget, IntoPartialRefMut, PartialRef, partial};
+//! # use partial_ref_tests::doctest_helpers::*;
+//! # let mut g = example_graph();
+//! # let mut g_ref = g.into_partial_ref_mut();
+//! let (neighbors, mut g_ref) = g_ref.split_part_mut(Neighbors);
+//! let (colors, mut g_ref) = g_ref.split_part(Colors);
+//!
+//! for (edges, &color) in neighbors.iter_mut().zip(colors.iter()) {
+//! edges.retain(|&neighbor| colors[neighbor] != color);
+//!
+//! for &neighbor in edges.iter() {
+//! add_color_to_weight(g_ref.borrow(), neighbor);
+//! }
+//! }
+//! ```
+//!
+//! This covers the basic functionality of this library. Beyond that this library also supports:
+//!
+//! * Partial references to nested structs using [`Nested`] and [`nested_part`].
+//! * Generic functions with bounds on available parts using [`HasPart`].
+//!
+//! # Notes
+//!
+//! Some documented items are marked with *(internal)*. Typical code using this library doesn't
+//! explicitly refer to them. Nevertheless they often appear in error messages and are thus part of
+//! this documentation. These items also have to be public for the inference driven meta programming
+//! to work. Code that is generic over parts of partial references might also need them.
+//!
+//! Many traits in this crate are marked as unsafe without documenting any requirements for
+//! implementations. This does not mean they are safe to implement, but rather means that they are
+//! not intended to be implemented outside of this library. Feel free to file an issue if you have a
+//! good reason to implement them so the requirements can be documented.
+//!
+//! [interprocedural-conflicts]: http://smallcultfollowing.com/babysteps/blog/2018/11/01/after-nll-interprocedural-conflicts/
+
+#[macro_use]
+mod macros;
+
+pub use partial_ref_derive::PartialRefTarget;
+
+use std::marker::PhantomData;
+
+/// A type that can be the target of partial references.
+///
+/// Implementations for this trait should be derived, see [`partial_ref_derive`].
+pub trait PartialRefTarget {
+ /// A partial reference will be represented by a pointer to this associated type.
+ ///
+ /// In most cases this is the implementing type itself. This is not a requirement though. In the
+ /// future, some features will introduce PartialRefTargets that have a different associated
+ /// `RawTarget` type.
+ type RawTarget: ?Sized;
+}
+
+/// Helper trait to associate the target type with a [`PartialRef`] without needing a lifetime.
+pub trait HasTarget {
+ /// The referenced type.
+ ///
+ // TODO add a warning that Target::RawTarget could be != Target when such a feature lands)
+ type Target: PartialRefTarget + ?Sized;
+}
+
+/// A partial reference.
+///
+/// This is implemented by variants of [`Ref`], [`Mut`] and [`Const`]. This is only implemented if the
+/// parts of any contained [`Mut`] or [`Const`] are valid for the referenced type.
+pub trait PartialRef<'a>: HasTarget + Sized {
+ /// Create a partial reference from a raw pointer.
+ ///
+ /// # Safety
+ /// This is unsafe for two reasons. It can be used to dereference a raw pointer, which is
+ /// already unsafe on its own, and it can be used to construct invalid partial references, for
+ /// example containing the same mutable part twice. Thus extra care is required when calling
+ /// this.
+ unsafe fn from_raw(ptr: *mut <Self::Target as PartialRefTarget>::RawTarget) -> Self;
+
+ /// Access to the underlying raw pointer.
+ ///
+ /// Beware that this can be used even for an empty reference with no parts. Doing anything with
+ /// the resulting pointer is very likely unsafe, even if the partial reference is still in
+ /// scope.
+ fn get_raw(&self) -> *mut <Self::Target as PartialRefTarget>::RawTarget;
+
+ /// Partially re-borrows a partial reference.
+ ///
+ /// This returns a new partial reference to the same value. The returned reference can have a
+ /// subset of the original reference's parts.
+ ///
+ /// A typical use case is passing a reference to a function that requires fewer parts than the
+ /// caller.
+ ///
+ /// Usually the type parameters can be inferred.
+ #[inline(always)]
+ fn borrow<BorrowedRef, SubsetIndex>(&'a mut self) -> BorrowedRef
+ where
+ BorrowedRef: PartialRef<'a, Target = Self::Target>,
+ Self: HasSubset<'a, BorrowedRef, SubsetIndex>,
+ {
+ unsafe { BorrowedRef::from_raw(self.get_raw()) }
+ }
+
+ /// Access a part of the referenced value.
+ ///
+ /// This returns a plain reference to a single part.
+ ///
+ /// The parameter is only present for type inference, its value is ignored. As all parts
+ /// implement [`Default`] it is always possible to pass a default value, which is useful in
+ /// generic code.
+ ///
+ /// Usually the type parameters can be inferred.
+ #[inline(always)]
+ fn part<FieldPartSpec, FieldPart, PartIndex, FieldType>(
+ &'a self,
+ _part: FieldPartSpec,
+ ) -> &'a FieldType
+ where
+ FieldType: ?Sized,
+ FieldPart: Part<PartType = Field<FieldType>>,
+ FieldPartSpec: PartSpec<FieldPart>,
+ Self: PluckConst<'a, FieldPart, PartIndex>,
+ Self::Target: HasPart<FieldPart> + 'a,
+ {
+ unsafe {
+ <Const<FieldPart, Ref<'a, Self::Target>> as PartialRef<'a>>::from_raw(self.get_raw())
+ .get_part()
+ }
+ }
+
+ /// Mutable access to a part of the referenced value.
+ ///
+ /// This returns a plain mutable reference to a single part.
+ ///
+ /// The parameter is only present for type inference, its value is ignored. As all parts
+ /// implement [`Default`] it is always possible to pass a default value, which is useful in
+ /// generic code.
+ ///
+ /// Usually the type parameters can be inferred.
+ #[inline(always)]
+ fn part_mut<FieldPartSpec, FieldPart, PartIndex, FieldType>(
+ &'a mut self,
+ _part: FieldPartSpec,
+ ) -> &'a mut FieldType
+ where
+ FieldType: ?Sized,
+ FieldPart: Part<PartType = Field<FieldType>>,
+ FieldPartSpec: PartSpec<FieldPart>,
+ Self: PluckMut<'a, FieldPart, PartIndex>,
+ Self::Target: HasPart<FieldPart> + 'a,
+ {
+ unsafe {
+ <Mut<FieldPart, Ref<'a, Self::Target>> as PartialRef<'a>>::from_raw(self.get_raw())
+ .get_part_mut()
+ }
+ }
+
+ /// Partially re-borrows a partial reference, splitting off the remaining parts.
+ ///
+ /// This is equivalent to [`borrow`](PartialRef::borrow) but also returns a second partial
+ /// reference that contains all parts that can be used simultaneously with the re-borrowed
+ /// reference.
+ ///
+ /// This means that constant parts are contained in both references, while mutable parts that
+ /// are re-borrowed are missing from the second partial reference. Mutable parts that are
+ /// re-borrowed as constant parts are constant parts of both references.
+ ///
+ /// Usually the type parameters can be inferred.
+ #[inline(always)]
+ fn split_borrow<BorrowedRef, SubsetIndex>(&'a mut self) -> (BorrowedRef, Self::Remainder)
+ where
+ BorrowedRef: PartialRef<'a, Target = Self::Target>,
+ Self: HasSubset<'a, BorrowedRef, SubsetIndex>,
+ {
+ let ptr = self.get_raw();
+ unsafe { (BorrowedRef::from_raw(ptr), Self::Remainder::from_raw(ptr)) }
+ }
+
+ /// Access a part of the referenced value, splitting off the remaining parts.
+ ///
+ /// This is equivalent to [`part`](PartialRef::part) but also returns a partial reference as
+ /// described in [`split_borrow`](PartialRef::split_borrow).
+ #[inline(always)]
+ fn split_part<FieldPartSpec, FieldPart, PartIndex, FieldType>(
+ &'a mut self,
+ _part: FieldPartSpec,
+ ) -> (&'a FieldType, Self::Remainder)
+ where
+ FieldType: ?Sized,
+ FieldPart: Part<PartType = Field<FieldType>>,
+ FieldPartSpec: PartSpec<FieldPart>,
+ Self: PluckConst<'a, FieldPart, PartIndex>,
+ Self::Target: HasPart<FieldPart> + 'a,
+ {
+ let ptr = self.get_raw();
+ unsafe {
+ (
+ <Const<FieldPart, Ref<'a, Self::Target>> as PartialRef<'a>>::from_raw(ptr)
+ .get_part(),
+ Self::Remainder::from_raw(ptr),
+ )
+ }
+ }
+
+ /// Mutable access to a part of the referenced value, splitting off the remaining parts.
+ ///
+ /// This is equivalent to [`part_mut`](PartialRef::part_mut) but also returns a partial
+ /// reference as described in [`split_borrow`](PartialRef::split_borrow).
+ #[inline(always)]
+ fn split_part_mut<FieldPartSpec, FieldPart, PartIndex, FieldType>(
+ &'a mut self,
+ _part: FieldPartSpec,
+ ) -> (&'a mut FieldType, Self::Remainder)
+ where
+ FieldType: ?Sized,
+ FieldPart: Part<PartType = Field<FieldType>>,
+ FieldPartSpec: PartSpec<FieldPart>,
+ Self: PluckMut<'a, FieldPart, PartIndex>,
+ Self::Target: HasPart<FieldPart> + 'a,
+ {
+ let ptr = self.get_raw();
+ unsafe {
+ (
+ <Mut<FieldPart, Ref<'a, Self::Target>> as PartialRef<'a>>::from_raw(ptr)
+ .get_part_mut(),
+ Self::Remainder::from_raw(ptr),
+ )
+ }
+ }
+}
+
+/// Construction of partial references.
+///
+/// See also [`IntoPartialRefMut`].
+///
+/// This trait gets an automatic implementation for references (mutable or immutable) to any type
+/// that has a derive statement for [`PartialRefTarget`]. Usually there is no need to implement this
+/// trait manually.
+pub trait IntoPartialRef<'a> {
+ type Ref: PartialRef<'a>;
+
+ /// Convert a mutable or immutable reference into a partial reference.
+ fn into_partial_ref(self) -> Self::Ref;
+}
+
+/// Construction of partial references from mutable references.
+///
+/// This has an implementation for mutable references that implement [`IntoPartialRefMut`]. It
+/// performs the same operation as [`IntoPartialRefMut`] but is only implemented for mutable
+/// references. This is useful as it allows writing `value.into_partial_ref_mut()` instead of `(&mut
+/// value).into_partial_ref_mut()` using auto referencing of method calls. Using just
+/// [`value.into_partial_ref()`] would result in an immutable reference.
+pub trait IntoPartialRefMut<'a>: IntoPartialRef<'a> {
+ /// Convert a mutable reference into a partial reference.
+ fn into_partial_ref_mut(self) -> Self::Ref;
+}
+
+impl<'a, T> IntoPartialRefMut<'a> for &'a mut T
+where
+ Self: IntoPartialRef<'a>,
+{
+ fn into_partial_ref_mut(self) -> Self::Ref {
+ self.into_partial_ref()
+ }
+}
+
+/// *(internal)* Split a part into nested parts.
+///
+/// This is used to implement splitting of nested parts.
+pub unsafe trait SplitIntoParts<'a, ContainingPart, Reference: PartialRef<'a>> {
+ /// A partial reference that has all the parts `Reference` and all parts of `Self` nested in
+ /// `ContainingPart` as constant parts.
+ type Result: PartialRef<'a, Target = Reference::Target>;
+ /// A partial reference that has all the parts `Reference` and all parts of `Self` nested in
+ /// `ContainingPart` as mutable parts.
+ type ResultMut: PartialRef<'a, Target = Reference::Target>;
+}
+
+/// An empty partial reference borrowing no parts.
+///
+/// Partial references with a non-empty set of borrowed parts are built by nesting this type within
+/// the [`Mut`] and [`Const`] types.
+#[repr(transparent)]
+pub struct Ref<'a, Target: PartialRefTarget + ?Sized> {
+ ptr: *mut Target::RawTarget,
+ phantom: PhantomData<&'a mut Target>,
+}
+
+impl<'a, Target: PartialRefTarget + ?Sized> HasTarget for Ref<'a, Target> {
+ type Target = Target;
+}
+
+/// An empty reference to a valid target is a valid reference.
+impl<'a, 'b: 'a, Target: PartialRefTarget + ?Sized> PartialRef<'a> for Ref<'b, Target> {
+ #[inline(always)]
+ unsafe fn from_raw(ptr: *mut <Self::Target as PartialRefTarget>::RawTarget) -> Self {
+ Ref {
+ ptr,
+ phantom: PhantomData,
+ }
+ }
+
+ #[inline(always)]
+ fn get_raw(&self) -> *mut <Self::Target as PartialRefTarget>::RawTarget {
+ self.ptr
+ }
+}
+
+/// An empty reference contains no mutable parts and thus is safe to clone.
+impl<'a, Target: PartialRefTarget> Copy for Ref<'a, Target> {}
+
+/// An empty reference contains no mutable parts and thus is safe to clone.
+impl<'a, Target: PartialRefTarget> Clone for Ref<'a, Target> {
+ #[inline(always)]
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+/// A mutable part of a partial reference.
+#[repr(transparent)]
+pub struct Mut<Part, Reference: HasTarget> {
+ ptr: *mut <<Reference as HasTarget>::Target as PartialRefTarget>::RawTarget,
+ phantom: PhantomData<(Reference, Part)>,
+}
+
+impl<'a, SomePart: Part, Reference: PartialRef<'a>> HasTarget for Mut<SomePart, Reference>
+where
+ Reference::Target: HasPart<SomePart>,
+{
+ type Target = Reference::Target;
+}
+
+/// Extending a valid reference by a mutable part is still a valid reference when the reference
+/// target has such a part.
+impl<'a, SomePart: Part, Reference: PartialRef<'a>> PartialRef<'a> for Mut<SomePart, Reference>
+where
+ Reference::Target: HasPart<SomePart>,
+{
+ #[inline(always)]
+ unsafe fn from_raw(ptr: *mut <Self::Target as PartialRefTarget>::RawTarget) -> Self {
+ Mut {
+ ptr,
+ phantom: PhantomData,
+ }
+ }
+
+ #[inline(always)]
+ fn get_raw(&self) -> *mut <Self::Target as PartialRefTarget>::RawTarget {
+ self.ptr
+ }
+}
+
+/// A constant (immutable) part of a partial reference.
+#[repr(transparent)]
+pub struct Const<Part, Reference: HasTarget> {
+ ptr: *mut <<Reference as HasTarget>::Target as PartialRefTarget>::RawTarget,
+ phantom: PhantomData<(Reference, Part)>,
+}
+
+impl<'a, SomePart: Part, Reference: PartialRef<'a>> HasTarget for Const<SomePart, Reference>
+where
+ Reference::Target: HasPart<SomePart>,
+{
+ type Target = Reference::Target;
+}
+
+/// Extending a valid reference by a constant part is still a valid reference when the reference
+/// target has such a part.
+impl<'a, SomePart: Part, Reference: PartialRef<'a>> PartialRef<'a> for Const<SomePart, Reference>
+where
+ Reference::Target: HasPart<SomePart>,
+{
+ #[inline(always)]
+ unsafe fn from_raw(ptr: *mut <Self::Target as PartialRefTarget>::RawTarget) -> Self {
+ Const {
+ ptr,
+ phantom: PhantomData,
+ }
+ }
+
+ #[inline(always)]
+ fn get_raw(&self) -> *mut <Self::Target as PartialRefTarget>::RawTarget {
+ self.ptr
+ }
+}
+
+/// A reference containing just constant parts is safe to clone.
+impl<SomePart, Reference: Copy + HasTarget> Copy for Const<SomePart, Reference> {}
+
+/// A reference containing just constant parts is safe to clone.
+impl<SomePart, Reference: Copy + HasTarget> Clone for Const<SomePart, Reference> {
+ #[inline(always)]
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<'a, SomePart, Target, FieldType> Const<SomePart, Ref<'a, Target>>
+where
+ FieldType: ?Sized,
+ SomePart: Part<PartType = Field<FieldType>>,
+ Target: ?Sized,
+ Target: HasPart<SomePart>,
+{
+ /// Only available on single part references, used to implement the more general
+ /// [`part`](PartialRef::part) method of [`PartialRef`].
+ #[inline(always)]
+ fn get_part(self) -> &'a FieldType {
+ unsafe { &*Target::part_ptr(self.get_raw() as *const _) }
+ }
+}
+
+impl<'a, SomePart, Target, FieldType> Mut<SomePart, Ref<'a, Target>>
+where
+ FieldType: ?Sized,
+ SomePart: Part<PartType = Field<FieldType>>,
+ Target: ?Sized,
+ Target: HasPart<SomePart>,
+{
+ /// Only available on single part references, used to implement the more general
+ /// [`part_mut`](PartialRef::part_mut) method of [`PartialRef`]
+ #[inline(always)]
+ fn get_part_mut(self) -> &'a mut FieldType {
+ unsafe { &mut *Target::part_ptr_mut(self.get_raw()) }
+ }
+}
+
+// Parts
+
+/// Marker types for a part of a type.
+///
+/// Types implementing this trait are usually created using the [`part`] macro.
+///
+/// A type implementing this trait is used to identify a part of a reference target. Multiple
+/// different reference targets can have a part identified by the same [`Part`] (see also
+/// [`HasPart`]). A part has an associated [`PartType`], which determines what can be done with a
+/// part.
+pub trait Part: Default {
+ type PartType: PartType;
+}
+
+/// Helper trait to strip lifetimes from a part.
+///
+/// Every part `SomePart<'a, ...>` should implement `PartSpec<SomePart<'b, ...>>`. This is used by
+/// the [`part`](PartialRef::part), [`part_mut`](PartialRef::part_mut),
+/// [`split_part`](PartialRef::split_part) and [`split_part_mut`](PartialRef::split_part_mut)
+/// functions. This allows the passed parameter to have a different lifetime than the accessed part.
+/// This in turn enables part selection using globals with static lifetimes as declared by the
+/// [`part`] macro.
+pub trait PartSpec<Part> {}
+
+/// Implemented when a reference target has a part.
+///
+/// This trait provides methods for unchecked access to a part of a reference target.
+/// Implementations for this are automatically created when deriving PartialRefTarget.
+pub trait HasPart<SomePart: Part>: PartialRefTarget {
+ /// Given a constant pointer to a target, produce a constant pointer to a part of it.
+ ///
+ /// # Safety
+ /// Implementations may construct a temporary reference to ptr, which thus must be valid.
+ unsafe fn part_ptr(ptr: *const Self::RawTarget) -> <SomePart::PartType as PartType>::Ptr;
+ /// Given a mutable pointer to a target, produce a mutable pointer to a part of it.
+ ///
+ /// # Safety
+ /// Implementations may construct a temporary reference to ptr, which thus must be valid.
+ unsafe fn part_ptr_mut(ptr: *mut Self::RawTarget) -> <SomePart::PartType as PartType>::PtrMut;
+}
+
+/// Type of a part, determines what can be done with a part.
+///
+/// Common part types are [`Field`] and [`AbstractPart`].
+pub trait PartType {
+ /// Type that can be produced from a constant pointer to a reference target.
+ type Ptr;
+ /// Type that can be produced from a mutable pointer to a reference target.
+ type PtrMut;
+}
+
+/// Type of a part that corresponds to a struct field.
+///
+/// Partial references containing a part of this type provide access to that field.
+pub struct Field<FieldType: ?Sized>(PhantomData<FieldType>);
+
+impl<FieldType: ?Sized> PartType for Field<FieldType> {
+ type Ptr = *const FieldType;
+ type PtrMut = *mut FieldType;
+}
+
+/// Type of an abstract part.
+///
+/// Partial reference keep track of an abstract part, without providing any operations on it.
+pub struct AbstractPart;
+
+impl PartType for AbstractPart {
+ type Ptr = ();
+ type PtrMut = ();
+}
+
+/// A nested part.
+///
+/// A nested part can be constructed from an outer part and an inner part. The outer part must be a
+/// [`Field`] part, and the field's type must be a [`PartialRefTarget`] having the the inner part
+/// ([`HasPart`]).
+///
+/// When nesting multiple times, the nested part should always be the outer part. This isn't
+/// enforced, but some operations are only supported in that case.
+#[derive(Default)]
+pub struct Nested<Outer, Inner>(Outer, Inner);
+
+/// Create default values for nested parts.
+///
+/// These are useful as parameters to pass to [`PartialRef`]'s part functions.
+impl<NewInnerPart: Part, Outer: Part, Inner: Part> std::ops::BitOr<NewInnerPart>
+ for Nested<Outer, Inner>
+{
+ type Output = Nested<Nested<Outer, Inner>, NewInnerPart>;
+
+ fn bitor(self, _rhs: NewInnerPart) -> Self::Output {
+ std::default::Default::default()
+ }
+}
+
+/// A nested part is itself a part.
+impl<Outer, OuterFieldType, Inner> Part for Nested<Outer, Inner>
+where
+ Outer: Part<PartType = Field<OuterFieldType>>,
+ Inner: Part,
+ OuterFieldType: ?Sized,
+ OuterFieldType: HasPart<Inner>,
+ OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
+{
+ type PartType = Inner::PartType;
+}
+
+impl<Outer, Inner, OuterS, InnerS> PartSpec<Nested<OuterS, InnerS>> for Nested<Outer, Inner>
+where
+ Outer: PartSpec<OuterS>,
+ Inner: PartSpec<InnerS>,
+{
+}
+
+/// A reference has a nested part if it has the outer part and the nested part is valid.
+impl<Reference, Outer, OuterFieldType, Inner> HasPart<Nested<Outer, Inner>> for Reference
+where
+ Reference: ?Sized,
+ Reference: HasPart<Outer>,
+ Outer: Part<PartType = Field<OuterFieldType>>,
+ Inner: Part,
+ OuterFieldType: ?Sized,
+ OuterFieldType: HasPart<Inner>,
+ OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
+{
+ #[inline(always)]
+ unsafe fn part_ptr(ptr: *const Self::RawTarget) -> <Inner::PartType as PartType>::Ptr {
+ <OuterFieldType as HasPart<Inner>>::part_ptr(<Self as HasPart<Outer>>::part_ptr(ptr))
+ }
+
+ #[inline(always)]
+ unsafe fn part_ptr_mut(ptr: *mut Self::RawTarget) -> <Inner::PartType as PartType>::PtrMut {
+ <OuterFieldType as HasPart<Inner>>::part_ptr_mut(<Self as HasPart<Outer>>::part_ptr_mut(
+ ptr,
+ ))
+ }
+}
+
+// Type level logic for subsetting
+// This is inspired by the `frunk` crate
+
+/// *(internal)* Select the first part.
+pub struct IndexHere;
+
+/// *(internal)* Skip the first part.
+pub struct IndexNext<Index>(Index);
+
+/// *(internal)* Split the first part.
+pub struct IndexSplit<NestedPartIndex, Index>(NestedPartIndex, Index);
+
+/// *(internal)* Extracts the constant part `PluckedPart` at position `Index` from the partial
+/// reference having this trait, leaving `Self::Remainder`.
+///
+/// Plucking a constant part still leaves the part in the remaining reference, but will change it
+/// from mutable to constant.
+///
+/// The `Index` type can be inferred.
+pub unsafe trait PluckConst<'a, PluckedPart, Index>: PartialRef<'a> {
+ /// The partial reference left after plucking.
+ type Remainder: PartialRef<'a, Target = Self::Target>;
+}
+
+/// *(internal)* Extracts the mutable part `PluckedPart` at position `Index` from the partial
+/// reference having this trait, leaving `Self::Remainder`.
+///
+/// Plucking a mutable part removes it from the remaining reference.
+///
+/// The `Index` type can be inferred.
+pub unsafe trait PluckMut<'a, PluckedPart, Index>: PartialRef<'a> {
+ /// The partial reference left after plucking.
+ type Remainder: PartialRef<'a, Target = Self::Target>;
+}
+
+/// *(internal)* Plucks the outermost constant part.
+unsafe impl<'a, PluckedPart, Reference> PluckConst<'a, PluckedPart, IndexHere>
+ for Const<PluckedPart, Reference>
+where
+ PluckedPart: Part,
+ Reference: PartialRef<'a>,
+ Reference::Target: HasPart<PluckedPart>,
+{
+ type Remainder = Const<PluckedPart, Reference>;
+}
+
+/// *(internal)* Plucks the first part, converting it from mutable to constant.
+unsafe impl<'a, PluckedPart, Reference> PluckConst<'a, PluckedPart, IndexHere>
+ for Mut<PluckedPart, Reference>
+where
+ PluckedPart: Part,
+ Reference: PartialRef<'a>,
+ Reference::Target: HasPart<PluckedPart>,
+{
+ type Remainder = Const<PluckedPart, Reference>;
+}
+
+/// *(internal)* Plucks the first mutable part.
+unsafe impl<'a, PluckedPart, Reference> PluckMut<'a, PluckedPart, IndexHere>
+ for Mut<PluckedPart, Reference>
+where
+ PluckedPart: Part,
+ Reference: PartialRef<'a>,
+ Reference::Target: HasPart<PluckedPart>,
+{
+ type Remainder = Reference;
+}
+
+/// *(internal)* Skips the constant first part while plucking a constant part.
+unsafe impl<'a, PluckedPart, SkippedPart, Reference, Index>
+ PluckConst<'a, PluckedPart, IndexNext<Index>> for Const<SkippedPart, Reference>
+where
+ PluckedPart: Part,
+ SkippedPart: Part,
+ Reference::Target: HasPart<PluckedPart>,
+ Reference::Target: HasPart<SkippedPart>,
+ Reference: PluckConst<'a, PluckedPart, Index>,
+{
+ type Remainder = Const<SkippedPart, Reference::Remainder>;
+}
+
+/// *(internal)* Skips the mutable first part while plucking a constant part.
+unsafe impl<'a, PluckedPart, SkippedPart, Reference, Index>
+ PluckConst<'a, PluckedPart, IndexNext<Index>> for Mut<SkippedPart, Reference>
+where
+ PluckedPart: Part,
+ SkippedPart: Part,
+ Reference::Target: HasPart<PluckedPart>,
+ Reference::Target: HasPart<SkippedPart>,
+ Reference: PluckConst<'a, PluckedPart, Index>,
+{
+ type Remainder = Mut<SkippedPart, Reference::Remainder>;
+}
+
+/// *(internal)* Skips the constant first part while plucking a mutable part.
+unsafe impl<'a, PluckedPart, SkippedPart, Reference, Index>
+ PluckMut<'a, PluckedPart, IndexNext<Index>> for Const<SkippedPart, Reference>
+where
+ PluckedPart: Part,
+ SkippedPart: Part,
+ Reference::Target: HasPart<PluckedPart>,
+ Reference::Target: HasPart<SkippedPart>,
+ Reference: PluckMut<'a, PluckedPart, Index>,
+{
+ type Remainder = Const<SkippedPart, Reference::Remainder>;
+}
+
+/// *(internal)* Skips the mutable first part while plucking a mutable part.
+unsafe impl<'a, PluckedPart, SkippedPart, Reference, Index>
+ PluckMut<'a, PluckedPart, IndexNext<Index>> for Mut<SkippedPart, Reference>
+where
+ PluckedPart: Part,
+ SkippedPart: Part,
+ Reference::Target: HasPart<PluckedPart>,
+ Reference::Target: HasPart<SkippedPart>,
+ Reference: PluckMut<'a, PluckedPart, Index>,
+{
+ type Remainder = Mut<SkippedPart, Reference::Remainder>;
+}
+
+/// *(internal)* Pluck a mutable nested subpart of the mutable first part.
+///
+/// This leaves all other subparts in the remaining reference.
+unsafe impl<
+ 'a,
+ ContainingPart,
+ PluckedOuter,
+ PluckedInner,
+ Reference,
+ NestedPartIndex,
+ Index,
+ OuterFieldType,
+ ContainingFieldType,
+ > PluckMut<'a, Nested<PluckedOuter, PluckedInner>, IndexSplit<NestedPartIndex, Index>>
+ for Mut<ContainingPart, Reference>
+where
+ PluckedOuter: Part<PartType = Field<OuterFieldType>>,
+ PluckedInner: Part,
+ ContainingPart: Part<PartType = Field<ContainingFieldType>>,
+ ContainingFieldType: SplitIntoParts<'a, ContainingPart, Reference>,
+ ContainingFieldType: ?Sized,
+ ContainingFieldType::ResultMut: PluckMut<'a, Nested<PluckedOuter, PluckedInner>, Index>,
+ OuterFieldType: ?Sized,
+ OuterFieldType: HasPart<PluckedInner>,
+ OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
+ Reference: PartialRef<'a>,
+ Reference::Target: HasPart<ContainingPart>,
+ ContainingPart: ContainsNestedPart<PluckedOuter, NestedPartIndex>,
+{
+ type Remainder = <ContainingFieldType::ResultMut as PluckMut<
+ 'a,
+ Nested<PluckedOuter, PluckedInner>,
+ Index,
+ >>::Remainder;
+}
+
+/// *(internal)* Pluck a constant nested subpart of the mutable first part.
+///
+/// This leaves all other subparts as mutable in the remaining reference.
+unsafe impl<
+ 'a,
+ ContainingPart,
+ PluckedOuter,
+ PluckedInner,
+ Reference,
+ NestedPartIndex,
+ Index,
+ OuterFieldType,
+ ContainingFieldType,
+ > PluckConst<'a, Nested<PluckedOuter, PluckedInner>, IndexSplit<NestedPartIndex, Index>>
+ for Mut<ContainingPart, Reference>
+where
+ PluckedOuter: Part<PartType = Field<OuterFieldType>>,
+ PluckedInner: Part,
+ ContainingPart: Part<PartType = Field<ContainingFieldType>>,
+ ContainingFieldType: SplitIntoParts<'a, ContainingPart, Reference>,
+ ContainingFieldType: ?Sized,
+ ContainingFieldType::ResultMut: PluckConst<'a, Nested<PluckedOuter, PluckedInner>, Index>,
+ OuterFieldType: ?Sized,
+ OuterFieldType: HasPart<PluckedInner>,
+ OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
+ Reference: PartialRef<'a>,
+ Reference::Target: HasPart<ContainingPart>,
+ ContainingPart: ContainsNestedPart<PluckedOuter, NestedPartIndex>,
+{
+ type Remainder = <ContainingFieldType::ResultMut as PluckConst<
+ 'a,
+ Nested<PluckedOuter, PluckedInner>,
+ Index,
+ >>::Remainder;
+}
+
+/// *(internal)* Pluck a constant nested subpart of the constant first part.
+unsafe impl<
+ 'a,
+ ContainingPart,
+ PluckedOuter,
+ PluckedInner,
+ Reference,
+ NestedPartIndex,
+ Index,
+ OuterFieldType,
+ ContainingFieldType,
+ > PluckConst<'a, Nested<PluckedOuter, PluckedInner>, IndexSplit<NestedPartIndex, Index>>
+ for Const<ContainingPart, Reference>
+where
+ PluckedOuter: Part<PartType = Field<OuterFieldType>>,
+ PluckedInner: Part,
+ ContainingPart: Part<PartType = Field<ContainingFieldType>>,
+ ContainingFieldType: SplitIntoParts<'a, ContainingPart, Reference>,
+ ContainingFieldType: ?Sized,
+ ContainingFieldType::ResultMut: PluckConst<'a, Nested<PluckedOuter, PluckedInner>, Index>,
+ OuterFieldType: ?Sized,
+ OuterFieldType: HasPart<PluckedInner>,
+ OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
+ Reference: PartialRef<'a>,
+ Reference::Target: HasPart<ContainingPart>,
+ ContainingPart: ContainsNestedPart<PluckedOuter, NestedPartIndex>,
+{
+ type Remainder = Const<ContainingPart, Reference>;
+}
+
+/// *(internal)* Index for the empty subset.
+pub struct SubsetIndexEnd;
+
+/// *(internal)* Construct a subset index from a part index and another subset index.
+pub struct SubsetIndexCons<PartIndex, TailIndex>(PartIndex, TailIndex);
+
+/// *(internal)* Asserts that the parts of the partial reference `Reference` are a subset of the
+/// parts of the partial reference having this trait.
+///
+/// A list of parts is considered a subset if they can be plucked in sequence.
+pub unsafe trait HasSubset<'a, Reference, SubsetIndex>: PartialRef<'a> {
+ type Remainder: PartialRef<'a, Target = Self::Target>;
+}
+
+/// *(internal)* Every reference has the empty reference as subset.
+unsafe impl<'a, Reference> HasSubset<'a, Ref<'a, Reference::Target>, SubsetIndexEnd> for Reference
+where
+ Reference: PartialRef<'a>,
+{
+ type Remainder = Reference;
+}
+
+/// *(internal)* To have a reference with a constant first part as subset, pluck that part and make
+/// sure the remaining references are in a subset relation.
+unsafe impl<'a, SubsetPart, Reference, PluckedRef, PartIndex, TailIndex>
+ HasSubset<'a, Const<SubsetPart, Reference>, SubsetIndexCons<PartIndex, TailIndex>>
+ for PluckedRef
+where
+ PluckedRef: PluckConst<'a, SubsetPart, PartIndex>,
+ <PluckedRef as PluckConst<'a, SubsetPart, PartIndex>>::Remainder:
+ HasSubset<'a, Reference, TailIndex>,
+ Reference: HasTarget,
+{
+ type Remainder =
+ <<PluckedRef as PluckConst<'a, SubsetPart, PartIndex>>::Remainder as HasSubset<
+ 'a,
+ Reference,
+ TailIndex,
+ >>::Remainder;
+}
+
+/// *(internal)* To have a reference with a mutable first part as subset, pluck that part and make
+/// sure the remaining references are in a subset relation.
+unsafe impl<'a, SubsetPart, Reference, PluckedRef, PartIndex, TailIndex>
+ HasSubset<'a, Mut<SubsetPart, Reference>, SubsetIndexCons<PartIndex, TailIndex>> for PluckedRef
+where
+ PluckedRef: PluckMut<'a, SubsetPart, PartIndex>,
+ <PluckedRef as PluckMut<'a, SubsetPart, PartIndex>>::Remainder:
+ HasSubset<'a, Reference, TailIndex>,
+ Reference: HasTarget,
+{
+ type Remainder =
+ <<PluckedRef as PluckMut<'a, SubsetPart, PartIndex>>::Remainder as HasSubset<
+ 'a,
+ Reference,
+ TailIndex,
+ >>::Remainder;
+}
+
+// Nesting helpers
+
+/// *(internal)* Check whether a part is nested inside another part.
+pub trait ContainsNestedPart<NestedPart, Index>: Part {}
+
+/// *(internal)* A part contains itself as a nested part.
+impl<NestedPart> ContainsNestedPart<NestedPart, IndexHere> for NestedPart where NestedPart: Part {}
+
+/// *(internal)* A part contains a nested part if it contains the outer part of the nested part.
+impl<NestedPart, Outer, Inner, OuterFieldType, Index>
+ ContainsNestedPart<Nested<Outer, Inner>, IndexNext<Index>> for NestedPart
+where
+ NestedPart: Part,
+ Inner: Part,
+ NestedPart: ContainsNestedPart<Outer, Index>,
+ Outer: Part<PartType = Field<OuterFieldType>>,
+ OuterFieldType: ?Sized,
+ OuterFieldType: HasPart<Inner>,
+ OuterFieldType: PartialRefTarget<RawTarget = OuterFieldType>,
+{
+}
diff --git a/vendor/partial_ref/src/macros.rs b/vendor/partial_ref/src/macros.rs
new file mode 100644
index 000000000..49930e4d6
--- /dev/null
+++ b/vendor/partial_ref/src/macros.rs
@@ -0,0 +1,154 @@
+/// Declares a [`Part`].
+///
+/// Defines an empty struct type and derives all necessary instances to use it as a marker type for
+/// parts.
+///
+/// This macro can define [`AbstractPart`]s using `part!(PartName);` or `part!(pub PartName);` and
+/// [`Field`] parts using `part!(PartName: FieldType);` or `part!(pub PartName: FieldType);`.
+#[macro_export]
+macro_rules! part {
+ ($part:ident) => { part!(@template $part () () ($crate::AbstractPart)); };
+ (pub $part:ident) => { part!(@template $part () (pub) ($crate::AbstractPart)); };
+ ($part:ident<> : $field:ty) => { part!($part : $field); };
+ (pub $part:ident<> : $field:ty) => { part!(pub $part : $field); };
+ ($part:ident<$($lt:lifetime),*> : $field:ty) => {
+ part!(@template $part ($($lt),*) () ($crate::Field<$field>) ($field));
+ };
+ (pub $part:ident<$($lt:lifetime),*> : $field:ty) => {
+ part!(@template $part ($($lt),*) (pub) ($crate::Field<$field>) ($field));
+ };
+ ($part:ident : $field:ty) => { part!(@template $part () () ($crate::Field<$field>)); };
+ (pub $part:ident : $field:ty) => { part!(@template $part () (pub) ($crate::Field<$field>)); };
+ (@template $part:ident () ($($vis:tt)*) ($($part_type:tt)*)) => {
+ #[derive(Default)]
+ $($vis)* struct $part;
+ impl $crate::Part for $part {
+ type PartType = $($part_type)*;
+ }
+
+ impl $crate::PartSpec<$part> for $part {}
+
+ // TODO maybe constrain InnerPart
+ impl<InnerPart: $crate::Part> ::std::ops::BitOr<InnerPart> for $part {
+ type Output = $crate::Nested<$part, InnerPart>;
+
+ fn bitor(self, _rhs: InnerPart) -> Self::Output {
+ std::default::Default::default()
+ }
+ }
+ };
+ (@template $part:ident ($($lt:lifetime),*) ($($vis:tt)*) ($($part_type:tt)*) ($field:ty)) => {
+ #[derive(Default)]
+ $($vis)* struct $part<$($lt),*> {
+ phantom: ::std::marker::PhantomData<$field>,
+ }
+
+ #[allow(non_upper_case_globals)]
+ $($vis)* const $part: $part = $part { phantom: ::std::marker::PhantomData };
+
+ impl<$($lt),*> $crate::Part for $part<$($lt),*> {
+ type PartType = $($part_type)*;
+ }
+
+ part!(@spec_template $part ($($lt),*));
+
+ // TODO maybe constrain InnerPart
+ impl<$($lt),*, InnerPart: $crate::Part> ::std::ops::BitOr<InnerPart> for $part<$($lt),*> {
+ type Output = $crate::Nested<$part<$($lt),*>, InnerPart>;
+
+ fn bitor(self, _rhs: InnerPart) -> Self::Output {
+ std::default::Default::default()
+ }
+ }
+ };
+ (@spec_template $part:ident ($l:lifetime)) => {
+ impl<'a, 'b> $crate::PartSpec<$part<'a>> for $part<'b> {}
+ };
+ (@spec_template $part:ident ($l1:lifetime, $l2:lifetime)) => {
+ impl<'a1, 'a2, 'b1, 'b2> $crate::PartSpec<$part<'a1, 'a2>> for $part<'b1, 'b2> {}
+ };
+ (@spec_template $part:ident ($l1:lifetime, $l2:lifetime, $l3:lifetime)) => {
+ impl<'a1, 'a2, 'a3, 'b1, 'b2, 'b3>
+ $crate::PartSpec<$part<'a1, 'a2, 'a3>>
+ for $part<'b1, 'b2, 'b3> {}
+ };
+ (@spec_template $part:ident ($($tt:tt)*)) => {
+ // TODO avoid this limitation
+ compile_error!("parts with more than 3 lifetimes are not supported yet");
+ };
+}
+
+/// Concise syntax for partial reference types.
+///
+/// The first parameter is the reference target type, optionally preceded by a lifetime. The
+/// following parameters are the referenced parts, each optionally preceded by the keyword `mut` to
+/// indicate a mutable reference to that part. Nested parts can be specified using the pipe syntax
+/// of [`nested_part`].
+///
+/// Examples:
+/// * `partial!(Ty, PartA)` is `Const<PartA, Ref<Ty>>`
+/// * `partial!('a Ty, mut PartA)` is `Mut<PartA, Ref<'a, Ty>>`
+/// * `partial!(Ty, PartA, PartB, mut PartC)` is
+/// `Const<PartA, Const<PartB, Mut<PartC, Ref<Ty>>`
+/// * `partial!('a Ty, mut PartA | PartB)` is `Mut<Nested<PartA, PartB>, Ref<'a, Ty>>`
+#[macro_export]
+macro_rules! partial {
+ ($target_lt:lifetime $target:ty) => { $crate::Ref<$target_lt, $target> };
+ ($target_lt:lifetime $target:ty, $($parts:tt)*) => {
+ partial!(@extend $crate::Ref<$target_lt, $target>, $($parts)*)
+ };
+ ($target:ty) => { $crate::Ref<$target> };
+ ($target:ty, $($parts:tt)* ) => {
+ partial!(@extend $crate::Ref<$target>, $($parts)*)
+ };
+ (@extend $target:ty) => {$target};
+ (@extend $target:ty, ) => {$target};
+ (@extend $target:ty, mut $($part:ty)|* , $($rest:tt)*) => {
+ partial!(@extend $crate::Mut<$crate::nested_part!($($part)|*), $target>, $($rest)*)
+ };
+ (@extend $target:ty, mut $($part:ty)|*) => {
+ partial!(@extend $target, mut $($part)|*, )
+ };
+ (@extend $target:ty, $($part:ty)|* , $($rest:tt)*) => {
+ partial!(@extend $crate::Const<$crate::nested_part!($($part)|*), $target>, $($rest)*)
+ };
+ (@extend $target:ty, $($part:ty)|*) => {
+ partial!(@extend $target, $($part)|*, )
+ };
+}
+
+/// Expands `A | B | ... | Z` to `Nested<...Nested<A, B>, ..., Z>`
+///
+/// This mirrors the syntax for the expressions that can be passed to [`PartialRef`]'s part
+/// functions.
+#[macro_export]
+macro_rules! nested_part {
+ ($target:ty) => { $target };
+ ($target:ty | $part:ty) => {
+ $crate::Nested<$target , $part>
+ };
+ ($target:ty | $part:ty | $($subparts:ty)|*) => {
+ nested_part!($crate::Nested<$target , $part> | $($subparts)|*)
+ };
+}
+
+/// Helper macro for splitting a partial reference.
+///
+/// The statement `split_borrow!(target, rest = &(...) expr)` where `...` is a list of parts (same
+/// syntax as used for [`partial`]) splits the partial reference returned by expr and binds the listed
+/// parts to the identifier `target` and the remaining parts to the identifier `rest`. This is done
+/// using [`PartialRef`]'s split_borrow method.
+///
+/// As shorter version is available as `split_borrow!(target = &(...) ident)` which is identical to
+/// `split_borrow!(target, ident = &(...) ident)`. This shadows the existing partial reference with
+/// a new binding.
+#[macro_export]
+macro_rules! split_borrow {
+ ($target:ident = &($($parts:tt)*) $from:ident) => {
+ split_borrow!($target, $from = &($($parts)*) $from)
+ };
+ ($target:ident, $rest:ident = &($($parts:tt)*) $from:expr) => {
+ #[allow(unused_variables, unused_mut)]
+ let (mut $target, mut $rest) = ($from).split_borrow::<partial!(_, $($parts)*), _>();
+ };
+}