Skip to main content

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}