object_rainbow_point/
lib.rs

1use std::{
2    any::Any,
3    marker::PhantomData,
4    ops::{Deref, DerefMut},
5    sync::Arc,
6};
7
8use futures_util::{TryFutureExt, future::ready};
9use object_rainbow::{
10    Address, ByteNode, Equivalent, Error, ExtraFor, FailFuture, Fetch, FetchBytes, FullHash, Hash,
11    InlineOutput, ListHashes, MaybeHasNiche, Node, ObjectMarker, OptionalHash, Output, Parse,
12    ParseAsInline, ParseInline, PointInput, PointVisitor, Resolve, Singular, Size, Tagged, Tags,
13    ToOutput, Topological, Traversible,
14};
15
16#[cfg(feature = "serde")]
17mod point_deserialize;
18#[cfg(feature = "point-serialize")]
19mod point_serialize;
20
21#[derive(Clone, ParseAsInline)]
22struct Extras<Extra>(Extra);
23
24impl<Extra> Deref for Extras<Extra> {
25    type Target = Extra;
26
27    fn deref(&self) -> &Self::Target {
28        &self.0
29    }
30}
31
32impl<Extra> ToOutput for Extras<Extra> {
33    fn to_output(&self, _: &mut dyn Output) {}
34}
35
36impl<Extra> InlineOutput for Extras<Extra> {}
37
38impl<I: PointInput> ParseInline<I> for Extras<I::Extra> {
39    fn parse_inline(input: &mut I) -> object_rainbow::Result<Self> {
40        Ok(Self(input.extra().clone()))
41    }
42}
43
44impl<Extra> Tagged for Extras<Extra> {}
45impl<Extra> ListHashes for Extras<Extra> {}
46impl<Extra> Topological for Extras<Extra> {}
47
48#[derive(Clone)]
49struct ByAddressInner {
50    address: Address,
51    resolve: Arc<dyn Resolve>,
52}
53
54impl FetchBytes for ByAddressInner {
55    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
56        self.resolve.resolve(self.address)
57    }
58
59    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
60        self.resolve.resolve_data(self.address)
61    }
62
63    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
64        self.resolve.try_resolve_local(self.address)
65    }
66}
67
68impl Singular for ByAddressInner {
69    fn hash(&self) -> Hash {
70        self.address.hash
71    }
72}
73
74struct ByAddress<T, Extra> {
75    inner: ByAddressInner,
76    extra: Extra,
77    _object: PhantomData<fn() -> T>,
78}
79
80impl<T, Extra> ByAddress<T, Extra> {
81    fn from_inner(inner: ByAddressInner, extra: Extra) -> Self {
82        Self {
83            inner,
84            extra,
85            _object: PhantomData,
86        }
87    }
88}
89
90impl<T, Extra> FetchBytes for ByAddress<T, Extra> {
91    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
92        self.inner.fetch_bytes()
93    }
94
95    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
96        self.inner.fetch_data()
97    }
98
99    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
100        self.inner.fetch_bytes_local()
101    }
102
103    fn as_inner(&self) -> Option<&dyn Any> {
104        Some(&self.inner)
105    }
106}
107
108impl<T, Extra: Send + Sync> Singular for ByAddress<T, Extra> {
109    fn hash(&self) -> Hash {
110        self.inner.hash()
111    }
112}
113
114impl<T: FullHash, Extra: Send + Sync + ExtraFor<T>> Fetch for ByAddress<T, Extra> {
115    type T = T;
116
117    fn fetch_full(&'_ self) -> FailFuture<'_, Node<Self::T>> {
118        Box::pin(async {
119            let (data, resolve) = self.fetch_bytes().await?;
120            let object = self.extra.parse(&data, &resolve)?;
121            if self.inner.address.hash != object.full_hash() {
122                Err(Error::FullHashMismatch)
123            } else {
124                Ok((object, resolve))
125            }
126        })
127    }
128
129    fn fetch(&'_ self) -> FailFuture<'_, Self::T> {
130        Box::pin(async {
131            let (data, resolve) = self.fetch_bytes().await?;
132            let object = self.extra.parse(&data, &resolve)?;
133            if self.inner.address.hash != object.full_hash() {
134                Err(Error::FullHashMismatch)
135            } else {
136                Ok(object)
137            }
138        })
139    }
140
141    fn try_fetch_local(&self) -> object_rainbow::Result<Option<Node<Self::T>>> {
142        let Some((data, resolve)) = self.fetch_bytes_local()? else {
143            return Ok(None);
144        };
145        let object = self.extra.parse(&data, &resolve)?;
146        if self.inner.address.hash != object.full_hash() {
147            Err(Error::FullHashMismatch)
148        } else {
149            Ok(Some((object, resolve)))
150        }
151    }
152}
153
154trait FromInner {
155    type Inner: 'static + Clone;
156    type Extra: 'static + Clone;
157
158    fn from_inner(inner: Self::Inner, extra: Self::Extra) -> Self;
159}
160
161trait InnerCast: FetchBytes {
162    fn inner_cast<T: FromInner>(&self, extra: &T::Extra) -> Option<T> {
163        self.as_inner()?
164            .downcast_ref()
165            .cloned()
166            .map(|inner| T::from_inner(inner, extra.clone()))
167    }
168}
169
170impl<T: ?Sized + FetchBytes> InnerCast for T {}
171
172pub trait ExtractResolve: FetchBytes {
173    fn extract_resolve<R: Any>(&self) -> Option<(&Address, &R)> {
174        let ByAddressInner { address, resolve } =
175            self.as_inner()?.downcast_ref::<ByAddressInner>()?;
176        let resolve = resolve.as_ref().any_ref().downcast_ref::<R>()?;
177        Some((address, resolve))
178    }
179}
180
181impl<T: ?Sized + FetchBytes> ExtractResolve for T {}
182
183#[derive(Clone, ParseAsInline)]
184pub struct RawPointInner {
185    hash: Hash,
186    fetch: Arc<dyn Send + Sync + FetchBytes>,
187}
188
189impl RawPointInner {
190    pub fn cast<T, Extra: 'static + Clone>(self, extra: Extra) -> RawPoint<T, Extra> {
191        RawPoint::from_inner(self, extra)
192    }
193
194    pub fn from_address(address: Address, resolve: Arc<dyn Resolve>) -> Self {
195        Self {
196            hash: address.hash,
197            fetch: Arc::new(ByAddressInner { address, resolve }),
198        }
199    }
200
201    pub fn from_singular(singular: impl 'static + Singular) -> Self {
202        Self {
203            hash: singular.hash(),
204            fetch: Arc::new(singular),
205        }
206    }
207}
208
209impl ToOutput for RawPointInner {
210    fn to_output(&self, output: &mut dyn Output) {
211        self.hash.to_output(output);
212    }
213}
214
215impl InlineOutput for RawPointInner {}
216
217impl<I: PointInput> ParseInline<I> for RawPointInner {
218    fn parse_inline(input: &mut I) -> object_rainbow::Result<Self> {
219        Ok(Self::from_address(input.parse_inline()?, input.resolve()))
220    }
221}
222
223impl Tagged for RawPointInner {}
224
225impl Singular for RawPointInner {
226    fn hash(&self) -> Hash {
227        self.hash
228    }
229}
230
231impl ListHashes for RawPointInner {
232    fn list_hashes(&self, f: &mut impl FnMut(Hash)) {
233        f(self.hash)
234    }
235
236    fn point_count(&self) -> usize {
237        1
238    }
239}
240
241impl FetchBytes for RawPointInner {
242    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
243        self.fetch.fetch_bytes()
244    }
245
246    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
247        self.fetch.fetch_data()
248    }
249
250    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
251        self.fetch.fetch_bytes_local()
252    }
253
254    fn fetch_data_local(&self) -> Option<Vec<u8>> {
255        self.fetch.fetch_data_local()
256    }
257}
258
259#[derive(ToOutput, InlineOutput, Tagged, Parse, ParseInline)]
260pub struct RawPoint<T, Extra = ()> {
261    inner: RawPointInner,
262    extra: Extras<Extra>,
263    object: ObjectMarker<T>,
264}
265
266impl<T, Extra> ListHashes for RawPoint<T, Extra> {
267    fn list_hashes(&self, f: &mut impl FnMut(Hash)) {
268        self.inner.list_hashes(f);
269    }
270
271    fn topology_hash(&self) -> Hash {
272        self.inner.topology_hash()
273    }
274
275    fn point_count(&self) -> usize {
276        self.inner.point_count()
277    }
278}
279
280impl<T, Extra: 'static + Clone> FromInner for RawPoint<T, Extra> {
281    type Inner = RawPointInner;
282    type Extra = Extra;
283
284    fn from_inner(inner: Self::Inner, extra: Self::Extra) -> Self {
285        RawPoint {
286            inner,
287            extra: Extras(extra),
288            object: Default::default(),
289        }
290    }
291}
292
293impl<T, Extra: Clone> Clone for RawPoint<T, Extra> {
294    fn clone(&self) -> Self {
295        Self {
296            inner: self.inner.clone(),
297            extra: self.extra.clone(),
298            object: Default::default(),
299        }
300    }
301}
302
303impl<T: 'static + Traversible, Extra: 'static + Send + Sync + Clone + ExtraFor<T>> Topological
304    for RawPoint<T, Extra>
305{
306    fn traverse(&self, visitor: &mut impl PointVisitor) {
307        visitor.visit(self);
308    }
309}
310
311impl<T, Extra: Send + Sync> Singular for RawPoint<T, Extra> {
312    fn hash(&self) -> Hash {
313        self.inner.hash()
314    }
315}
316
317impl<T, Extra: 'static + Clone> RawPoint<T, Extra> {
318    pub fn cast<U>(self) -> RawPoint<U, Extra> {
319        self.inner.cast(self.extra.0)
320    }
321}
322
323impl<T: 'static + FullHash, Extra: 'static + Send + Sync + ExtraFor<T>> RawPoint<T, Extra> {
324    pub fn into_point(self) -> Point<T> {
325        Point::from_fetch(self.inner.hash, Arc::new(self))
326    }
327}
328
329impl<T, Extra> FetchBytes for RawPoint<T, Extra> {
330    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
331        self.inner.fetch_bytes()
332    }
333
334    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
335        self.inner.fetch_data()
336    }
337
338    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
339        self.inner.fetch_bytes_local()
340    }
341
342    fn fetch_data_local(&self) -> Option<Vec<u8>> {
343        self.inner.fetch_data_local()
344    }
345
346    fn as_inner(&self) -> Option<&dyn Any> {
347        Some(&self.inner)
348    }
349}
350
351impl<T: FullHash, Extra: Send + Sync + ExtraFor<T>> Fetch for RawPoint<T, Extra> {
352    type T = T;
353
354    fn fetch_full(&'_ self) -> FailFuture<'_, Node<Self::T>> {
355        Box::pin(async {
356            let (data, resolve) = self.inner.fetch.fetch_bytes().await?;
357            let object = self.extra.0.parse(&data, &resolve)?;
358            if self.inner.hash != object.full_hash() {
359                Err(Error::FullHashMismatch)
360            } else {
361                Ok((object, resolve))
362            }
363        })
364    }
365
366    fn fetch(&'_ self) -> FailFuture<'_, Self::T> {
367        Box::pin(async {
368            let (data, resolve) = self.inner.fetch.fetch_bytes().await?;
369            let object = self.extra.0.parse(&data, &resolve)?;
370            if self.inner.hash != object.full_hash() {
371                Err(Error::FullHashMismatch)
372            } else {
373                Ok(object)
374            }
375        })
376    }
377
378    fn try_fetch_local(&self) -> object_rainbow::Result<Option<Node<Self::T>>> {
379        let Some((data, resolve)) = self.inner.fetch.fetch_bytes_local()? else {
380            return Ok(None);
381        };
382        let object = self.extra.0.parse(&data, &resolve)?;
383        if self.inner.hash != object.full_hash() {
384            Err(Error::FullHashMismatch)
385        } else {
386            Ok(Some((object, resolve)))
387        }
388    }
389}
390
391impl<T> Point<T> {
392    pub fn from_fetch(hash: Hash, fetch: Arc<dyn Fetch<T = T>>) -> Self {
393        Self {
394            hash: hash.into(),
395            fetch,
396        }
397    }
398
399    fn map_fetch<U>(
400        self,
401        f: impl FnOnce(Arc<dyn Fetch<T = T>>) -> Arc<dyn Fetch<T = U>>,
402    ) -> Point<U> {
403        Point {
404            hash: self.hash,
405            fetch: f(self.fetch),
406        }
407    }
408}
409
410#[derive(ParseAsInline)]
411#[must_use]
412pub struct Point<T> {
413    hash: OptionalHash,
414    fetch: Arc<dyn Fetch<T = T>>,
415}
416
417impl<T> Point<T> {
418    pub fn raw<Extra: 'static + Clone>(self, extra: Extra) -> RawPoint<T, Extra> {
419        {
420            if let Some(raw) = self.fetch.inner_cast(&extra) {
421                return raw;
422            }
423        }
424        RawPointInner {
425            hash: self.hash.unwrap(),
426            fetch: self.fetch,
427        }
428        .cast(extra)
429    }
430}
431
432impl<T> PartialOrd for Point<T> {
433    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
434        Some(self.cmp(other))
435    }
436}
437
438impl<T> Ord for Point<T> {
439    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
440        self.hash().cmp(&other.hash())
441    }
442}
443
444impl<T> Eq for Point<T> {}
445
446impl<T> PartialEq for Point<T> {
447    fn eq(&self, other: &Self) -> bool {
448        self.hash() == other.hash()
449    }
450}
451
452impl<T> Clone for Point<T> {
453    fn clone(&self) -> Self {
454        Self {
455            hash: self.hash,
456            fetch: self.fetch.clone(),
457        }
458    }
459}
460
461impl<T> Size for Point<T> {
462    const SIZE: usize = Hash::SIZE;
463    type Size = <Hash as Size>::Size;
464}
465
466impl<T: 'static + FullHash> Point<T>
467where
468    (): ExtraFor<T>,
469{
470    pub fn from_address(address: Address, resolve: Arc<dyn Resolve>) -> Self {
471        Self::from_address_extra(address, resolve, ())
472    }
473}
474
475impl<T: 'static + FullHash> Point<T> {
476    pub fn from_address_extra<Extra: 'static + Send + Sync + Clone + ExtraFor<T>>(
477        address: Address,
478        resolve: Arc<dyn Resolve>,
479        extra: Extra,
480    ) -> Self {
481        Self::from_fetch(
482            address.hash,
483            Arc::new(ByAddress::from_inner(
484                ByAddressInner { address, resolve },
485                extra,
486            )),
487        )
488    }
489
490    pub fn with_resolve<Extra: 'static + Send + Sync + Clone + ExtraFor<T>>(
491        &self,
492        resolve: Arc<dyn Resolve>,
493        extra: Extra,
494    ) -> Self {
495        Self::from_address_extra(Address::from_hash(self.hash()), resolve, extra)
496    }
497}
498
499impl<T> ListHashes for Point<T> {
500    fn list_hashes(&self, f: &mut impl FnMut(Hash)) {
501        f(self.hash());
502    }
503
504    fn point_count(&self) -> usize {
505        1
506    }
507}
508
509impl<T: Traversible> Topological for Point<T> {
510    fn traverse(&self, visitor: &mut impl PointVisitor) {
511        visitor.visit(self);
512    }
513}
514
515impl<T: 'static + FullHash, I: PointInput<Extra: Send + Sync + ExtraFor<T>>> ParseInline<I>
516    for Point<T>
517{
518    fn parse_inline(input: &mut I) -> object_rainbow::Result<Self> {
519        Ok(Self::from_address_extra(
520            input.parse_inline()?,
521            input.resolve(),
522            input.extra().clone(),
523        ))
524    }
525}
526
527impl<T: Tagged> Tagged for Point<T> {
528    const TAGS: Tags = T::TAGS;
529}
530
531impl<T> ToOutput for Point<T> {
532    fn to_output(&self, output: &mut dyn Output) {
533        self.hash().to_output(output);
534    }
535}
536
537impl<T> InlineOutput for Point<T> {}
538
539impl<T> FetchBytes for Point<T> {
540    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
541        self.fetch.fetch_bytes()
542    }
543
544    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
545        self.fetch.fetch_data()
546    }
547
548    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
549        self.fetch.fetch_bytes_local()
550    }
551
552    fn fetch_data_local(&self) -> Option<Vec<u8>> {
553        self.fetch.fetch_data_local()
554    }
555
556    fn as_inner(&self) -> Option<&dyn Any> {
557        self.fetch.as_inner()
558    }
559}
560
561impl<T> Singular for Point<T> {
562    fn hash(&self) -> Hash {
563        self.hash.unwrap()
564    }
565}
566
567impl<T> Point<T> {
568    pub fn get(&self) -> Option<&T> {
569        self.fetch.get()
570    }
571
572    pub fn try_fetch_local(&self) -> object_rainbow::Result<Option<Node<T>>> {
573        self.fetch.try_fetch_local()
574    }
575}
576
577impl<T: Traversible + Clone> Point<T> {
578    pub fn from_object(object: T) -> Self {
579        Self::from_fetch(object.full_hash(), Arc::new(LocalFetch { object }))
580    }
581
582    fn yolo_mut(&mut self) -> bool {
583        self.fetch.get().is_some()
584            && Arc::get_mut(&mut self.fetch).is_some_and(|fetch| fetch.get_mut().is_some())
585    }
586
587    async fn prepare_yolo_fetch(&mut self) -> object_rainbow::Result<()> {
588        if !self.yolo_mut() {
589            let object = self.fetch.fetch().await?;
590            self.fetch = Arc::new(LocalFetch { object });
591        }
592        Ok(())
593    }
594
595    pub async fn fetch_mut(&'_ mut self) -> object_rainbow::Result<PointMut<'_, T>> {
596        self.prepare_yolo_fetch().await?;
597        let fetch = Arc::get_mut(&mut self.fetch).unwrap();
598        assert!(fetch.get_mut().is_some());
599        self.hash.clear();
600        Ok(PointMut {
601            hash: &mut self.hash,
602            fetch,
603        })
604    }
605
606    pub async fn fetch_ref(&mut self) -> object_rainbow::Result<&T> {
607        self.prepare_yolo_fetch().await?;
608        Ok(self.fetch.get().unwrap())
609    }
610}
611
612impl<T: FullHash> Fetch for Point<T> {
613    type T = T;
614
615    fn fetch_full(&'_ self) -> FailFuture<'_, Node<Self::T>> {
616        self.fetch.fetch_full()
617    }
618
619    fn fetch(&'_ self) -> FailFuture<'_, Self::T> {
620        self.fetch.fetch()
621    }
622
623    fn try_fetch_local(&self) -> object_rainbow::Result<Option<Node<Self::T>>> {
624        self.fetch.try_fetch_local()
625    }
626
627    fn fetch_local(&self) -> Option<Self::T> {
628        self.fetch.fetch_local()
629    }
630
631    fn get(&self) -> Option<&Self::T> {
632        self.fetch.get()
633    }
634
635    fn get_mut(&mut self) -> Option<&mut Self::T> {
636        self.hash.clear();
637        Arc::get_mut(&mut self.fetch)?.get_mut()
638    }
639
640    fn get_mut_finalize(&mut self) {
641        let fetch = Arc::get_mut(&mut self.fetch).unwrap();
642        fetch.get_mut_finalize();
643        self.hash = fetch.get().unwrap().full_hash().into();
644    }
645}
646
647/// This implementation is the main goal of [`Equivalent`]: we assume transmuting the pointer is
648/// safe.
649impl<U: 'static + Equivalent<T>, T: 'static> Equivalent<Point<T>> for Point<U> {
650    fn into_equivalent(self) -> Point<T> {
651        self.map_fetch(|fetch| {
652            Arc::new(MapEquivalent {
653                fetch,
654                map: U::into_equivalent,
655            })
656        })
657    }
658
659    fn from_equivalent(point: Point<T>) -> Self {
660        point.map_fetch(|fetch| {
661            Arc::new(MapEquivalent {
662                fetch,
663                map: U::from_equivalent,
664            })
665        })
666    }
667}
668
669impl<T> MaybeHasNiche for Point<T> {
670    type MnArray = <Hash as MaybeHasNiche>::MnArray;
671}
672
673impl<T: FullHash + Default> Point<T> {
674    pub fn is_default(&self) -> bool {
675        self.hash() == T::default().full_hash()
676    }
677}
678
679impl<T: Default + Traversible + Clone> Default for Point<T> {
680    fn default() -> Self {
681        T::default().point()
682    }
683}
684
685pub trait IntoPoint: Traversible {
686    fn point(self) -> Point<Self>
687    where
688        Self: Clone,
689    {
690        Point::from_object(self)
691    }
692}
693
694impl<T: Traversible> IntoPoint for T {}
695
696struct LocalFetch<T> {
697    object: T,
698}
699
700impl<T: Traversible + Clone> Fetch for LocalFetch<T> {
701    type T = T;
702
703    fn fetch_full(&'_ self) -> FailFuture<'_, Node<Self::T>> {
704        Box::pin(ready(Ok((self.object.clone(), self.object.to_resolve()))))
705    }
706
707    fn fetch(&'_ self) -> FailFuture<'_, Self::T> {
708        Box::pin(ready(Ok(self.object.clone())))
709    }
710
711    fn try_fetch_local(&self) -> object_rainbow::Result<Option<Node<Self::T>>> {
712        Ok(Some((self.object.clone(), self.object.to_resolve())))
713    }
714
715    fn fetch_local(&self) -> Option<Self::T> {
716        Some(self.object.clone())
717    }
718
719    fn get(&self) -> Option<&Self::T> {
720        Some(&self.object)
721    }
722
723    fn get_mut(&mut self) -> Option<&mut Self::T> {
724        Some(&mut self.object)
725    }
726}
727
728impl<T: Traversible + Clone> FetchBytes for LocalFetch<T> {
729    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
730        Box::pin(ready(Ok((self.object.output(), self.object.to_resolve()))))
731    }
732
733    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
734        Box::pin(ready(Ok(self.object.output())))
735    }
736
737    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
738        Ok(Some((self.object.output(), self.object.to_resolve())))
739    }
740
741    fn fetch_data_local(&self) -> Option<Vec<u8>> {
742        Some(self.object.output())
743    }
744}
745
746impl<T: Traversible + Clone> Singular for LocalFetch<T> {
747    fn hash(&self) -> Hash {
748        self.object.full_hash()
749    }
750}
751
752struct MapEquivalent<T, F> {
753    fetch: Arc<dyn Fetch<T = T>>,
754    map: F,
755}
756
757impl<T, F> FetchBytes for MapEquivalent<T, F> {
758    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
759        self.fetch.fetch_bytes()
760    }
761
762    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
763        self.fetch.fetch_data()
764    }
765
766    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
767        self.fetch.fetch_bytes_local()
768    }
769
770    fn fetch_data_local(&self) -> Option<Vec<u8>> {
771        self.fetch.fetch_data_local()
772    }
773}
774
775trait Map1<T>: Fn(T) -> Self::U {
776    type U;
777}
778
779impl<T, U, F: Fn(T) -> U> Map1<T> for F {
780    type U = U;
781}
782
783impl<T, F: Send + Sync + Map1<T>> Fetch for MapEquivalent<T, F> {
784    type T = F::U;
785
786    fn fetch_full(&'_ self) -> FailFuture<'_, Node<Self::T>> {
787        Box::pin(self.fetch.fetch_full().map_ok(|(x, r)| ((self.map)(x), r)))
788    }
789
790    fn fetch(&'_ self) -> FailFuture<'_, Self::T> {
791        Box::pin(self.fetch.fetch().map_ok(&self.map))
792    }
793
794    fn try_fetch_local(&self) -> object_rainbow::Result<Option<Node<Self::T>>> {
795        let Some((object, resolve)) = self.fetch.try_fetch_local()? else {
796            return Ok(None);
797        };
798        let object = (self.map)(object);
799        Ok(Some((object, resolve)))
800    }
801
802    fn fetch_local(&self) -> Option<Self::T> {
803        self.fetch.fetch_local().map(&self.map)
804    }
805}
806
807pub struct PointMut<'a, T: FullHash> {
808    hash: &'a mut OptionalHash,
809    fetch: &'a mut dyn Fetch<T = T>,
810}
811
812impl<T: FullHash> Deref for PointMut<'_, T> {
813    type Target = T;
814
815    fn deref(&self) -> &Self::Target {
816        self.fetch.get().unwrap()
817    }
818}
819
820impl<T: FullHash> DerefMut for PointMut<'_, T> {
821    fn deref_mut(&mut self) -> &mut Self::Target {
822        self.fetch.get_mut().unwrap()
823    }
824}
825
826impl<T: FullHash> Drop for PointMut<'_, T> {
827    fn drop(&mut self) {
828        self.finalize();
829    }
830}
831
832impl<'a, T: FullHash> PointMut<'a, T> {
833    fn finalize(&mut self) {
834        self.fetch.get_mut_finalize();
835        *self.hash = self.full_hash().into();
836    }
837}