Skip to content

Commit ca3691d

Browse files
committed
Change internal implementation of Piece to be boxed PieceArray to remove the need of mem::transmute in some cases
1 parent ac68f3a commit ca3691d

File tree

2 files changed

+115
-35
lines changed

2 files changed

+115
-35
lines changed

crates/subspace-core-primitives/src/pieces.rs

+17-34
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ mod serde;
33

44
#[cfg(feature = "serde")]
55
use ::serde::{Deserialize, Serialize};
6+
use alloc::boxed::Box;
67
use alloc::vec;
78
use alloc::vec::Vec;
9+
use core::array::TryFromSliceError;
810
use core::mem;
911
use core::ops::{Deref, DerefMut};
1012
use derive_more::{AsMut, AsRef, Deref, DerefMut};
@@ -68,74 +70,55 @@ impl AsMut<[u8]> for RecordWitness {
6870
/// Internally piece contains a record and corresponding witness that together with records root of
6971
/// the segment this piece belongs to can be used to verify that a piece belongs to the actual
7072
/// archival history of the blockchain.
71-
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Encode, Decode, TypeInfo)]
73+
#[derive(Debug, Default, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Encode, Decode, TypeInfo)]
7274
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
73-
pub struct Piece(#[cfg_attr(feature = "serde", serde(with = "hex::serde"))] Vec<u8>);
74-
75-
impl Default for Piece {
76-
fn default() -> Self {
77-
Self(vec![0u8; PIECE_SIZE])
78-
}
79-
}
75+
pub struct Piece(Box<PieceArray>);
8076

8177
impl From<Piece> for Vec<u8> {
8278
fn from(piece: Piece) -> Self {
83-
piece.0
79+
piece.0.to_vec()
8480
}
8581
}
86-
8782
impl TryFrom<&[u8]> for Piece {
88-
type Error = &'static str;
83+
type Error = TryFromSliceError;
84+
8985
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
90-
if slice.len() != PIECE_SIZE {
91-
Err("Wrong piece size, expected: 32768")
92-
} else {
93-
Ok(Self(slice.to_vec()))
94-
}
86+
<[u8; PIECE_SIZE]>::try_from(slice).map(|bytes| Piece(Box::new(PieceArray(bytes))))
9587
}
9688
}
9789

9890
impl TryFrom<Vec<u8>> for Piece {
99-
type Error = &'static str;
91+
type Error = TryFromSliceError;
10092

10193
fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
102-
if vec.len() != PIECE_SIZE {
103-
Err("Wrong piece size, expected: 32768")
104-
} else {
105-
Ok(Self(vec))
106-
}
94+
// TODO: Maybe possible to transmute boxed slice into boxed array
95+
Self::try_from(vec.as_slice())
10796
}
10897
}
10998

11099
impl Deref for Piece {
111100
type Target = PieceArray;
112101

113102
fn deref(&self) -> &Self::Target {
114-
let array =
115-
<&[u8; PIECE_SIZE]>::try_from(self.0.as_slice()).expect("Piece has correct size; qed");
116-
// SAFETY: Same memory layout due to `#[repr(transparent)]`
117-
unsafe { mem::transmute(array) }
103+
&self.0
118104
}
119105
}
120106

121107
impl DerefMut for Piece {
122108
fn deref_mut(&mut self) -> &mut Self::Target {
123-
let array = <&mut [u8; PIECE_SIZE]>::try_from(self.0.as_mut_slice())
124-
.expect("Piece has correct size; qed");
125-
// SAFETY: Same memory layout due to `#[repr(transparent)]`
126-
unsafe { mem::transmute(array) }
109+
&mut self.0
127110
}
128111
}
129112

130113
impl AsRef<[u8]> for Piece {
131114
fn as_ref(&self) -> &[u8] {
132-
&self.0
115+
self.0.as_slice()
133116
}
134117
}
135118

136119
impl AsMut<[u8]> for Piece {
137120
fn as_mut(&mut self) -> &mut [u8] {
138-
&mut self.0
121+
self.0.as_mut_slice()
139122
}
140123
}
141124

@@ -187,13 +170,13 @@ impl AsMut<[u8]> for PieceArray {
187170

188171
impl From<&PieceArray> for Piece {
189172
fn from(value: &PieceArray) -> Self {
190-
Piece(value.0.to_vec())
173+
Piece(Box::new(*value))
191174
}
192175
}
193176

194177
impl From<PieceArray> for Piece {
195178
fn from(value: PieceArray) -> Self {
196-
Piece(value.0.to_vec())
179+
Piece(Box::new(value))
197180
}
198181
}
199182

crates/subspace-core-primitives/src/pieces/serde.rs

+98-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,104 @@
1-
use crate::{FlatPieces, PIECE_SIZE};
1+
use crate::{FlatPieces, PieceArray, PIECE_SIZE};
22
use hex::{decode_to_slice, FromHex, FromHexError};
33
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
44

5+
impl FromHex for PieceArray {
6+
type Error = FromHexError;
7+
8+
fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
9+
let hex = hex.as_ref();
10+
if hex.len() % 2 != 0 {
11+
return Err(FromHexError::OddLength);
12+
}
13+
if hex.len() != 2 * PIECE_SIZE {
14+
return Err(FromHexError::InvalidStringLength);
15+
}
16+
17+
let mut out = Self::default();
18+
19+
decode_to_slice(hex, out.as_mut_slice())?;
20+
21+
Ok(out)
22+
}
23+
}
24+
25+
impl Serialize for PieceArray {
26+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
27+
where
28+
S: Serializer,
29+
{
30+
Serializer::serialize_newtype_struct(serializer, "PieceArray", {
31+
struct SerializeWith<'a> {
32+
values: &'a [u8],
33+
}
34+
impl<'a> Serialize for SerializeWith<'a> {
35+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36+
where
37+
S: Serializer,
38+
{
39+
hex::serde::serialize(self.values, serializer)
40+
}
41+
}
42+
&SerializeWith {
43+
values: self.as_ref(),
44+
}
45+
})
46+
}
47+
}
48+
49+
impl<'de> Deserialize<'de> for PieceArray {
50+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
51+
where
52+
D: Deserializer<'de>,
53+
{
54+
struct Visitor;
55+
56+
impl<'de> de::Visitor<'de> for Visitor {
57+
type Value = PieceArray;
58+
59+
fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60+
formatter.write_str("tuple struct PieceArray")
61+
}
62+
63+
#[inline]
64+
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
65+
where
66+
D: Deserializer<'de>,
67+
{
68+
hex::serde::deserialize(deserializer)
69+
}
70+
71+
#[inline]
72+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
73+
where
74+
A: de::SeqAccess<'de>,
75+
{
76+
struct DeserializeWith {
77+
value: PieceArray,
78+
}
79+
impl<'de> Deserialize<'de> for DeserializeWith {
80+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
81+
where
82+
D: Deserializer<'de>,
83+
{
84+
Ok(DeserializeWith {
85+
value: hex::serde::deserialize(deserializer)?,
86+
})
87+
}
88+
}
89+
90+
de::SeqAccess::next_element::<DeserializeWith>(&mut seq)?
91+
.map(|wrap| wrap.value)
92+
.ok_or(de::Error::invalid_length(
93+
0usize,
94+
&"tuple struct PieceArray with 1 element",
95+
))
96+
}
97+
}
98+
Deserializer::deserialize_newtype_struct(deserializer, "PieceArray", Visitor)
99+
}
100+
}
101+
5102
impl FromHex for FlatPieces {
6103
type Error = FromHexError;
7104

0 commit comments

Comments
 (0)