Created
June 26, 2024 19:00
-
-
Save cchudant/9bbb025c60a9fe23ca56b895fdcff13c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use core::fmt; | |
use serde::de::DeserializeSeed; | |
use serde::ser::SerializeTuple; | |
use serde::Deserializer; | |
use serde::Serializer; | |
use serde::{de, Deserialize, Serialize}; | |
const COMPRESSED: u8 = 0b1000_0000; | |
#[derive(PartialEq, Debug, Copy, Clone)] | |
struct Felt([u8; 32]); | |
impl Serialize for Felt { | |
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { | |
if serializer.is_human_readable() { | |
todo!() | |
//serializer.serialize_str(&format!("{:#x}", self)) | |
} else { | |
let bytes = self.0; | |
let first_significant_byte = bytes.iter().position(|&b| b != 0).unwrap_or(31); | |
struct RestSerialize<'a>(&'a [u8]); | |
impl<'a> Serialize for RestSerialize<'a> { | |
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { | |
let mut tup = serializer.serialize_tuple(self.0.len())?; | |
for el in self.0 { | |
tup.serialize_element(el)?; | |
} | |
tup.end() | |
} | |
} | |
if first_significant_byte > 1 { | |
let len = 32 - first_significant_byte; | |
let mut tup = serializer.serialize_tuple(2)?; | |
tup.serialize_element(&(len as u8 | COMPRESSED))?; | |
tup.serialize_element(&RestSerialize(&bytes[first_significant_byte..]))?; | |
tup.end() | |
} else { | |
let mut tup = serializer.serialize_tuple(2)?; | |
tup.serialize_element(&bytes[0])?; | |
tup.serialize_element(&RestSerialize(&bytes[1..]))?; | |
tup.end() | |
} | |
} | |
} | |
} | |
impl<'de> Deserialize<'de> for Felt { | |
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { | |
struct FeltVisitor; | |
impl<'de> de::Visitor<'de> for FeltVisitor { | |
type Value = Felt; | |
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { | |
formatter.write_str("Failed to deserialize felt") | |
} | |
fn visit_str<E: de::Error>(self, _value: &str) -> Result<Self::Value, E> { | |
// Strip the '0x' prefix from the encoded hex string | |
// value | |
// .strip_prefix("0x") | |
// .and_then(|v| FieldElement::<Stark252PrimeField>::from_hex(v).ok()) | |
// .map(Felt) | |
// .ok_or(String::from("Expected hex string to be prefixed by '0x'")) | |
// .map_err(de::Error::custom) | |
todo!() | |
} | |
fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> { | |
struct RestDeserialize<'a>(&'a mut [u8]); | |
impl<'a, 'de> DeserializeSeed<'de> for RestDeserialize<'a> { | |
type Value = (); | |
fn deserialize<D: Deserializer<'de>>( | |
self, | |
deserializer: D, | |
) -> Result<Self::Value, D::Error> { | |
struct RestDeserializeVisitor<'a>(&'a mut [u8]); | |
impl<'a, 'de> de::Visitor<'de> for RestDeserializeVisitor<'a> { | |
type Value = (); | |
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { | |
formatter.write_str("Failed to deserialize felt") | |
} | |
fn visit_seq<A: de::SeqAccess<'de>>( | |
self, | |
mut seq: A, | |
) -> Result<Self::Value, A::Error> { | |
for (i, el) in self.0.iter_mut().enumerate() { | |
*el = seq | |
.next_element::<u8>()? | |
.ok_or(de::Error::invalid_length(i + 1, &"more bytes"))?; | |
} | |
Ok(()) | |
} | |
} | |
deserializer.deserialize_tuple(self.0.len(), RestDeserializeVisitor(self.0)) | |
} | |
} | |
let mut bytes = [0u8; 32]; | |
let first = seq | |
.next_element::<u8>()? | |
.ok_or(de::Error::invalid_length(1, &"tagging byte"))?; | |
if first & COMPRESSED != 0 { | |
let len = first & !COMPRESSED; | |
seq.next_element_seed(RestDeserialize(&mut bytes[32 - len as usize..]))?; | |
} else { | |
bytes[0] = first; | |
seq.next_element_seed(RestDeserialize(&mut bytes[1..]))?; | |
} | |
Ok(Felt(bytes)) | |
} | |
} | |
if deserializer.is_human_readable() { | |
deserializer.deserialize_str(FeltVisitor) | |
} else { | |
deserializer.deserialize_tuple(2, FeltVisitor) // deserialize tuple uses visit_seq in serde | |
} | |
} | |
} | |
fn main() { | |
let mut bytes = [0; 32]; | |
for i in 0..32 { | |
bytes[32 - 1 - i] = 1; | |
let felt = Felt(bytes); | |
let bytes = bincode::serialize(&felt).unwrap(); | |
println!("{:?} => {} bytes", felt.0, bytes.len()); | |
let other = bincode::deserialize(&bytes).unwrap(); | |
assert_eq!(felt, other); | |
#[derive(Serialize, Deserialize, Debug, PartialEq)] | |
struct WithOtherFields { | |
a: String, | |
b: u32, | |
c: Felt, | |
u: u32, | |
d: Felt, | |
y: String, | |
e: Felt, | |
} | |
let struct_ = WithOtherFields { | |
a: "hello world".into(), | |
b: 446, | |
c: felt, | |
u: 8092, | |
d: felt, | |
y: "hii".into(), | |
e: felt, | |
}; | |
let bytes = bincode::serialize(&struct_).unwrap(); | |
let other = bincode::deserialize(&bytes).unwrap(); | |
assert_eq!(struct_, other); | |
} | |
} |
Author
cchudant
commented
Jun 26, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment