ab_core_primitives/pieces/
piece.rs1#[cfg(all(test, feature = "serde"))]
2mod tests;
3
4use crate::pieces::InnerPiece;
5use crate::pieces::cow_bytes::CowBytes;
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()) }
208 }
209}
210
211impl DerefMut for Piece {
212 #[inline]
213 fn deref_mut(&mut self) -> &mut Self::Target {
214 unsafe { InnerPiece::from_bytes_mut_unchecked(self.as_mut()) }
216 }
217}
218
219impl AsRef<[u8]> for Piece {
220 #[inline]
221 fn as_ref(&self) -> &[u8] {
222 self.0.as_ref()
223 }
224}
225
226impl AsMut<[u8]> for Piece {
227 #[inline]
228 fn as_mut(&mut self) -> &mut [u8] {
229 self.0.as_mut()
230 }
231}
232
233impl Piece {
234 pub const SIZE: usize = InnerPiece::SIZE;
236
237 pub fn to_shared(self) -> Self {
243 Self(match self.0 {
244 CowBytes::Shared(bytes) => CowBytes::Shared(bytes),
245 CowBytes::Owned(bytes) => CowBytes::Shared(bytes.freeze()),
246 })
247 }
248}