partial_borrow/lib.rs
1// Copyright 2021 Ian Jackson and contributors
2// SPDX-License-Identifier: GPL-3.0-or-later
3// There is NO WARRANTY.
4
5#![doc=include_str!("../README.md")]
6
7#[cfg(test)] #[path="../test/test.rs"] mod test;
8
9/// Helper trait (types that can be partially borrowed).
10///
11/// This is used by the [`partial!()`] macro,
12/// to construct type expressions that name particular borrowing sets.
13/// You probably don't want to use this trait directly.
14///
15/// This trait will be derived. You probably don't want to implement it.
16#[allow(non_camel_case_types)]
17pub trait PartialBorrow {
18 /** `Self` as a `Partial`, but with all fields `Mut` */ type All_Mut;
19 /** `Self` as a `Partial`, with all fields `Const` */ type All_Const;
20 /** `Self` as a `Partial`, with all fields `No` */ type All_No;
21
22 /// Field index lookup type: field names are those of the original struct.
23 type Fields;
24 /// Field index lookup table: values are usize indices, the field numbers.
25 const FIELDS: Self::Fields;
26}
27
28/// Methods (**`downgrade`**) for downgrading (partial) references.
29///
30/// Reborrows a partial or complete (ordinary) struct borrow as a
31/// partial borrow, possibly imposing further restrictions (as defined
32/// by the return type `R`).
33///
34/// Note that these associated functions are not methods, to avoid
35/// interfering with any methods on `Self.`
36/// If you want a method, use the `AsRef` or `AsMut` implementations,
37/// which are also provided whenever this trait is.
38///
39/// This trait will be derived. You probably don't want to implement it.
40pub trait Downgrade<R> {
41 fn downgrade (input: &Self ) -> & R;
42 fn downgrade_mut(input: &mut Self) -> &mut R;
43}
44
45/// Methods (**`split_off`**) for splitting off (partial) references.
46///
47/// Reborrows `Self`, giving `R` and whatever is still accessible
48/// after `R` has been borrowed.
49///
50/// Note that these associated functions are not methods, to avoid
51/// interfering with any methods on `Self.`
52/// Unlike `SplitInto`, precisely determines the remaining type, which
53/// may mean it can be inferred.
54///
55/// This trait will be derived. You probably don't want to implement it.
56pub trait SplitOff<R> {
57 type Remaining;
58 fn split_off (input: & Self) -> (& R, & Self::Remaining);
59 fn split_off_mut(input: &mut Self) -> (&mut R, &mut Self::Remaining);
60}
61
62/// Methods (**`split_into`**) for splitting (partial) references.
63///
64/// Reborrows `Self`, giving `R` and `S`, if that is allowed:
65/// ie, if `R` and `S` borrowings are compatible, and no more
66/// permissive than `Self`.
67///
68/// Note that these associated functions are not methods, to avoid
69/// interfering with any methods on `Self.`
70/// There is always an equivalent `From` (and therefore `Into`)
71/// implementation.
72///
73/// This trait will be derived. You probably don't want to implement it.
74pub trait SplitInto<R,S> {
75 fn split_into (input: & Self) -> (& R, & S);
76 fn split_into_mut(input: &mut Self) -> (&mut R, &mut S);
77}
78
79pub use partial_borrow_macros::PartialBorrow;
80
81pub use partial_borrow_macros::partial;
82
83/// **`use *` for convenient use of this crate** in your module.
84pub mod prelude {
85 pub use crate as partial_borrow;
86 pub use super::{PartialBorrow, partial};
87}
88
89/// Field borrowing permissions.
90///
91/// # Types
92///
93/// [`Mut`](perms::Mut),
94/// [`Const`](perms::Const) and
95/// [`No`](perms::No)
96/// are unit structs whose type indicates the permission
97/// (borrowing status) of a field.
98///
99/// They just show up in error messages and it is not normally
100/// necessary to name them directly in user code.
101/// If specifying field permissions as a list, or in other unusual
102/// situations, you may need to refer to them explicitly.
103///
104/// # Traits
105///
106/// The traits are all helper traits used for type judo by code
107/// generated by the derive, often including unsafe code.
108///
109/// You should not need to implement these.
110///
111/// It is not sound to add user implementations of the unsafe traits.
112pub mod perms {
113 /// Mutable access (permission marker unit struct)
114 #[derive(Debug)] pub struct Mut;
115 /// Immutable access (permission marker unit struct)
116 #[derive(Debug,Clone,Copy)] pub struct Const;
117 /// No access (permission marker unit struct)
118 #[derive(Debug,Clone,Copy)] pub struct No;
119
120 /// Permissions that allow immutable access.
121 pub unsafe trait IsRef { }
122 unsafe impl IsRef for Const { }
123 unsafe impl IsRef for Mut { }
124
125 /// Permissions that allow mutable access.
126 pub unsafe trait IsMut: IsRef { }
127 unsafe impl IsMut for Mut { }
128
129 /// Permissions that might or might not allow access. (Ie, all of them.)
130 pub unsafe trait IsRefOrNot { /// Allows immutable access ?
131 const REF: Option<Const>; }
132 unsafe impl IsRefOrNot for Mut { const REF: Option<Const> = Some(Const); }
133 unsafe impl IsRefOrNot for Const { const REF: Option<Const> = Some(Const); }
134 unsafe impl IsRefOrNot for No { const REF: Option<Const> = None; }
135
136 /// Permissions that are no greater than `P`
137 pub unsafe trait IsDowngradeFrom<P> { type Remaining: IsRefOrNot; }
138 unsafe impl IsDowngradeFrom<Mut> for Mut { type Remaining = No; }
139 unsafe impl IsDowngradeFrom<Mut> for Const { type Remaining = Const; }
140 unsafe impl IsDowngradeFrom<Mut> for No { type Remaining = Mut; }
141 //
142 unsafe impl IsDowngradeFrom<Const> for Const { type Remaining = Const; }
143 unsafe impl IsDowngradeFrom<Const> for No { type Remaining = Const; }
144 //
145 unsafe impl IsDowngradeFrom<No> for No { type Remaining = No; }
146
147 /// Permissions that could be reborrowed, simulaneously, as both `R` and `S`.
148 pub unsafe trait CanSplitInto<R,S> { }
149 unsafe impl CanSplitInto<Mut ,No > for Mut { }
150 unsafe impl CanSplitInto<No ,No > for Mut { }
151 //
152 unsafe impl CanSplitInto<Const,Const> for Mut { }
153 unsafe impl CanSplitInto<Const,No > for Mut { }
154 unsafe impl CanSplitInto<No ,Mut > for Mut { }
155 unsafe impl CanSplitInto<No ,Const> for Mut { }
156 //
157 unsafe impl CanSplitInto<Const,Const> for Const { }
158 unsafe impl CanSplitInto<Const,No > for Const { }
159 unsafe impl CanSplitInto<No, Const> for Const { }
160 unsafe impl CanSplitInto<No, No > for Const { }
161 //
162 unsafe impl CanSplitInto<No,No> for No { }
163
164 /// Adjustable partial type:
165 /// `Self` but with field #`FI` accessible with permission `P`.
166 ///
167 /// Used by the [`partial!()`](crate::partial) macro.
168 pub trait Adjust<P, const FI: usize> { type Adjusted; }
169}
170
171/// Helper imports for the use of macro-generated code.
172///
173/// **Don't import this**; it would needlessly pollute your namespace.
174/// `use partial_borrow::prelude::*` instead.
175pub mod imports {
176 pub use core::option::Option::Some;
177
178 pub use std::convert::{AsMut, AsRef};
179 pub use std::fmt::{self, Debug, Formatter};
180 pub use std::marker::{PhantomData, Sized};
181 pub use std::mem::transmute;
182 pub use std::ops::{Deref, DerefMut};
183
184 pub use memoffset::offset_of;
185
186 pub use super::*;
187 pub use perms::*;
188 pub use crate as partial_borrow;
189}
190
191pub use prelude::*;