partial-borrow 1.0.1

Partially borrow a struct
Documentation
// Copyright 2021 Ian Jackson and contributors
// SPDX-License-Identifier: GPL-3.0-or-later
// There is NO WARRANTY.

#![doc=include_str!("../README.md")]

#[cfg(test)] #[path="../test/test.rs"] mod test;

/// Helper trait (types that can be partially borrowed).
///
/// This is used by the [`partial!()`] macro,
/// to construct type expressions that name particular borrowing sets.
/// You probably don't want to use this trait directly.
///
/// This trait will be derived.  You probably don't want to implement it.
#[allow(non_camel_case_types)]
pub trait PartialBorrow {
  /** `Self` as a `Partial`, but with all fields `Mut` */ type All_Mut;
  /** `Self` as a `Partial`, with all fields `Const` */   type All_Const;
  /** `Self` as a `Partial`, with all fields `No` */      type All_No;

  /// Field index lookup type: field names are those of the original struct.
  type Fields;
  /// Field index lookup table: values are usize indices, the field numbers.
  const FIELDS: Self::Fields;
}

/// Methods (**`downgrade`**) for downgrading (partial) references.
///
/// Reborrows a partial or complete (ordinary) struct borrow as a
/// partial borrow, possibly imposing further restrictions (as defined
/// by the return type `R`).
///
/// Note that these associated functions are not methods, to avoid
/// interfering with any methods on `Self.`
/// If you want a method, use the `AsRef` or `AsMut` implementations,
/// which are also provided whenever this trait is.
///
/// This trait will be derived.  You probably don't want to implement it.
pub trait Downgrade<R> {
  fn downgrade    (input: &Self    ) -> &    R;
  fn downgrade_mut(input: &mut Self) -> &mut R;
}

/// Methods (**`split_off`**) for splitting off (partial) references.
///
/// Reborrows `Self`, giving `R` and whatever is still accessible
/// after `R` has been borrowed.
///
/// Note that these associated functions are not methods, to avoid
/// interfering with any methods on `Self.`
/// Unlike `SplitInto`, precisely determines the remaining type, which
/// may mean it can be inferred.
///
/// This trait will be derived.  You probably don't want to implement it.
pub trait SplitOff<R> {
  type Remaining;
  fn split_off    (input: &    Self) -> (&    R, &    Self::Remaining);
  fn split_off_mut(input: &mut Self) -> (&mut R, &mut Self::Remaining);
}

/// Methods (**`split_into`**) for splitting (partial) references.
///
/// Reborrows `Self`, giving `R` and `S`, if that is allowed:
/// ie, if `R` and `S` borrowings are compatible, and no more
/// permissive than `Self`.
///
/// Note that these associated functions are not methods, to avoid
/// interfering with any methods on `Self.`
/// There is always an equivalent `From` (and therefore `Into`)
/// implementation.
///
/// This trait will be derived.  You probably don't want to implement it.
pub trait SplitInto<R,S> {
  fn split_into    (input: &    Self) -> (&    R, &    S);
  fn split_into_mut(input: &mut Self) -> (&mut R, &mut S);
}

pub use partial_borrow_macros::PartialBorrow;

pub use partial_borrow_macros::partial;

/// **`use *` for convenient use of this crate** in your module.
pub mod prelude {
  pub use crate as partial_borrow;
  pub use super::{PartialBorrow, partial};
}

/// Field borrowing permissions.
///
/// # Types
///
/// [`Mut`](perms::Mut),
/// [`Const`](perms::Const) and
/// [`No`](perms::No)
/// are unit structs whose type indicates the permission
/// (borrowing status) of a field.
///
/// They just show up in error messages and it is not normally
/// necessary to name them directly in user code.
/// If specifying field permissions as a list, or in other unusual
/// situations, you may need to refer to them explicitly.
///
/// # Traits
///
/// The traits are all helper traits used for type judo by code
/// generated by the derive, often including unsafe code.
///
/// You should not need to implement these.
///
/// It is not sound to add user implementations of the unsafe traits.
pub mod perms {
  /// Mutable access (permission marker unit struct)
  #[derive(Debug)]            pub struct Mut;
  /// Immutable access (permission marker unit struct)
  #[derive(Debug,Clone,Copy)] pub struct Const;
  /// No access (permission marker unit struct)
  #[derive(Debug,Clone,Copy)] pub struct No;

  /// Permissions that allow immutable access.
  pub unsafe trait IsRef { }
  unsafe impl IsRef for Const { }
  unsafe impl IsRef for Mut   { }

  /// Permissions that allow mutable access.
  pub unsafe trait IsMut: IsRef { }
  unsafe impl IsMut for Mut { }

  /// Permissions that might or might not allow access.  (Ie, all of them.)
  pub unsafe trait IsRefOrNot      { /// Allows immutable access ?
                                     const REF: Option<Const>; }
  unsafe impl IsRefOrNot for Mut   { const REF: Option<Const> = Some(Const); }
  unsafe impl IsRefOrNot for Const { const REF: Option<Const> = Some(Const); }
  unsafe impl IsRefOrNot for No    { const REF: Option<Const> = None; }

  /// Permissions that are no greater than `P`
  pub unsafe trait IsDowngradeFrom<P>          { type Remaining: IsRefOrNot; }
  unsafe impl IsDowngradeFrom<Mut>   for Mut   { type Remaining = No;    }
  unsafe impl IsDowngradeFrom<Mut>   for Const { type Remaining = Const; }
  unsafe impl IsDowngradeFrom<Mut>   for No    { type Remaining = Mut;   }
  //
  unsafe impl IsDowngradeFrom<Const> for Const { type Remaining = Const; }
  unsafe impl IsDowngradeFrom<Const> for No    { type Remaining = Const; }
  //
  unsafe impl IsDowngradeFrom<No>    for No    { type Remaining = No;    }

  /// Permissions that could be reborrowed, simulaneously, as both `R` and `S`.
  pub unsafe trait CanSplitInto<R,S> { }
  unsafe impl CanSplitInto<Mut  ,No   > for Mut { }
  unsafe impl CanSplitInto<No   ,No   > for Mut { }
  //
  unsafe impl CanSplitInto<Const,Const> for Mut { }
  unsafe impl CanSplitInto<Const,No   > for Mut { }
  unsafe impl CanSplitInto<No   ,Mut  > for Mut { }
  unsafe impl CanSplitInto<No   ,Const> for Mut { }
  //
  unsafe impl CanSplitInto<Const,Const> for Const { }
  unsafe impl CanSplitInto<Const,No   > for Const { }
  unsafe impl CanSplitInto<No,   Const> for Const { }
  unsafe impl CanSplitInto<No,   No   > for Const { }
  //
  unsafe impl CanSplitInto<No,No> for No { }

  /// Adjustable partial type:
  /// `Self` but with field #`FI` accessible with permission `P`.
  ///
  /// Used by the [`partial!()`](crate::partial) macro.
  pub trait Adjust<P, const FI: usize>  { type Adjusted; }
}

/// Helper imports for the use of macro-generated code.
///
/// **Don't import this**; it would needlessly pollute your namespace.
/// `use partial_borrow::prelude::*` instead.
pub mod imports {
  pub use core::option::Option::Some;

  pub use std::convert::{AsMut, AsRef};
  pub use std::fmt::{self, Debug, Formatter};
  pub use std::marker::{PhantomData, Sized};
  pub use std::mem::transmute;
  pub use std::ops::{Deref, DerefMut};

  pub use memoffset::offset_of;

  pub use super::*;
  pub use perms::*;
  pub use crate as partial_borrow;
}

pub use prelude::*;