Skip to content

Commit fd2299f

Browse files
jbcaroncchudant
andcommitted
Implement compressed binary format for felts
Co-authored-by: cchudant <[email protected]>
1 parent 7b98204 commit fd2299f

File tree

1 file changed

+127
-72
lines changed
  • crates/starknet-types-core/src/felt

1 file changed

+127
-72
lines changed

crates/starknet-types-core/src/felt/mod.rs

+127-72
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,10 @@ mod arithmetic {
909909
mod serde_impl {
910910
use alloc::{format, string::String};
911911
use core::fmt;
912-
use serde::{de, ser::SerializeSeq, Deserialize, Serialize};
912+
use serde::{
913+
de, de::DeserializeSeed, ser::SerializeTuple, Deserialize, Deserializer, Serialize,
914+
Serializer,
915+
};
913916

914917
use super::*;
915918

@@ -925,20 +928,30 @@ mod serde_impl {
925928
} else {
926929
let bytes = self.to_bytes_be();
927930
let first_significant_byte = bytes.iter().position(|&b| b != 0).unwrap_or(31);
931+
932+
struct RestSerialize<'a>(&'a [u8]);
933+
impl<'a> Serialize for RestSerialize<'a> {
934+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
935+
let mut tup = serializer.serialize_tuple(self.0.len())?;
936+
for el in self.0 {
937+
tup.serialize_element(el)?;
938+
}
939+
tup.end()
940+
}
941+
}
942+
928943
if first_significant_byte > 1 {
929944
let len = 32 - first_significant_byte;
930-
let mut seq = serializer.serialize_seq(Some(len + 1))?;
931-
seq.serialize_element(&(len as u8 | COMPRESSED))?;
932-
for b in &bytes[first_significant_byte..] {
933-
seq.serialize_element(b)?;
934-
}
935-
seq.end()
945+
946+
let mut tup = serializer.serialize_tuple(2)?;
947+
tup.serialize_element(&(len as u8 | COMPRESSED))?;
948+
tup.serialize_element(&RestSerialize(&bytes[first_significant_byte..]))?;
949+
tup.end()
936950
} else {
937-
let mut seq = serializer.serialize_seq(Some(32))?;
938-
for b in &bytes {
939-
seq.serialize_element(b)?;
940-
}
941-
seq.end()
951+
let mut tup = serializer.serialize_tuple(2)?;
952+
tup.serialize_element(&bytes[0])?;
953+
tup.serialize_element(&RestSerialize(&bytes[1..]))?;
954+
tup.end()
942955
}
943956
}
944957
}
@@ -952,7 +965,7 @@ mod serde_impl {
952965
if deserializer.is_human_readable() {
953966
deserializer.deserialize_str(FeltVisitor)
954967
} else {
955-
deserializer.deserialize_seq(FeltVisitor)
968+
deserializer.deserialize_tuple(2, FeltVisitor)
956969
}
957970
}
958971
}
@@ -979,32 +992,47 @@ mod serde_impl {
979992
.map_err(de::Error::custom)
980993
}
981994

