use std::marker::PhantomData;
use std::ops;
use std::sync::Arc;
use crate::Data;
pub trait Lens<T: ?Sized, U: ?Sized> {
fn with<V, F: FnOnce(&U) -> V>(&self, data: &T, f: F) -> V;
fn with_mut<V, F: FnOnce(&mut U) -> V>(&self, data: &mut T, f: F) -> V;
}
pub trait LensExt<A: ?Sized, B: ?Sized>: Lens<A, B> {
fn get(&self, data: &A) -> B
where
B: Clone,
{
self.with(data, |x| x.clone())
}
fn put(&self, data: &mut A, value: B)
where
B: Sized,
{
self.with_mut(data, |x| *x = value);
}
fn then<Other, C>(self, other: Other) -> Then<Self, Other, B>
where
Other: Lens<B, C> + Sized,
C: ?Sized,
Self: Sized,
{
Then::new(self, other)
}
fn map<Get, Put, C>(self, get: Get, put: Put) -> Then<Self, Map<Get, Put>, B>
where
Get: Fn(&B) -> C,
Put: Fn(&mut B, C),
Self: Sized,
{
self.then(Map::new(get, put))
}
fn deref(self) -> Then<Self, Deref, B>
where
B: ops::Deref + ops::DerefMut,
Self: Sized,
{
self.then(Deref)
}
#[allow(clippy::wrong_self_convention)]
fn as_ref<T: ?Sized>(self) -> Then<Self, Ref, B>
where
B: AsRef<T> + AsMut<T>,
Self: Sized,
{
self.then(Ref)
}
fn index<I>(self, index: I) -> Then<Self, Index<I>, B>
where
I: Clone,
B: ops::Index<I> + ops::IndexMut<I>,
Self: Sized,
{
self.then(Index::new(index))
}
fn in_arc(self) -> InArc<Self>
where
A: Clone,
B: Data,
Self: Sized,
{
InArc::new(self)
}
fn not(self) -> Then<Self, Not, B>
where
Self: Sized,
B: Sized + Into<bool> + Copy,
bool: Into<B>,
{
self.then(Not)
}
}
impl<A: ?Sized, B: ?Sized, T: Lens<A, B>> LensExt<A, B> for T {}
pub struct Field<Get, GetMut> {
get: Get,
get_mut: GetMut,
}
impl<Get, GetMut> Field<Get, GetMut> {
pub fn new<T: ?Sized, U: ?Sized>(get: Get, get_mut: GetMut) -> Self
where
Get: Fn(&T) -> &U,
GetMut: Fn(&mut T) -> &mut U,
{
Self { get, get_mut }
}
}
impl<T, U, Get, GetMut> Lens<T, U> for Field<Get, GetMut>
where
T: ?Sized,
U: ?Sized,
Get: Fn(&T) -> &U,
GetMut: Fn(&mut T) -> &mut U,
{
fn with<V, F: FnOnce(&U) -> V>(&self, data: &T, f: F) -> V {
f((self.get)(data))
}
fn with_mut<V, F: FnOnce(&mut U) -> V>(&self, data: &mut T, f: F) -> V {
f((self.get_mut)(data))
}
}
#[macro_export]
macro_rules! lens {
($ty:ty, [$index:expr]) => {
$crate::lens::Field::new::<$ty, _>(move |x| &x[$index], move |x| &mut x[$index])
};
($ty:ty, $($field:tt)*) => {
$crate::lens::Field::new::<$ty, _>(move |x| &x.$($field)*, move |x| &mut x.$($field)*)
};
}
#[derive(Debug, Copy)]
pub struct Then<T, U, B: ?Sized> {
left: T,
right: U,
_marker: PhantomData<B>,
}
impl<T, U, B: ?Sized> Then<T, U, B> {
pub fn new<A: ?Sized, C: ?Sized>(left: T, right: U) -> Self
where
T: Lens<A, B>,
U: Lens<B, C>,
{
Self {
left,
right,
_marker: PhantomData,
}
}
}
impl<T, U, A, B, C> Lens<A, C> for Then<T, U, B>
where
A: ?Sized,
B: ?Sized,
C: ?Sized,
T: Lens<A, B>,
U: Lens<B, C>,
{
fn with<V, F: FnOnce(&C) -> V>(&self, data: &A, f: F) -> V {
self.left.with(data, |b| self.right.with(b, f))
}
fn with_mut<V, F: FnOnce(&mut C) -> V>(&self, data: &mut A, f: F) -> V {
self.left.with_mut(data, |b| self.right.with_mut(b, f))
}
}
impl<T: Clone, U: Clone, B> Clone for Then<T, U, B> {
fn clone(&self) -> Self {
Self {
left: self.left.clone(),
right: self.right.clone(),
_marker: PhantomData,
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct Map<Get, Put> {
get: Get,
put: Put,
}
impl<Get, Put> Map<Get, Put> {
pub fn new<A: ?Sized, B>(get: Get, put: Put) -> Self
where
Get: Fn(&A) -> B,
Put: Fn(&mut A, B),
{
Self { get, put }
}
}
impl<A: ?Sized, B, Get, Put> Lens<A, B> for Map<Get, Put>
where
Get: Fn(&A) -> B,
Put: Fn(&mut A, B),
{
fn with<V, F: FnOnce(&B) -> V>(&self, data: &A, f: F) -> V {
f(&(self.get)(data))
}
fn with_mut<V, F: FnOnce(&mut B) -> V>(&self, data: &mut A, f: F) -> V {
let mut temp = (self.get)(data);
let x = f(&mut temp);
(self.put)(data, temp);
x
}
}
#[derive(Debug, Copy, Clone)]
pub struct Deref;
impl<T: ?Sized> Lens<T, T::Target> for Deref
where
T: ops::Deref + ops::DerefMut,
{
fn with<V, F: FnOnce(&T::Target) -> V>(&self, data: &T, f: F) -> V {
f(data.deref())
}
fn with_mut<V, F: FnOnce(&mut T::Target) -> V>(&self, data: &mut T, f: F) -> V {
f(data.deref_mut())
}
}
#[derive(Debug, Copy, Clone)]
pub struct Ref;
impl<T: ?Sized, U: ?Sized> Lens<T, U> for Ref
where
T: AsRef<U> + AsMut<U>,
{
fn with<V, F: FnOnce(&U) -> V>(&self, data: &T, f: F) -> V {
f(data.as_ref())
}
fn with_mut<V, F: FnOnce(&mut U) -> V>(&self, data: &mut T, f: F) -> V {
f(data.as_mut())
}
}
#[derive(Debug, Copy, Clone)]
pub struct Index<I> {
index: I,
}
impl<I> Index<I> {
pub fn new(index: I) -> Self {
Self { index }
}
}
impl<T, I> Lens<T, T::Output> for Index<I>
where
T: ?Sized + ops::Index<I> + ops::IndexMut<I>,
I: Clone,
{
fn with<V, F: FnOnce(&T::Output) -> V>(&self, data: &T, f: F) -> V {
f(&data[self.index.clone()])
}
fn with_mut<V, F: FnOnce(&mut T::Output) -> V>(&self, data: &mut T, f: F) -> V {
f(&mut data[self.index.clone()])
}
}
#[derive(Debug, Copy, Clone)]
pub struct Identity;
impl<A: ?Sized> Lens<A, A> for Identity {
fn with<V, F: FnOnce(&A) -> V>(&self, data: &A, f: F) -> V {
f(data)
}
fn with_mut<V, F: FnOnce(&mut A) -> V>(&self, data: &mut A, f: F) -> V {
f(data)
}
}
#[derive(Debug, Copy, Clone)]
pub struct InArc<L> {
inner: L,
}
impl<L> InArc<L> {
pub fn new<A, B>(inner: L) -> Self
where
A: Clone,
B: Data,
L: Lens<A, B>,
{
Self { inner }
}
}
impl<A, B, L> Lens<Arc<A>, B> for InArc<L>
where
A: Clone,
B: Data,
L: Lens<A, B>,
{
fn with<V, F: FnOnce(&B) -> V>(&self, data: &Arc<A>, f: F) -> V {
self.inner.with(data, f)
}
fn with_mut<V, F: FnOnce(&mut B) -> V>(&self, data: &mut Arc<A>, f: F) -> V {
let mut temp = self.inner.with(data, |x| x.clone());
let v = f(&mut temp);
if self.inner.with(data, |x| !x.same(&temp)) {
self.inner.with_mut(Arc::make_mut(data), |x| *x = temp);
}
v
}
}
#[derive(Debug, Default, Copy, Clone)]
pub struct Unit;
impl<T> Lens<T, ()> for Unit {
fn with<V, F: FnOnce(&()) -> V>(&self, _data: &T, f: F) -> V {
f(&())
}
fn with_mut<V, F: FnOnce(&mut ()) -> V>(&self, _data: &mut T, f: F) -> V {
f(&mut ())
}
}
#[derive(Debug, Copy, Clone)]
pub struct Not;
impl<T> Lens<T, bool> for Not
where
T: Into<bool> + Copy,
bool: Into<T>,
{
fn with<V, F: FnOnce(&bool) -> V>(&self, data: &T, f: F) -> V {
let tmp = !<T as Into<bool>>::into(*data);
f(&tmp)
}
fn with_mut<V, F: FnOnce(&mut bool) -> V>(&self, data: &mut T, f: F) -> V {
let mut tmp = !<T as Into<bool>>::into(*data);
let out = f(&mut tmp);
*data = (!tmp).into();
out
}
}
#[derive(Debug, Copy, Clone)]
pub struct Constant<T>(pub T);
impl<A, B: Clone> Lens<A, B> for Constant<B> {
fn with<V, F: FnOnce(&B) -> V>(&self, _: &A, f: F) -> V {
f(&self.0)
}
fn with_mut<V, F: FnOnce(&mut B) -> V>(&self, _: &mut A, f: F) -> V {
let mut tmp = self.0.clone();
f(&mut tmp)
}
}
macro_rules! impl_lens_for_tuple {
($(($Lens:ident, $B:ident, $i:tt)),*) => {
#[allow(non_snake_case)]
impl<A, $($Lens,)* $($B,)*> Lens<A, ($($B,)*)> for ($($Lens,)*)
where
$($B: Clone,)*
$($Lens: Lens<A, $B>,)*
{
fn with<V, F: FnOnce(&($($B,)*)) -> V>(&self, data: &A, f: F) -> V {
$(let $B = self.$i.with(data, |v| v.clone());)*
let tuple = ($($B,)*);
f(&tuple)
}
fn with_mut<V, F: FnOnce(&mut ($($B,)*)) -> V>(&self, data: &mut A, f: F) -> V {
$(let $B = self.$i.with(data, |v| v.clone());)*
let mut tuple = ($($B,)*);
let out = f(&mut tuple);
let ($($B,)*) = tuple;
$(self.$i.with_mut(data, |v| *v = $B);)*
out
}
}
};
}
impl_lens_for_tuple!((L0, L0B, 0), (L1, L1B, 1));
impl_lens_for_tuple!((L0, L0B, 0), (L1, L1B, 1), (L2, L2B, 2));
impl_lens_for_tuple!((L0, L0B, 0), (L1, L1B, 1), (L2, L2B, 2), (L3, L3B, 3));
impl_lens_for_tuple!(
(L0, L0B, 0),
(L1, L1B, 1),
(L2, L2B, 2),
(L3, L3B, 3),
(L4, L4B, 4)
);
impl_lens_for_tuple!(
(L0, L0B, 0),
(L1, L1B, 1),
(L2, L2B, 2),
(L3, L3B, 3),
(L4, L4B, 4),
(L5, L5B, 5)
);
impl_lens_for_tuple!(
(L0, L0B, 0),
(L1, L1B, 1),
(L2, L2B, 2),
(L3, L3B, 3),
(L4, L4B, 4),
(L5, L5B, 5),
(L6, L6B, 6)
);
impl_lens_for_tuple!(
(L0, L0B, 0),
(L1, L1B, 1),
(L2, L2B, 2),
(L3, L3B, 3),
(L4, L4B, 4),
(L5, L5B, 5),
(L6, L6B, 6),
(L7, L7B, 7)
);