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