linera_cache/arc.rs
1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! A provenance-tracking wrapper around [`std::sync::Arc`].
5//!
6//! [`Arc<T>`] is identical to [`std::sync::Arc<T>`] at runtime but has no
7//! public constructor. The only way to obtain one is through
8//! [`ValueCache::insert`], [`ValueCache::insert_hashed`], or
9//! [`ValueCache::get`]. This makes the "one allocation per content" invariant
10//! structurally enforced: callers cannot bypass the cache by calling
11//! `Arc::new` directly.
12
13use std::{
14 fmt,
15 hash::{Hash, Hasher},
16 ops::Deref,
17 sync::Arc as StdArc,
18};
19
20/// A reference-counted pointer that can only be constructed through a
21/// [`crate::ValueCache`].
22///
23/// `Arc<T>` wraps [`std::sync::Arc<T>`] and implements `Deref<Target = T>`,
24/// `Clone`, `Debug`, `Display`, `PartialEq`, `Eq`, and `Hash` identically.
25///
26/// Use [`Arc::into_std`] or [`Arc::as_std`] to interoperate with APIs that
27/// require [`std::sync::Arc<T>`] explicitly.
28pub struct Arc<T>(pub(crate) StdArc<T>);
29
30impl<T> Arc<T> {
31 /// Returns a reference to the underlying [`std::sync::Arc<T>`].
32 pub fn as_std(&self) -> &StdArc<T> {
33 &self.0
34 }
35
36 /// Converts into the underlying [`std::sync::Arc<T>`].
37 pub fn into_std(self) -> StdArc<T> {
38 self.0
39 }
40
41 /// Unwraps the inner value if this is the only strong reference;
42 /// otherwise clones it.
43 pub fn unwrap_or_clone(this: Self) -> T
44 where
45 T: Clone,
46 {
47 StdArc::unwrap_or_clone(this.0)
48 }
49
50 /// Returns `true` if two `Arc`s point to the same allocation.
51 pub fn ptr_eq(a: &Self, b: &Self) -> bool {
52 StdArc::ptr_eq(&a.0, &b.0)
53 }
54}
55
56impl<T> Deref for Arc<T> {
57 type Target = T;
58
59 fn deref(&self) -> &T {
60 &self.0
61 }
62}
63
64impl<T> Clone for Arc<T> {
65 fn clone(&self) -> Self {
66 Self(self.0.clone())
67 }
68}
69
70impl<T: fmt::Debug> fmt::Debug for Arc<T> {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 fmt::Debug::fmt(&*self.0, f)
73 }
74}
75
76impl<T: fmt::Display> fmt::Display for Arc<T> {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 fmt::Display::fmt(&*self.0, f)
79 }
80}
81
82impl<T: PartialEq> PartialEq for Arc<T> {
83 fn eq(&self, other: &Self) -> bool {
84 self.0 == other.0
85 }
86}
87
88impl<T: Eq> Eq for Arc<T> {}
89
90impl<T: Hash> Hash for Arc<T> {
91 fn hash<H: Hasher>(&self, state: &mut H) {
92 self.0.hash(state);
93 }
94}
95
96impl<T> From<Arc<T>> for StdArc<T> {
97 fn from(arc: Arc<T>) -> Self {
98 arc.0
99 }
100}
101
102impl<T> AsRef<StdArc<T>> for Arc<T> {
103 fn as_ref(&self) -> &StdArc<T> {
104 &self.0
105 }
106}