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