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::*;