Skip to main content

object_rainbow_point/
lib.rs

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