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