freya_core/lifecycle/
readable.rs1use std::{
4 cell::Ref,
5 rc::Rc,
6};
7
8use crate::prelude::*;
9
10pub struct Readable<T: 'static> {
52 pub(crate) read_fn: Rc<dyn Fn() -> ReadableRef<T>>,
53 pub(crate) peek_fn: Rc<dyn Fn() -> ReadableRef<T>>,
54 pub(crate) equal_fn: Rc<dyn Fn(&T) -> bool>,
55}
56
57impl<T: 'static> Clone for Readable<T> {
58 fn clone(&self) -> Self {
59 Self {
60 read_fn: self.read_fn.clone(),
61 peek_fn: self.peek_fn.clone(),
62 equal_fn: self.equal_fn.clone(),
63 }
64 }
65}
66
67impl<T: 'static> PartialEq for Readable<T> {
68 fn eq(&self, other: &Self) -> bool {
69 (self.equal_fn)(&*other.peek())
70 }
71}
72
73impl<T: PartialEq> From<T> for Readable<T> {
74 fn from(value: T) -> Self {
75 Readable::from_value(value)
76 }
77}
78
79impl<T: 'static + PartialEq> Readable<T> {
80 pub fn from_value(value: T) -> Self {
82 let value = Rc::new(value);
83 Self {
84 read_fn: Rc::new({
85 let value = value.clone();
86 move || ReadableRef::Borrowed(value.clone())
87 }),
88 peek_fn: Rc::new({
89 let value = value.clone();
90 move || ReadableRef::Borrowed(value.clone())
91 }),
92 equal_fn: Rc::new(move |other| other == &*value),
93 }
94 }
95}
96impl<T: 'static> Readable<T> {
97 pub fn from_state(state: State<T>) -> Self {
99 Self {
100 read_fn: Rc::new(move || ReadableRef::Ref(state.read())),
101 peek_fn: Rc::new(move || ReadableRef::Ref(state.peek())),
102 equal_fn: Rc::new(move |_| true),
103 }
104 }
105
106 pub fn new(
108 read_fn: impl Fn() -> ReadableRef<T> + 'static,
109 peek_fn: impl Fn() -> ReadableRef<T> + 'static,
110 equal_fn: impl Fn(&T) -> bool + 'static,
111 ) -> Self {
112 Self {
113 read_fn: Rc::new(read_fn),
114 peek_fn: Rc::new(peek_fn),
115 equal_fn: Rc::new(equal_fn),
116 }
117 }
118
119 pub fn read(&self) -> ReadableRef<T> {
126 (self.read_fn)()
127 }
128
129 pub fn peek(&self) -> ReadableRef<T> {
131 (self.peek_fn)()
132 }
133
134 pub fn map<O>(
145 &self,
146 map_fn: impl Fn(&T) -> &O + 'static,
147 equal_fn: impl Fn(&O) -> bool + 'static,
148 ) -> Readable<O> {
149 let readable = self.clone();
150 let map_fn = Rc::new(map_fn);
151 Readable {
152 read_fn: Rc::new({
153 let map_fn = map_fn.clone();
154 let readable = readable.clone();
155 move || {
156 let ReadableRef::Ref(r) = readable.read() else {
157 unreachable!("Unsupported")
158 };
159
160 ReadableRef::Ref(r.map(|r| Ref::map(r, |v| (map_fn)(v))))
161 }
162 }),
163 peek_fn: Rc::new(move || {
164 let ReadableRef::Ref(r) = readable.peek() else {
165 unreachable!("Unsupported")
166 };
167
168 ReadableRef::Ref(r.map(|r| Ref::map(r, |v| (map_fn)(v))))
169 }),
170 equal_fn: Rc::new(equal_fn),
171 }
172 }
173}
174
175pub trait IntoReadable<T: 'static> {
176 fn into_readable(self) -> Readable<T>;
177}
178
179impl<T: 'static> IntoReadable<T> for State<T> {
180 fn into_readable(self) -> Readable<T> {
181 Readable::from_state(self)
182 }
183}
184
185impl<T: 'static + PartialEq> IntoReadable<T> for T {
186 fn into_readable(self) -> Readable<T> {
187 Readable::from_value(self)
188 }
189}
190
191impl<T: 'static> IntoReadable<T> for Memo<T> {
192 fn into_readable(self) -> Readable<T> {
193 Readable::from_state(self.state)
194 }
195}
196
197impl<T> From<State<T>> for Readable<T> {
198 fn from(value: State<T>) -> Self {
199 value.into_readable()
200 }
201}
202
203impl<T> From<Memo<T>> for Readable<T> {
204 fn from(value: Memo<T>) -> Self {
205 value.into_readable()
206 }
207}