guts/
lib.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
6
7//! Traits for constructing/destructuring from/into a type's internal guts.
8//!
9//! # Example
10//!
11//! ```
12//! mod state_machine {
13//!     use guts::{Guts, FromGutsUnchecked};
14//!
15//!     /// A State machine's internal state.
16//!     pub enum State {
17//!         Off,
18//!         On,
19//!     }
20//!
21//!     /// A State machine that hides its internal state.
22//!     pub struct StateMachine {
23//!         state: State,
24//!     }
25//!
26//!     impl Default for StateMachine {
27//!         /// Creates a state machine in the only allowed initial state: `Off`.
28//!         fn default() -> Self {
29//!             Self { state: State::Off }
30//!         }
31//!     }
32//!
33//!     impl Guts for StateMachine {
34//!         type Guts = State;
35//!     }
36//!
37//!     impl FromGutsUnchecked for StateMachine {
38//!         /// Creates a state machine in an arbitrary state, unsafely.
39//!         unsafe fn from_guts_unchecked(guts: Self::Guts) -> Self {
40//!             Self { state: guts }
41//!         }
42//!     }
43//! }
44//!
45//! use guts::FromGutsUnchecked;
46//! use state_machine::{State, StateMachine};
47//!
48//! // A machine can easily be safely created in its initial state:
49//! let machine = StateMachine::default();
50//!
51//! // To create a machine in a non-initial state `unsafe { … }` is required:
52//! let machine = unsafe { StateMachine::from_guts_unchecked(State::On) };
53//! ```
54
55#![cfg_attr(feature = "never_type", feature(never_type))]
56
57/// The base trait of `FromGuts` and `IntoGuts`, its more useful companions.
58pub trait HasGuts: Sized {
59    /// The type's guts.
60    type Guts;
61}
62
63/// Safely access a value's guts.
64pub trait Guts: HasGuts {
65    /// Returns a borrow of its guts.
66    fn guts(&self) -> &Self::Guts;
67}
68
69/// Safely mutably access a value's guts.
70pub trait GutsMut: Guts {
71    /// Returns a mutable borrow of its guts.
72    fn guts_mut(&mut self) -> &mut Self::Guts;
73}
74
75/// Safely destructuring values into their guts.
76pub trait IntoGuts: HasGuts {
77    /// Destructures a value into its guts.
78    fn into_guts(self) -> Self::Guts;
79}
80
81/// Safely constructing values from their guts.
82pub trait FromGuts: HasGuts {
83    /// Constructs a value from its guts.
84    fn from_guts(guts: Self::Guts) -> Self;
85}
86
87/// Safely constructing values from their guts with possible failure.
88pub trait TryFromGuts: HasGuts {
89    type Error;
90
91    /// Constructs a value from its guts, or fails.
92    fn try_from_guts(guts: Self::Guts) -> Result<Self, Self::Error>;
93}
94
95#[cfg(feature = "never_type")]
96impl<T> TryFromGuts for T
97where
98    T: FromGuts,
99{
100    type Error = !;
101
102    fn try_from_guts(guts: Self::Guts) -> Result<Self, Self::Error> {
103        Ok(Self::from_guts(guts))
104    }
105}
106
107/// Unsafely constructing values from their guts without checking invariants.
108pub trait FromGutsUnchecked: HasGuts {
109    /// Constructs a value from its guts, without checking invariants.
110    ///
111    /// # Safety
112    /// Depending on the invariants of `Self` this method may
113    /// introduce unsafety by constructing from unchecked guts.
114    unsafe fn from_guts_unchecked(guts: Self::Guts) -> Self;
115}
116
117impl<T> FromGutsUnchecked for T
118where
119    T: FromGuts,
120{
121    unsafe fn from_guts_unchecked(guts: Self::Guts) -> Self {
122        Self::from_guts(guts)
123    }
124}