peniko/
blob.rs

1// Copyright 2022 the Peniko Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4use core::fmt;
5use core::sync::atomic::{AtomicU64, Ordering};
6extern crate alloc;
7use alloc::boxed::Box;
8use alloc::sync::{Arc, Weak};
9use alloc::vec::Vec;
10
11/// Shared data with an associated unique identifier.
12pub struct Blob<T> {
13    data: Arc<dyn AsRef<[T]> + Send + Sync>,
14    id: u64,
15}
16
17#[cfg(feature = "serde")]
18impl<T> serde::Serialize for Blob<T>
19where
20    [T]: serde_bytes::Serialize,
21{
22    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23    where
24        S: serde::ser::Serializer,
25    {
26        serde_bytes::serialize(self.data(), serializer)
27    }
28}
29
30#[cfg(feature = "serde")]
31impl<'de, T> serde::de::Deserialize<'de> for Blob<T>
32where
33    T: serde::de::Deserialize<'de> + Sync + Send + 'static,
34    Box<[u8]>: AsRef<[T]>,
35{
36    fn deserialize<D>(des: D) -> Result<Self, D::Error>
37    where
38        D: serde::de::Deserializer<'de>,
39    {
40        let byte_buf: serde_bytes::ByteBuf = serde_bytes::Deserialize::deserialize(des)?;
41        let boxed_slice: Box<[u8]> = byte_buf.into_boxed_slice();
42        Ok(Self::new(Arc::new(boxed_slice)))
43    }
44}
45
46impl<T> fmt::Debug for Blob<T> {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        f.debug_struct("Blob")
49            .field("id", &self.id)
50            .finish_non_exhaustive()
51    }
52}
53
54impl<T> PartialEq for Blob<T> {
55    fn eq(&self, other: &Self) -> bool {
56        self.id == other.id
57    }
58}
59
60impl<T> Clone for Blob<T> {
61    fn clone(&self) -> Self {
62        Self {
63            data: Arc::clone(&self.data),
64            id: self.id,
65        }
66    }
67}
68
69impl<T> AsRef<[T]> for Blob<T> {
70    fn as_ref(&self) -> &[T] {
71        self.data()
72    }
73}
74
75impl<T> From<Vec<T>> for Blob<T>
76where
77    T: 'static + Send + Sync,
78{
79    fn from(vec: Vec<T>) -> Self {
80        let boxed: Box<[T]> = vec.into();
81        Self::new(Arc::new(boxed))
82    }
83}
84
85static ID_COUNTER: AtomicU64 = AtomicU64::new(0);
86
87impl<T> Blob<T> {
88    /// Creates a new blob from the given data and generates a unique
89    /// identifier.
90    pub fn new(data: Arc<dyn AsRef<[T]> + Send + Sync>) -> Self {
91        Self {
92            data,
93            id: ID_COUNTER.fetch_add(1, Ordering::Relaxed),
94        }
95    }
96
97    /// Creates a new blob from the given data and identifier.
98    ///
99    /// Note that while this function is not unsafe, usage of this in combination
100    /// with `new` (or with identifiers that are not uniquely associated with the given data)
101    /// can lead to inconsistencies.
102    ///
103    /// This is primarily for libraries that wish to interop with vello but are
104    /// unable to depend on our resource types.
105    pub fn from_raw_parts(data: Arc<dyn AsRef<[T]> + Send + Sync>, id: u64) -> Self {
106        Self { data, id }
107    }
108
109    /// Consumes self and returns the inner components of the blob.
110    #[must_use]
111    pub fn into_raw_parts(self) -> (Arc<dyn AsRef<[T]> + Send + Sync>, u64) {
112        (self.data, self.id)
113    }
114
115    /// Returns the length of the data.
116    #[must_use]
117    pub fn len(&self) -> usize {
118        self.data().len()
119    }
120
121    /// Returns `true` if the blob is empty.
122    #[must_use]
123    pub fn is_empty(&self) -> bool {
124        self.len() == 0
125    }
126
127    /// Returns a reference to the underlying data.
128    #[must_use]
129    pub fn data(&self) -> &[T] {
130        self.data.as_ref().as_ref()
131    }
132
133    /// Returns the unique identifier associated with the data.
134    #[must_use]
135    pub fn id(&self) -> u64 {
136        self.id
137    }
138
139    /// Returns the number of existing strong pointers to this blob.
140    #[must_use]
141    pub fn strong_count(&self) -> usize {
142        Arc::strong_count(&self.data)
143    }
144
145    /// Downgrades the shared blob to a weak reference.
146    #[must_use]
147    pub fn downgrade(&self) -> WeakBlob<T> {
148        WeakBlob {
149            data: Arc::downgrade(&self.data),
150            id: self.id,
151        }
152    }
153}
154
155/// Weak reference to a shared [blob](Blob).
156#[derive(Debug)]
157pub struct WeakBlob<T> {
158    data: Weak<dyn AsRef<[T]> + Send + Sync>,
159    id: u64,
160}
161
162impl<T> Clone for WeakBlob<T> {
163    fn clone(&self) -> Self {
164        Self {
165            data: Weak::clone(&self.data),
166            id: self.id,
167        }
168    }
169}
170
171impl<T> WeakBlob<T> {
172    /// Returns the unique identifier associated with the data.
173    #[must_use]
174    pub fn id(&self) -> u64 {
175        self.id
176    }
177
178    /// Upgrades the weak reference. Returns `None` if the inner value has been
179    /// dropped.
180    #[must_use]
181    pub fn upgrade(&self) -> Option<Blob<T>> {
182        Some(Blob {
183            data: self.data.upgrade()?,
184            id: self.id,
185        })
186    }
187}