982-
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
983-
where
984-
A: de::SeqAccess<'de>,
985-
{
995+
fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
996+
struct RestDeserialize<'a>(&'a mut [u8]);
997+
impl<'a, 'de> DeserializeSeed<'de> for RestDeserialize<'a> {
998+
type Value = ();
999+
fn deserialize<D: Deserializer<'de>>(
1000+
self,
1001+
deserializer: D,
1002+
) -> Result<Self::Value, D::Error> {
1003+
struct RestDeserializeVisitor<'a>(&'a mut [u8]);
1004+
impl<'a, 'de> de::Visitor<'de> for RestDeserializeVisitor<'a> {
1005+
type Value = ();
1006+
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1007+
formatter.write_str("Failed to deserialize felt")
1008+
}
1009+
fn visit_seq<A: de::SeqAccess<'de>>(
1010+
self,
1011+
mut seq: A,
1012+
) -> Result<Self::Value, A::Error> {
1013+
for (i, el) in self.0.iter_mut().enumerate() {
1014+
*el = seq
1015+
.next_element::<u8>()?
1016+
.ok_or(de::Error::invalid_length(i + 1, &"more bytes"))?;
1017+
}
1018+
Ok(())
1019+
}
1020+
}
1021+
deserializer.deserialize_tuple(self.0.len(), RestDeserializeVisitor(self.0))
1022+
}
1023+
}
1024+
9861025
let mut bytes = [0u8; 32];
9871026
let first = seq
9881027
.next_element::<u8>()?
989-
.ok_or(de::Error::invalid_length(0, &"more bytes"))?;
1028+
.ok_or(de::Error::invalid_length(1, &"tagging byte"))?;
1029+
9901030
if first & COMPRESSED != 0 {
9911031
let len = first & !COMPRESSED;
992-
for (i, byte) in bytes.iter_mut().skip(32 - len as usize).enumerate() {
993-
if let Some(b) = seq.next_element()? {
994-
*byte = b;
995-
} else {
996-
return Err(de::Error::invalid_length(i + 1, &"more bytes"));
997-
}
998-
}
1032+
seq.next_element_seed(RestDeserialize(&mut bytes[32 - len as usize..]))?;
9991033
} else {
10001034
bytes[0] = first;
1001-
for byte in bytes.iter_mut().skip(1) {
1002-
if let Some(b) = seq.next_element()? {
1003-
*byte = b;
1004-
} else {
1005-
return Err(de::Error::invalid_length(0, &"32 bytes"));
1006-
}
1007-
}
1035+
seq.next_element_seed(RestDeserialize(&mut bytes[1..]))?;
10081036
}
10091037
Ok(Felt::from_bytes_be(&bytes))
10101038
}
@@ -1136,9 +1164,7 @@ mod test {
11361164
use proptest::prelude::*;
11371165
use regex::Regex;
11381166
#[cfg(feature = "serde")]
1139-
use serde_test::{
1140-
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, Compact, Configure, Token,
1141-
};
1167+
use serde_test::{assert_de_tokens, assert_ser_tokens, Configure, Token};
11421168

11431169
#[test]
11441170
fn test_debug_format() {
@@ -1685,46 +1711,76 @@ mod test {
16851711
assert_de_tokens(
16861712
&Felt::ZERO.compact(),
16871713
&[
1688-
Token::Seq { len: Some(2) },
1714+
Token::Tuple { len: 2 },
16891715
Token::U8(1 | 0x80),
1716+
Token::Tuple { len: 1 },
16901717
Token::U8(0),
1691-
Token::SeqEnd,
1692-
],
1693-
);
1694-
assert_de_tokens(
1695-
&Felt::ONE.compact(),
1696-
&[
1697-
Token::Seq { len: Some(2) },
1698-
Token::U8(1 | 0x80),
1699-
Token::U8(1),
1700-
Token::SeqEnd,
1718+
Token::TupleEnd,
1719+
Token::TupleEnd,
17011720
],
17021721
);
17031722
assert_de_tokens(
17041723
&Felt::TWO.compact(),
17051724
&[
1706-
Token::Seq { len: Some(2) },
1725+
Token::Tuple { len: 2 },
17071726
Token::U8(1 | 0x80),
1727+
Token::Tuple { len: 1 },
17081728
Token::U8(2),
1709-
Token::SeqEnd,
1729+
Token::TupleEnd,
1730+
Token::TupleEnd,
17101731
],
17111732
);
17121733
assert_de_tokens(
17131734
&Felt::THREE.compact(),
17141735
&[
1715-
Token::Seq { len: Some(2) },
1736+
Token::Tuple { len: 2 },
17161737
Token::U8(1 | 0x80),
1738+
Token::Tuple { len: 1 },
17171739
Token::U8(3),
1718-
Token::SeqEnd,
1740+
Token::TupleEnd,
1741+
Token::TupleEnd,
17191742
],
17201743
);
1721-
assert_de_tokens_error::<Compact<Felt>>(
1744+
assert_de_tokens(
1745+
&Felt::MAX.compact(),
17221746
&[
1723-
Token::Seq { len: Some(1) },
1724-
Token::U8(1 | 0x80),
1725-
Token::SeqEnd,
1747+
Token::Tuple { len: 2 },
1748+
Token::U8(8),
1749+
Token::Tuple { len: 31 },
1750+
Token::U8(0),
1751+
Token::U8(0),
1752+
Token::U8(0),
1753+
Token::U8(0),
1754+
Token::U8(0),
1755+
Token::U8(0),
1756+
Token::U8(17),
1757+
Token::U8(0),
1758+
Token::U8(0),
1759+
Token::U8(0),
1760+
Token::U8(0),
1761+
Token::U8(0),
1762+
Token::U8(0),
1763+
Token::U8(0),
1764+
Token::U8(0),
1765+
Token::U8(0),
1766+
Token::U8(0),
1767+
Token::U8(0),
1768+
Token::U8(0),
1769+
Token::U8(0),
1770+
Token::U8(0),
1771+
Token::U8(0),
1772+
Token::U8(0),
1773+
Token::U8(0),
1774+
Token::U8(0),
1775+
Token::U8(0),
1776+
Token::U8(0),
1777+
Token::U8(0),
1778+
Token::U8(0),
1779+
Token::U8(0),
1780+
Token::U8(0),
1781+
Token::TupleEnd,
1782+
Token::TupleEnd,
17261783
],
1727-
"invalid length 1, expected more bytes",
17281784
);
17291785
}
17301786

@@ -1744,44 +1800,42 @@ mod test {
17441800
assert_ser_tokens(
17451801
&Felt::ZERO.compact(),
17461802
&[
1747-
Token::Seq { len: Some(2) },
1803+
Token::Tuple { len: 2 },
17481804
Token::U8(1 | 0x80),
1805+
Token::Tuple { len: 1 },
17491806
Token::U8(0),
1750-
Token::SeqEnd,
1751-
],
1752-
);
1753-
assert_ser_tokens(
1754-
&Felt::ONE.compact(),
1755-
&[
1756-
Token::Seq { len: Some(2) },
1757-
Token::U8(1 | 0x80),
1758-
Token::U8(1),
1759-
Token::SeqEnd,
1807+
Token::TupleEnd,
1808+
Token::TupleEnd,
17601809
],
17611810
);
17621811
assert_ser_tokens(
17631812
&Felt::TWO.compact(),
17641813
&[
1765-
Token::Seq { len: Some(2) },
1814+
Token::Tuple { len: 2 },
17661815
Token::U8(1 | 0x80),
1816+
Token::Tuple { len: 1 },
17671817
Token::U8(2),
1768-
Token::SeqEnd,
1818+
Token::TupleEnd,
1819+
Token::TupleEnd,
17691820
],
17701821
);
17711822
assert_ser_tokens(
17721823
&Felt::THREE.compact(),
17731824
&[
1774-
Token::Seq { len: Some(2) },
1825+
Token::Tuple { len: 2 },
17751826
Token::U8(1 | 0x80),
1827+
Token::Tuple { len: 1 },
17761828
Token::U8(3),
1777-
Token::SeqEnd,
1829+
Token::TupleEnd,
1830+
Token::TupleEnd,
17781831
],
17791832
);
17801833
assert_ser_tokens(
17811834
&Felt::MAX.compact(),
17821835
&[
1783-
Token::Seq { len: Some(32) },
1836+
Token::Tuple { len: 2 },
17841837
Token::U8(8),
1838+
Token::Tuple { len: 31 },
17851839
Token::U8(0),
17861840
Token::U8(0),
17871841
Token::U8(0),
@@ -1813,7 +1867,8 @@ mod test {
18131867
Token::U8(0),
18141868
Token::U8(0),
18151869
Token::U8(0),
1816-
Token::SeqEnd,
1870+
Token::TupleEnd,
1871+
Token::TupleEnd,
18171872
],
18181873
);
18191874
}

0 commit comments

Comments
 (0)