ab_core_primitives/pieces/
piece.rs1use crate::pieces::InnerPiece;
2use crate::pieces::cow_bytes::CowBytes;
3use ab_io_type::trivial_type::TrivialType;
4#[cfg(any(feature = "scale-codec", feature = "serde"))]
5use alloc::format;
6use alloc::vec::Vec;
7use bytes::{Bytes, BytesMut};
8use core::ops::{Deref, DerefMut};
9#[cfg(feature = "scale-codec")]
10use parity_scale_codec::{Decode, Encode, EncodeLike, Input, Output};
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Deserializer, Serialize, Serializer};
13
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22pub struct Piece(pub(super) CowBytes);
23
24#[cfg(feature = "scale-codec")]
25impl Encode for Piece {
26 #[inline]
27 fn size_hint(&self) -> usize {
28 self.as_ref().size_hint()
29 }
30
31 #[inline]
32 fn encode_to<O>(&self, dest: &mut O)
33 where
34 O: Output + ?Sized,
35 {
36 self.as_ref().encode_to(dest);
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>(&self, f: F) -> R
46 where
47 F: FnOnce(&[u8]) -> R,
48 {
49 self.as_ref().using_encoded(f)
50 }
51}
52
53#[cfg(feature = "scale-codec")]
54impl EncodeLike for Piece {}
55
56#[cfg(feature = "scale-codec")]
57impl Decode for Piece {
58 fn decode<I>(input: &mut I) -> Result<Self, parity_scale_codec::Error>
59 where
60 I: Input,
61 {
62 let bytes =
63 Bytes::decode(input).map_err(|error| error.chain("Could not decode `Piece`"))?;
64
65 if bytes.len() != Self::SIZE {
66 return Err(
67 parity_scale_codec::Error::from("Incorrect Piece length").chain(format!(
68 "Expected {} bytes, found {} bytes",
69 Self::SIZE,
70 bytes.len()
71 )),
72 );
73 }
74
75 Ok(Piece(CowBytes::Shared(bytes)))
76 }
77}
78
79#[cfg(feature = "serde")]
80impl Serialize for Piece {
81 #[inline]
82 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
83 where
84 S: Serializer,
85 {
86 let bytes = match &self.0 {
87 CowBytes::Shared(bytes) => bytes.as_ref(),
88 CowBytes::Owned(bytes) => bytes.as_ref(),
89 };
90
91 if serializer.is_human_readable() {
92 hex::serde::serialize(bytes, serializer)
93 } else {
94 bytes.serialize(serializer)
95 }
96 }
97}
98
99#[cfg(feature = "serde")]
100impl<'de> Deserialize<'de> for Piece {
101 #[inline]
102 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
103 where
104 D: Deserializer<'de>,
105 {
106 let bytes = if deserializer.is_human_readable() {
107 hex::serde::deserialize::<_, Vec<u8>>(deserializer).and_then(|bytes| {
108 if bytes.len() == Piece::SIZE {
109 Ok(Bytes::from(bytes))
110 } else {
111 Err(serde::de::Error::invalid_length(
112 bytes.len(),
113 &format!("Expected {} bytes", Piece::SIZE).as_str(),
114 ))
115 }
116 })?
117 } else {
118 Bytes::deserialize(deserializer)?
119 };
120
121 Ok(Piece(CowBytes::Shared(bytes)))
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}