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