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