Skip to main content

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