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