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
666impl<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}