freezie/
lib.rs

1#![warn(
2    missing_debug_implementations,
3    missing_docs,
4    rust_2018_idioms,
5    unreachable_pub,
6    non_snake_case,
7    non_upper_case_globals
8)]
9#![deny(rustdoc::broken_intra_doc_links)]
10#![allow(clippy::cognitive_complexity)]
11//! # freezie
12//!
13//! A wrapper type with no `DerefMut` impl, disallowing mutation
14//! ```compile_fail
15//! use domain_list::freeze::Freeze;
16//! let mut v = Freeze::new(vec![1, 2, 3]);
17//! v.push(1); // ERROR - cannot borrow data in dereference of ...
18//! ```
19
20use std::ops::Deref;
21
22/// A wrapper type with no `DerefMut` impl, disallowing mutation
23/// ```compile_fail
24/// use domain_list::freeze::Freeze;
25/// let mut v = Freeze::new(vec![1, 2, 3]);
26/// v.push(1); // ERROR - cannot borrow data in dereference of ...
27/// ```
28#[derive(Copy, Debug, Clone, Default, Hash, PartialEq, PartialOrd, Eq, Ord)]
29pub struct Freeze<T>(T);
30
31impl<T> Deref for Freeze<T> {
32    type Target = T;
33
34    fn deref(&self) -> &Self::Target {
35        &self.0
36    }
37}
38
39impl<T> Freeze<T> {
40    /// construct a new "frozen" type
41    pub fn new(inner: T) -> Self {
42        Self(inner)
43    }
44
45    /// unfreeze the inner value
46    pub fn defrost(self) -> T {
47        self.0
48    }
49}
50
51/// Defines how to make a type immutable
52pub trait Frozen {
53    /// `freeze` this type to make it immutable
54    fn freeze(self) -> Freeze<Self>
55    where
56        Self: Sized,
57    {
58        Freeze::new(self)
59    }
60}
61
62impl<T> Frozen for T {
63    fn freeze(self) -> Freeze<T> {
64        Freeze::new(self)
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn build_from_iter() {
74        let im = (0..10).collect::<Vec<_>>().freeze();
75        for (&x, y) in im.iter().zip(0..10) {
76            assert_eq!(x, y);
77        }
78    }
79}