use core::fmt;
use core::ops::{Deref, DerefMut};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Unrestricted<T> {
value: T,
}
pub type Liber<T> = Unrestricted<T>;
impl<T> Unrestricted<T> {
#[inline]
pub const fn new(value: T) -> Self {
Unrestricted { value }
}
#[inline]
pub fn extract(self) -> T {
self.value
}
#[inline]
pub fn inner_ref(&self) -> &T {
&self.value
}
#[inline]
pub fn inner_mut(&mut self) -> &mut T {
&mut self.value
}
#[inline]
pub fn fmap<B, F>(self, f: F) -> Unrestricted<B>
where
F: FnOnce(T) -> B,
{
Unrestricted::new(f(self.value))
}
#[inline]
pub fn flat_map<B, F>(self, f: F) -> Unrestricted<B>
where
F: FnOnce(T) -> Unrestricted<B>,
{
f(self.value)
}
#[inline]
pub fn duplicate(&self) -> (Unrestricted<T>, Unrestricted<T>)
where
T: Clone,
{
(
Unrestricted::new(self.value.clone()),
Unrestricted::new(self.value.clone()),
)
}
#[inline]
pub fn zip<B>(self, other: Unrestricted<B>) -> Unrestricted<(T, B)> {
Unrestricted::new((self.value, other.value))
}
}
impl<T: Clone> Unrestricted<T> {
#[inline]
pub fn use_value(&self) -> T {
self.value.clone()
}
}
impl<T> From<T> for Unrestricted<T> {
fn from(value: T) -> Self {
Unrestricted::new(value)
}
}
impl<T> Deref for Unrestricted<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<T> DerefMut for Unrestricted<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.value
}
}
impl<T: fmt::Debug> fmt::Debug for Unrestricted<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Unrestricted")
.field("value", &self.value)
.finish()
}
}
impl<T: fmt::Display> fmt::Display for Unrestricted<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Unrestricted({})", self.value)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_and_extract() {
let x = Unrestricted::new(42);
assert_eq!(x.extract(), 42);
}
#[test]
fn test_fmap() {
let x = Unrestricted::new(5);
let y = x.fmap(|n| n * 2);
assert_eq!(y.extract(), 10);
}
#[test]
fn test_flat_map() {
let x = Unrestricted::new(5);
let y = x.flat_map(|n| Unrestricted::new(n + 10));
assert_eq!(y.extract(), 15);
}
#[test]
fn test_duplicate() {
let x = Unrestricted::new(42);
let (a, b) = x.duplicate();
assert_eq!(a.extract(), 42);
assert_eq!(b.extract(), 42);
}
#[test]
fn test_use_value() {
let x = Unrestricted::new(42);
assert_eq!(x.use_value(), 42);
assert_eq!(x.use_value(), 42); }
#[test]
fn test_zip() {
let x = Unrestricted::new(1);
let y = Unrestricted::new("hello");
let zipped = x.zip(y);
assert_eq!(zipped.extract(), (1, "hello"));
}
#[test]
fn test_deref() {
let x = Unrestricted::new(42);
assert_eq!(*x, 42);
}
#[test]
fn test_deref_mut() {
let mut x = Unrestricted::new(42);
*x = 100;
assert_eq!(*x, 100);
}
#[test]
fn test_clone() {
let x = Unrestricted::new(42);
let y = x;
assert_eq!(x.extract(), y.extract());
}
#[test]
fn test_liber_alias() {
let x: Liber<i32> = Liber::new(42);
assert_eq!(x.extract(), 42);
}
}