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 async fn echo(fetch: impl 'static + Fetch<T = T>) -> object_rainbow::Result<Self>
455    where
456        T: FullHash,
457    {
458        Ok(Self::from_alternate_source(&fetch.fetch().await?, fetch))
459    }
460
461    pub fn from_alternate_source(object: &T, fetch: impl 'static + Fetch<T = T>) -> Self
462    where
463        T: FullHash,
464    {
465        Self::from_fetch(object.full_hash(), fetch)
466    }
467
468    fn from_trusted_fetch(hash: Hash, fetch: Arc<dyn Fetch<T = T>>) -> Self {
469        Self {
470            hash: hash.into(),
471            fetch,
472        }
473    }
474
475    pub fn from_fetch(hash: Hash, fetch: impl 'static + Fetch<T = T>) -> Self {
476        Self::from_trusted_fetch(hash, fetch.into_dyn_fetch())
477    }
478
479    pub fn from_singular(singular: impl 'static + SingularFetch<T = T>) -> Self {
480        Self::from_fetch(singular.hash(), singular)
481    }
482
483    fn map_fetch<U>(
484        self,
485        f: impl FnOnce(Arc<dyn Fetch<T = T>>) -> Arc<dyn Fetch<T = U>>,
486    ) -> Point<U> {
487        Point {
488            hash: self.hash,
489            fetch: f(self.fetch),
490        }
491    }
492}
493
494impl<U: 'static + Equivalent<T>, T: 'static, Extra> Equivalent<RawPoint<T, Extra>>
495    for RawPoint<U, Extra>
496{
497    fn into_equivalent(self) -> RawPoint<T, Extra> {
498        RawPoint {
499            inner: self.inner,
500            extra: self.extra,
501            object: Default::default(),
502        }
503    }
504
505    fn from_equivalent(object: RawPoint<T, Extra>) -> Self {
506        Self {
507            inner: object.inner,
508            extra: object.extra,
509            object: Default::default(),
510        }
511    }
512}
513
514#[derive(ParseAsInline, Tagged)]
515#[must_use]
516pub struct Point<T> {
517    hash: OptionalHash,
518    fetch: Arc<dyn Fetch<T = T>>,
519}
520
521impl<T> std::hash::Hash for Point<T> {
522    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
523        self.hash.hash(state);
524    }
525}
526
527impl<T> std::fmt::Debug for Point<T> {
528    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
529        #[derive(Debug)]
530        struct Arc;
531        f.debug_struct("Point")
532            .field("hash", &self.hash)
533            .field("fetch", &Arc)
534            .finish()
535    }
536}
537
538impl<T> Point<T> {
539    pub fn raw<Extra: 'static + Clone>(self, extra: Extra) -> RawPoint<T, Extra> {
540        {
541            if let Some(raw) = self.fetch.inner_cast(&extra) {
542                return raw;
543            }
544        }
545        RawPointInner {
546            hash: self.hash(),
547            fetch: self.fetch,
548        }
549        .cast(extra)
550    }
551}
552
553impl<T> PartialOrd for Point<T> {
554    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
555        Some(self.cmp(other))
556    }
557}
558
559impl<T> Ord for Point<T> {
560    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
561        self.hash().cmp(&other.hash())
562    }
563}
564
565impl<T> Eq for Point<T> {}
566
567impl<T> PartialEq for Point<T> {
568    fn eq(&self, other: &Self) -> bool {
569        self.hash() == other.hash()
570    }
571}
572
573impl<T> Clone for Point<T> {
574    fn clone(&self) -> Self {
575        Self {
576            hash: self.hash,
577            fetch: self.fetch.clone(),
578        }
579    }
580}
581
582impl<T> Size for Point<T> {
583    const SIZE: usize = Hash::SIZE;
584    type Size = <Hash as Size>::Size;
585}
586
587impl<T: 'static + FullHash> Point<T>
588where
589    (): ExtraFor<T>,
590{
591    pub fn from_address(address: Address, resolve: Arc<dyn Resolve>) -> Self {
592        Self::from_address_extra(address, resolve, ())
593    }
594}
595
596impl<T: 'static + FullHash> Point<T> {
597    pub fn from_address_extra<Extra: 'static + Send + Sync + Clone + ExtraFor<T>>(
598        address: Address,
599        resolve: Arc<dyn Resolve>,
600        extra: Extra,
601    ) -> Self {
602        Self::from_trusted_fetch(
603            address.hash,
604            ByAddress::from_inner(ByAddressInner { address, resolve }, extra).into_dyn_fetch(),
605        )
606    }
607
608    pub fn with_resolve<Extra: 'static + Send + Sync + Clone + ExtraFor<T>>(
609        &self,
610        resolve: Arc<dyn Resolve>,
611        extra: Extra,
612    ) -> Self {
613        Self::from_address_extra(Address::from_hash(self.hash()), resolve, extra)
614    }
615
616    pub fn from_fetch_extra<Extra: 'static + Send + Sync + Clone + ExtraFor<T>>(
617        address: Address,
618        resolve: Arc<dyn Resolve>,
619        fetch: impl 'static + Fetch<T = Extra>,
620    ) -> Self
621    where
622        T: Send,
623    {
624        Self::from_trusted_fetch(
625            address.hash,
626            FetchExtra::from_inner(ByAddressInner { address, resolve }, fetch).into_dyn_fetch(),
627        )
628    }
629}
630
631impl<T> ListHashes for Point<T> {
632    fn list_hashes(&self, f: &mut impl FnMut(Hash)) {
633        f(self.hash());
634    }
635
636    fn point_count(&self) -> usize {
637        1
638    }
639}
640
641impl<T: Traversible> Topological for Point<T> {
642    fn traverse(&self, visitor: &mut impl PointVisitor) {
643        visitor.visit(self);
644    }
645}
646
647impl<T: 'static + FullHash, I: PointInput<Extra: Send + Sync + ExtraFor<T>>> ParseInline<I>
648    for Point<T>
649{
650    fn parse_inline(input: &mut I) -> object_rainbow::Result<Self> {
651        Ok(Self::from_address_extra(
652            input.parse_inline()?,
653            input.resolve(),
654            input.extra().clone(),
655        ))
656    }
657}
658
659impl<T> ToOutput for Point<T> {
660    fn to_output(&self, output: &mut impl Output) {
661        self.hash().to_output(output);
662    }
663}
664
665impl<T> InlineOutput for Point<T> {}
666
667impl<T> FetchBytes for Point<T> {
668    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
669        self.fetch.fetch_bytes()
670    }
671
672    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
673        self.fetch.fetch_data()
674    }
675
676    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
677        self.fetch.fetch_bytes_local()
678    }
679
680    fn fetch_data_local(&self) -> Option<Vec<u8>> {
681        self.fetch.fetch_data_local()
682    }
683
684    fn as_inner(&self) -> Option<&dyn Any> {
685        self.fetch.as_inner()
686    }
687
688    fn as_resolve(&self) -> Option<&Arc<dyn Resolve>> {
689        self.fetch.as_resolve()
690    }
691
692    fn try_unwrap_resolve(self: Arc<Self>) -> Option<Arc<dyn Resolve>> {
693        Arc::try_unwrap(self).ok()?.fetch.try_unwrap_resolve()
694    }
695}
696
697impl<T> Singular for Point<T> {
698    fn hash(&self) -> Hash {
699        self.hash.unwrap()
700    }
701}
702
703impl<T> Point<T> {
704    pub fn get(&self) -> Option<&T> {
705        self.fetch.get()
706    }
707
708    pub fn try_fetch_local(&self) -> object_rainbow::Result<Option<Node<T>>> {
709        self.fetch.try_fetch_local()
710    }
711
712    pub fn try_unwrap(self) -> Option<T> {
713        self.fetch.try_unwrap()
714    }
715
716    pub fn fetch(&self) -> FailFuture<'_, T> {
717        self.fetch.fetch()
718    }
719}
720
721impl<T: Traversible + Clone> Point<T> {
722    pub fn from_object(object: T) -> Self {
723        Self::from_trusted_fetch(object.full_hash(), object.local_fetch())
724    }
725
726    fn yolo_mut(&mut self) -> bool {
727        self.fetch.get().is_some()
728            && Arc::get_mut(&mut self.fetch).is_some_and(|fetch| fetch.get_mut().is_some())
729    }
730
731    async fn prepare_yolo_fetch(&mut self) -> object_rainbow::Result<()> {
732        if !self.yolo_mut() {
733            let object = self.fetch.fetch().await?;
734            self.fetch = object.local_fetch();
735        }
736        Ok(())
737    }
738
739    pub async fn fetch_mut(&'_ mut self) -> object_rainbow::Result<PointMut<'_, T>> {
740        self.prepare_yolo_fetch().await?;
741        let fetch = Arc::get_mut(&mut self.fetch).expect("shared fetch?");
742        assert!(fetch.get_mut().is_some());
743        self.hash.clear();
744        Ok(PointMut {
745            hash: &mut self.hash,
746            fetch,
747        })
748    }
749
750    pub async fn fetch_ref(&mut self) -> object_rainbow::Result<&T> {
751        self.prepare_yolo_fetch().await?;
752        Ok(self.fetch.get().expect("non-local fetch"))
753    }
754
755    pub async fn fetch_take(&mut self) -> object_rainbow::Result<T>
756    where
757        T: Default,
758    {
759        Ok(std::mem::take(&mut *self.fetch_mut().await?))
760    }
761}
762
763impl<T: FullHash> Fetch for Point<T> {
764    type T = T;
765
766    fn fetch_full(&'_ self) -> FailFuture<'_, Node<Self::T>> {
767        self.fetch.fetch_full()
768    }
769
770    fn fetch(&'_ self) -> FailFuture<'_, Self::T> {
771        self.fetch.fetch()
772    }
773
774    fn try_fetch_local(&self) -> object_rainbow::Result<Option<Node<Self::T>>> {
775        self.fetch.try_fetch_local()
776    }
777
778    fn fetch_local(&self) -> Option<Self::T> {
779        self.fetch.fetch_local()
780    }
781
782    fn get(&self) -> Option<&Self::T> {
783        self.fetch.get()
784    }
785
786    fn get_mut(&mut self) -> Option<&mut Self::T> {
787        self.hash.clear();
788        Arc::get_mut(&mut self.fetch)?.get_mut()
789    }
790
791    fn get_mut_finalize(&mut self) {
792        let fetch = Arc::get_mut(&mut self.fetch).expect("shared fetch?");
793        fetch.get_mut_finalize();
794        self.hash = fetch.get().expect("non-local fetch").full_hash().into();
795    }
796
797    fn try_unwrap(self: Arc<Self>) -> Option<Self::T> {
798        Arc::try_unwrap(self).ok()?.fetch.try_unwrap()
799    }
800
801    fn into_dyn_fetch<'a>(self) -> Arc<dyn 'a + Fetch<T = Self::T>>
802    where
803        Self: 'a + Sized,
804    {
805        self.fetch
806    }
807}
808
809/// This implementation is the main goal of [`Equivalent`]: we assume transmuting the pointer is
810/// safe.
811impl<U: 'static + Equivalent<T>, T: 'static> Equivalent<Point<T>> for Point<U> {
812    fn into_equivalent(self) -> Point<T> {
813        self.map_fetch(|fetch| {
814            MapEquivalent {
815                fetch,
816                map: U::into_equivalent,
817            }
818            .into_dyn_fetch()
819        })
820    }
821
822    fn from_equivalent(point: Point<T>) -> Self {
823        point.map_fetch(|fetch| {
824            MapEquivalent {
825                fetch,
826                map: U::from_equivalent,
827            }
828            .into_dyn_fetch()
829        })
830    }
831}
832
833impl<T> MaybeHasNiche for Point<T> {
834    type MnArray = <Hash as MaybeHasNiche>::MnArray;
835}
836
837impl<T: DefaultHash> Point<T> {
838    pub fn is_default(&self) -> bool {
839        self.hash() == T::default_hash()
840    }
841}
842
843impl<T: Default + Traversible + Clone> Default for Point<T> {
844    fn default() -> Self {
845        T::default().point()
846    }
847}
848
849pub trait IntoPoint: Traversible {
850    fn point(self) -> Point<Self>
851    where
852        Self: Clone,
853    {
854        Point::from_object(self)
855    }
856}
857
858impl<T: Traversible> IntoPoint for T {}
859
860struct MapEquivalent<T, F> {
861    fetch: Arc<dyn Fetch<T = T>>,
862    map: F,
863}
864
865impl<T, F> FetchBytes for MapEquivalent<T, F> {
866    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
867        self.fetch.fetch_bytes()
868    }
869
870    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
871        self.fetch.fetch_data()
872    }
873
874    fn fetch_bytes_local(&self) -> object_rainbow::Result<Option<ByteNode>> {
875        self.fetch.fetch_bytes_local()
876    }
877
878    fn fetch_data_local(&self) -> Option<Vec<u8>> {
879        self.fetch.fetch_data_local()
880    }
881
882    fn as_resolve(&self) -> Option<&Arc<dyn Resolve>> {
883        self.fetch.as_resolve()
884    }
885
886    fn try_unwrap_resolve(self: Arc<Self>) -> Option<Arc<dyn Resolve>> {
887        Arc::try_unwrap(self).ok()?.fetch.try_unwrap_resolve()
888    }
889}
890
891trait Map1<T>: Fn(T) -> Self::U {
892    type U;
893}
894
895impl<T, U, F: Fn(T) -> U> Map1<T> for F {
896    type U = U;
897}
898
899impl<T, F: Send + Sync + Map1<T>> Fetch for MapEquivalent<T, F> {
900    type T = F::U;
901
902    fn fetch_full(&'_ self) -> FailFuture<'_, Node<Self::T>> {
903        Box::pin(self.fetch.fetch_full().map_ok(|(x, r)| ((self.map)(x), r)))
904    }
905
906    fn fetch(&'_ self) -> FailFuture<'_, Self::T> {
907        Box::pin(self.fetch.fetch().map_ok(&self.map))
908    }
909
910    fn try_fetch_local(&self) -> object_rainbow::Result<Option<Node<Self::T>>> {
911        let Some((object, resolve)) = self.fetch.try_fetch_local()? else {
912            return Ok(None);
913        };
914        let object = (self.map)(object);
915        Ok(Some((object, resolve)))
916    }
917
918    fn fetch_local(&self) -> Option<Self::T> {
919        self.fetch.fetch_local().map(&self.map)
920    }
921
922    fn try_unwrap(self: Arc<Self>) -> Option<Self::T> {
923        let Self { fetch, map } = Arc::try_unwrap(self).ok()?;
924        fetch.try_unwrap().map(map)
925    }
926}
927
928pub struct PointMut<'a, T: FullHash> {
929    hash: &'a mut OptionalHash,
930    fetch: &'a mut dyn Fetch<T = T>,
931}
932
933impl<T: FullHash> Deref for PointMut<'_, T> {
934    type Target = T;
935
936    fn deref(&self) -> &Self::Target {
937        self.fetch.get().expect("non-local fetch")
938    }
939}
940
941impl<T: FullHash> DerefMut for PointMut<'_, T> {
942    fn deref_mut(&mut self) -> &mut Self::Target {
943        self.fetch.get_mut().expect("non-local fetch")
944    }
945}
946
947impl<T: FullHash> Drop for PointMut<'_, T> {
948    fn drop(&mut self) {
949        if !std::thread::panicking() {
950            self.finalize();
951        }
952    }
953}
954
955impl<'a, T: FullHash> PointMut<'a, T> {
956    fn finalize(&mut self) {
957        self.fetch.get_mut_finalize();
958        *self.hash = self.full_hash().into();
959    }
960}
961
962#[derive(ToOutput, InlineOutput, ListHashes, Topological, Tagged, Parse, ParseInline)]
963pub struct ExtraPoint<T, Extra = ()> {
964    pub extra: Extras<Extra>,
965    pub point: Point<T>,
966}
967
968impl<T, Extra: std::fmt::Debug> std::fmt::Debug for ExtraPoint<T, Extra> {
969    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
970        f.debug_struct("ExtraPoint")
971            .field("extra", &self.extra)
972            .field("point", &self.point)
973            .finish()
974    }
975}
976
977impl<T, Extra: Clone> Clone for ExtraPoint<T, Extra> {
978    fn clone(&self) -> Self {
979        Self {
980            extra: self.extra.clone(),
981            point: self.point.clone(),
982        }
983    }
984}
985
986impl<T, Extra: PartialEq> PartialEq for ExtraPoint<T, Extra> {
987    fn eq(&self, other: &Self) -> bool {
988        self.extra == other.extra && self.point == other.point
989    }
990}
991
992impl<T, Extra: Clone> CanonicalExtra for ExtraPoint<T, Extra> {
993    type Extra = Extra;
994
995    fn canonical_extra(&self) -> Self::Extra {
996        self.extra.canonical_extra()
997    }
998}
999
1000impl<T, E> FetchBytes for ExtraPoint<T, E> {
1001    fn fetch_bytes(&'_ self) -> FailFuture<'_, ByteNode> {
1002        self.point.fetch_bytes()
1003    }
1004
1005    fn fetch_data(&'_ self) -> FailFuture<'_, Vec<u8>> {
1006        self.point.fetch_data()
1007    }
1008}
1009
1010impl<T: FullHash, E: Send + Sync> Fetch for ExtraPoint<T, E> {
1011    type T = T;
1012
1013    fn fetch_full(&'_ self) -> FailFuture<'_, Node<Self::T>> {
1014        self.point.fetch_full()
1015    }
1016
1017    fn fetch(&'_ self) -> FailFuture<'_, Self::T> {
1018        self.point.fetch()
1019    }
1020}
1021
1022impl<T: 'static + Send + FullHash, E: 'static + Send + Sync + Clone + ExtraFor<T>> ParseFetch<E>
1023    for Point<T>
1024{
1025    fn parse_fetch<I: PointInput<Extra: Fetch<T = E>>>(input: I) -> object_rainbow::Result<Self> {
1026        Self::parse_fetch_as_inline(input)
1027    }
1028}
1029
1030impl<T: 'static + Send + FullHash, E: 'static + Send + Sync + Clone + ExtraFor<T>>
1031    ParseFetchInline<E> for Point<T>
1032{
1033    fn parse_fetch_inline<I: PointInput<Extra: Fetch<T = E>>>(
1034        input: &mut I,
1035    ) -> object_rainbow::Result<Self> {
1036        Ok(Self::from_fetch_extra(
1037            input.parse_inline()?,
1038            input.resolve(),
1039            input.extra().clone(),
1040        ))
1041    }
1042}