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