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