linebender_resource_handle/
blob.rs1use core::fmt;
5use core::sync::atomic::Ordering;
6extern crate alloc;
7use alloc::boxed::Box;
8use alloc::sync::{Arc, Weak};
9use alloc::vec::Vec;
10
11#[cfg(not(target_has_atomic = "64"))]
12use core::sync::atomic::AtomicU32 as AtomicCounter;
13#[cfg(target_has_atomic = "64")]
14use core::sync::atomic::AtomicU64 as AtomicCounter;
15
16pub struct Blob<T> {
18 data: Arc<dyn AsRef<[T]> + Send + Sync>,
19 id: u64,
20}
21
22#[cfg(feature = "serde")]
23impl<T> serde::Serialize for Blob<T>
24where
25 [T]: serde_bytes::Serialize,
26{
27 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
28 where
29 S: serde::ser::Serializer,
30 {
31 serde_bytes::serialize(self.data(), serializer)
32 }
33}
34
35#[cfg(feature = "serde")]
36impl<'de, T> serde::de::Deserialize<'de> for Blob<T>
37where
38 T: serde::de::Deserialize<'de> + Sync + Send + 'static,
39 Box<[u8]>: AsRef<[T]>,
40{
41 fn deserialize<D>(des: D) -> Result<Self, D::Error>
42 where
43 D: serde::de::Deserializer<'de>,
44 {
45 let byte_buf: serde_bytes::ByteBuf = serde_bytes::Deserialize::deserialize(des)?;
46 let boxed_slice: Box<[u8]> = byte_buf.into_boxed_slice();
47 Ok(Self::new(Arc::new(boxed_slice)))
48 }
49}
50
51impl<T> fmt::Debug for Blob<T> {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 f.debug_struct("Blob")
54 .field("id", &self.id)
55 .finish_non_exhaustive()
56 }
57}
58
59impl<T> PartialEq for Blob<T> {
60 fn eq(&self, other: &Self) -> bool {
61 self.id == other.id
62 }
63}
64
65impl<T> Clone for Blob<T> {
66 fn clone(&self) -> Self {
67 Self {
68 data: Arc::clone(&self.data),
69 id: self.id,
70 }
71 }
72}
73
74impl<T> AsRef<[T]> for Blob<T> {
75 fn as_ref(&self) -> &[T] {
76 self.data()
77 }
78}
79
80impl<T> From<Vec<T>> for Blob<T>
81where
82 T: 'static + Send + Sync,
83{
84 fn from(vec: Vec<T>) -> Self {
85 let boxed: Box<[T]> = vec.into();
86 Self::new(Arc::new(boxed))
87 }
88}
89
90static ID_COUNTER: AtomicCounter = AtomicCounter::new(0);
91
92impl<T> Blob<T> {
93 pub fn new(data: Arc<dyn AsRef<[T]> + Send + Sync>) -> Self {
96 Self {
97 data,
98 #[allow(clippy::useless_conversion)] id: ID_COUNTER.fetch_add(1, Ordering::Relaxed).into(),
102 }
103 }
104
105 pub fn from_raw_parts(data: Arc<dyn AsRef<[T]> + Send + Sync>, id: u64) -> Self {
111 Self { data, id }
112 }
113
114 #[must_use]
116 pub fn into_raw_parts(self) -> (Arc<dyn AsRef<[T]> + Send + Sync>, u64) {
117 (self.data, self.id)
118 }
119
120 #[must_use]
122 pub fn len(&self) -> usize {
123 self.data().len()
124 }
125
126 #[must_use]
128 pub fn is_empty(&self) -> bool {
129 self.len() == 0
130 }
131
132 #[must_use]
134 pub fn data(&self) -> &[T] {
135 self.data.as_ref().as_ref()
136 }
137
138 #[must_use]
140 pub fn id(&self) -> u64 {
141 self.id
142 }
143
144 #[must_use]
146 pub fn strong_count(&self) -> usize {
147 Arc::strong_count(&self.data)
148 }
149
150 #[must_use]
152 pub fn downgrade(&self) -> WeakBlob<T> {
153 WeakBlob {
154 data: Arc::downgrade(&self.data),
155 id: self.id,
156 }
157 }
158}
159
160#[derive(Debug)]
162pub struct WeakBlob<T> {
163 data: Weak<dyn AsRef<[T]> + Send + Sync>,
164 id: u64,
165}
166
167impl<T> Clone for WeakBlob<T> {
168 fn clone(&self) -> Self {
169 Self {
170 data: Weak::clone(&self.data),
171 id: self.id,
172 }
173 }
174}
175
176impl<T> WeakBlob<T> {
177 #[must_use]
179 pub fn id(&self) -> u64 {
180 self.id
181 }
182
183 #[must_use]
186 pub fn upgrade(&self) -> Option<Blob<T>> {
187 Some(Blob {
188 data: self.data.upgrade()?,
189 id: self.id,
190 })
191 }
192}