ab_core_primitives/pieces/
piece.rs1#[cfg(all(test, feature = "serde"))]
2mod tests;
3
4use crate::pieces::cow_bytes::CowBytes;
5use crate::pieces::{InnerPiece, PieceHeader, Record};
6use ab_io_type::trivial_type::TrivialType;
7#[cfg(any(feature = "scale-codec", feature = "serde"))]
8use alloc::format;
9use alloc::vec::Vec;
10use bytes::{Bytes, BytesMut};
11use core::ops::{Deref, DerefMut};
12#[cfg(feature = "scale-codec")]
13use parity_scale_codec::{Decode, Encode, EncodeLike, Input, Output};
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Deserializer, Serialize, Serializer};
16
17#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25pub struct Piece(pub(super) CowBytes);
26
27#[cfg(feature = "scale-codec")]
28impl Encode for Piece {
29 #[inline]
30 fn size_hint(&self) -> usize {
31 self.as_ref().size_hint()
32 }
33
34 #[inline]
35 fn encode_to<O>(&self, dest: &mut O)
36 where
37 O: Output + ?Sized,
38 {
39 self.as_ref().encode_to(dest);
40 }
41
42 #[inline]
43 fn encode(&self) -> Vec<u8> {
44 self.as_ref().encode()
45 }
46
47 #[inline]
48 fn using_encoded<R, F>(&self, f: F) -> R
49 where
50 F: FnOnce(&[u8]) -> R,
51 {
52 self.as_ref().using_encoded(f)
53 }
54}
55
56#[cfg(feature = "scale-codec")]
57impl EncodeLike for Piece {}
58
59#[cfg(feature = "scale-codec")]
60impl Decode for Piece {
61 fn decode<I>(input: &mut I) -> Result<Self, parity_scale_codec::Error>
62 where
63 I: Input,
64 {
65 let bytes =
66 Bytes::decode(input).map_err(|error| error.chain("Could not decode `Piece`"))?;
67
68 if bytes.len() != Self::SIZE {
69 return Err(
70 parity_scale_codec::Error::from("Incorrect Piece length").chain(format!(
71 "Expected {} bytes, found {} bytes",
72 Self::SIZE,
73 bytes.len()
74 )),
75 );
76 }
77
78 Ok(Piece(CowBytes::Shared(bytes)))
79 }
80}
81
82#[cfg(feature = "serde")]
83impl Serialize for Piece {
84 #[inline]
85 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86 where
87 S: Serializer,
88 {
89 let bytes = match &self.0 {
90 CowBytes::Shared(bytes) => bytes.as_ref(),
91 CowBytes::Owned(bytes) => bytes.as_ref(),
92 };
93
94 if serializer.is_human_readable() {
95 hex::serde::serialize(bytes, serializer)
96 } else {
97 bytes.serialize(serializer)
98 }
99 }
100}
101
102#[cfg(feature = "serde")]
103impl<'de> Deserialize<'de> for Piece {
104 #[inline]
105 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
106 where
107 D: Deserializer<'de>,
108 {
109 let bytes = if deserializer.is_human_readable() {
110 Bytes::from(hex::serde::deserialize::<_, Vec<u8>>(deserializer)?)
111 } else {
112 Bytes::deserialize(deserializer)?
113 };
114 let length = bytes.len();
115
116 Piece::try_from(bytes).map_err(|()| {
117 serde::de::Error::invalid_length(
118 length,
119 &format!("Expected {} bytes", Piece::SIZE).as_str(),
120 )
121 })
122 }
123}
124
125impl Default for Piece {
126 #[inline]
127 fn default() -> Self {
128 Self(CowBytes::Owned(BytesMut::zeroed(Self::SIZE)))
129 }
130}
131
132impl From<Piece> for Vec<u8> {
133 #[inline]
134 fn from(piece: Piece) -> Self {
135 match piece.0 {
136 CowBytes::Shared(bytes) => bytes.to_vec(),
137 CowBytes::Owned(bytes) => Vec::from(bytes),
138 }
139 }
140}
141
142impl TryFrom<&[u8]> for Piece {
143 type Error = ();
144
145 #[inline]
146 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
147 if slice.len() != Self::SIZE {
148 return Err(());
149 }
150
151 Ok(Self(CowBytes::Shared(Bytes::copy_from_slice(slice))))
152 }
153}
154
155impl TryFrom<Vec<u8>> for Piece {
156 type Error = ();
157
158 #[inline]
159 fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
160 if vec.len() != Self::SIZE {
161 return Err(());
162 }
163
164 Ok(Self(CowBytes::Shared(Bytes::from(vec))))
165 }
166}
167
168impl TryFrom<Bytes> for Piece {
169 type Error = ();
170
171 #[inline]
172 fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
173 if bytes.len() != Self::SIZE {
174 return Err(());
175 }
176
177 Ok(Self(CowBytes::Shared(bytes)))
178 }
179}
180
181impl TryFrom<BytesMut> for Piece {
182 type Error = ();
183
184 #[inline]
185 fn try_from(bytes: BytesMut) -> Result<Self, Self::Error> {
186 if bytes.len() != Self::SIZE {
187 return Err(());
188 }
189
190 Ok(Self(CowBytes::Owned(bytes)))
191 }
192}
193
194impl From<&InnerPiece> for Piece {
195 #[inline]
196 fn from(value: &InnerPiece) -> Self {
197 Self(CowBytes::Shared(Bytes::copy_from_slice(value.as_bytes())))
198 }
199}
200
201impl Deref for Piece {
202 type Target = InnerPiece;
203
204 #[inline]
205 fn deref(&self) -> &Self::Target {
206 unsafe { InnerPiece::from_bytes_unchecked(self.as_ref()) }
210 }
211}
212
213impl DerefMut for Piece {
214 #[inline]
215 fn deref_mut(&mut self) -> &mut Self::Target {
216 unsafe { InnerPiece::from_bytes_mut_unchecked(self.as_mut()) }
220 }
221}
222
223impl AsRef<[u8]> for Piece {
224 #[inline]
225 fn as_ref(&self) -> &[u8] {
226 self.0.as_ref()
227 }
228}
229
230impl AsMut<[u8]> for Piece {
231 #[inline]
232 fn as_mut(&mut self) -> &mut [u8] {
233 self.0.as_mut()
234 }
235}
236
237impl Piece {
238 pub const SIZE: usize = InnerPiece::SIZE;
240
241 pub fn from_parts(header: &PieceHeader, record: &Record) -> Self {
246 let mut bytes = BytesMut::with_capacity(Self::SIZE);
247 let inner_piece = bytes.spare_capacity_mut().as_mut_ptr().cast::<InnerPiece>();
248 unsafe {
251 (&raw mut (*inner_piece).header).write(*header);
252 (&raw mut (*inner_piece).record).copy_from_nonoverlapping(record, 1);
253 bytes.set_len(Self::SIZE);
254 }
255
256 Self(CowBytes::Shared(bytes.freeze()))
257 }
258
259 pub fn to_shared(self) -> Self {
265 Self(match self.0 {
266 CowBytes::Shared(bytes) => CowBytes::Shared(bytes),
267 CowBytes::Owned(bytes) => CowBytes::Shared(bytes.freeze()),
268 })
269 }
270}