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