Skip to content

Commit

Permalink
Added derive for Serde as well. (#2586)
Browse files Browse the repository at this point in the history
  • Loading branch information
orizi committed Mar 26, 2023
1 parent 5ee71d2 commit bc1ebcb
Show file tree
Hide file tree
Showing 8 changed files with 1,750 additions and 1,679 deletions.
2 changes: 1 addition & 1 deletion corelib/src/integer.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ impl U64RemEq of RemEq::<u64> {
}
}

#[derive(Copy, Drop, PartialEq)]
#[derive(Copy, Drop, PartialEq, Serde)]
struct u256 {
low: u128,
high: u128,
Expand Down
1 change: 1 addition & 0 deletions corelib/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ use integer::U256SubEq;
use integer::U256MulEq;
use integer::U256PartialOrd;
use integer::u256PartialEq;
use integer::u256Serde;
use integer::U256BitAnd;
use integer::U256BitOr;
use integer::U256BitXor;
Expand Down
15 changes: 0 additions & 15 deletions corelib/src/serde.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,6 @@ impl U128Serde of Serde::<u128> {
}
}

impl U256Serde of Serde::<u256> {
fn serialize(ref serialized: Array<felt252>, input: u256) {
Serde::<u128>::serialize(ref serialized, input.low);
Serde::<u128>::serialize(ref serialized, input.high);
}
fn deserialize(ref serialized: Span<felt252>) -> Option<u256> {
Option::Some(
u256 {
low: Serde::<u128>::deserialize(ref serialized)?,
high: Serde::<u128>::deserialize(ref serialized)?,
}
)
}
}

impl ArraySerde<T, impl TSerde: Serde::<T>, impl TDrop: Drop::<T>> of Serde::<Array::<T>> {
fn serialize(ref serialized: Array<felt252>, mut input: Array<T>) {
Serde::<usize>::serialize(ref serialized, input.len());
Expand Down
67 changes: 62 additions & 5 deletions crates/cairo-lang-plugins/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,16 @@ fn generate_derive_code_for_type(
"PartialEq" if !matches!(extra_info, ExtraInfo::Extern) => {
impls.push(get_partial_eq_impl(&name, &extra_info))
}
"Clone" | "PartialEq" => diagnostics.push(PluginDiagnostic {
stable_ptr: expr.stable_ptr().untyped(),
message: "Unsupported trait for derive for extern types."
.into(),
}),
"Serde" if !matches!(extra_info, ExtraInfo::Extern) => {
impls.push(get_serde_impl(&name, &extra_info))
}
"Clone" | "PartialEq" | "Serde" => {
diagnostics.push(PluginDiagnostic {
stable_ptr: expr.stable_ptr().untyped(),
message: "Unsupported trait for derive for extern types."
.into(),
})
}
_ => diagnostics.push(PluginDiagnostic {
stable_ptr: expr.stable_ptr().untyped(),
message: "Unsupported trait for derive.".into(),
Expand Down Expand Up @@ -212,6 +217,58 @@ fn get_partial_eq_impl(name: &str, extra_info: &ExtraInfo) -> String {
}
}

fn get_serde_impl(name: &str, extra_info: &ExtraInfo) -> String {
match extra_info {
ExtraInfo::Enum(variants) => {
formatdoc! {"
impl {name}Serde of serde::Serde::<{name}> {{
fn serialize(ref output: array::Array<felt252>, value: {name}) {{
match lhs {{
{}
}}
}}
fn deserialize(ref input: array::Span<felt252>) -> Option<{name}> {{
let idx: felt252 = serde::Serde::deserialize(ref input)?;
Option::Some(
{}
else {{ None }}
)
}}
}}
",
variants.iter().enumerate().map(|(idx, variant)| {
format!(
"{name}::{variant}(x) => serde::Serde::serialize(ref output, ({idx}, x)),",
)
}).join("\n "),
variants.iter().enumerate().map(|(idx, variant)| {
format!(
"if idx == {idx} {{ {name}::{variant}(serde::Serde::deserialize(ref input)?) }}",
)
}).join("\n else "),
}
}
ExtraInfo::Struct(members) => {
formatdoc! {"
impl {name}Serde of serde::Serde::<{name}> {{
fn serialize(ref output: array::Array<felt252>, value: {name}) {{
{}
}}
fn deserialize(ref input: array::Span<felt252>) -> Option<{name}> {{
Option::Some({name} {{
{}
}})
}}
}}
",
members.iter().map(|member| format!("serde::Serde::serialize(ref output, value.{member})")).join(";\n "),
members.iter().map(|member| format!("{member}: serde::Serde::deserialize(ref input)?,")).join("\n "),
}
}
ExtraInfo::Extern => unreachable!(),
}
}

fn get_empty_impl(name: &str, derived_trait: &str) -> String {
format!("impl {name}{derived_trait} of {derived_trait}::<{name}>;\n")
}
36 changes: 32 additions & 4 deletions crates/cairo-lang-plugins/src/test_data/derive
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ struct A{}
#[derive(Copy, Drop)]
struct B{}

#[derive(Clone, PartialEq)]
#[derive(Clone, PartialEq, Serde)]
struct TwoMemberStruct {
a: A,
b: B,
}

#[derive(Clone, PartialEq)]
#[derive(Clone, PartialEq, Serde)]
enum TwoVariantEnum {
First: A,
Second: B,
Expand All @@ -40,7 +40,7 @@ impl BCopy of Copy::<B>;
impl BDrop of Drop::<B>;


#[derive(Clone, PartialEq)]
#[derive(Clone, PartialEq, Serde)]
struct TwoMemberStruct {
a: A,
b: B,
Expand All @@ -66,9 +66,21 @@ impl TwoMemberStructPartialEq of PartialEq::<TwoMemberStruct> {
!(lhs == rhs)
}
}
impl TwoMemberStructSerde of serde::Serde::<TwoMemberStruct> {
fn serialize(ref output: array::Array<felt252>, value: TwoMemberStruct) {
serde::Serde::serialize(ref output, value.a);
serde::Serde::serialize(ref output, value.b)
}
fn deserialize(ref input: array::Span<felt252>) -> Option<TwoMemberStruct> {
Option::Some(TwoMemberStruct {
a: serde::Serde::deserialize(ref input)?,
b: serde::Serde::deserialize(ref input)?,
})
}
}


#[derive(Clone, PartialEq)]
#[derive(Clone, PartialEq, Serde)]
enum TwoVariantEnum {
First: A,
Second: B,
Expand Down Expand Up @@ -100,6 +112,22 @@ impl TwoVariantEnumPartialEq of PartialEq::<TwoVariantEnum> {
!(lhs == rhs)
}
}
impl TwoVariantEnumSerde of serde::Serde::<TwoVariantEnum> {
fn serialize(ref output: array::Array<felt252>, value: TwoVariantEnum) {
match lhs {
TwoVariantEnum::First(x) => serde::Serde::serialize(ref output, (0, x)),
TwoVariantEnum::Second(x) => serde::Serde::serialize(ref output, (1, x)),
}
}
fn deserialize(ref input: array::Span<felt252>) -> Option<TwoVariantEnum> {
let idx: felt252 = serde::Serde::deserialize(ref input)?;
Option::Some(
if idx == 0 { TwoVariantEnum::First(serde::Serde::deserialize(ref input)?) }
else if idx == 1 { TwoVariantEnum::Second(serde::Serde::deserialize(ref input)?) }
else { None }
)
}
}


#[derive(Copy, Drop)]
Expand Down

0 comments on commit bc1ebcb

Please sign in to comment.