Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

85 changes: 65 additions & 20 deletions wacore/derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,8 @@ fn is_option_type(ty: &syn::Type) -> bool {
// 3. int (enum has #[wire(kind = "int")])
// Unit variants + optional #[wire_fallback] tuple with i32. Each variant
// has #[wire = NUM].
// Emits: code(), From<i32>, Serialize (as i32), Deserialize (from i32).
// Emits: code(), Serialize (as i32), Deserialize (from i32), and either
// From<i32> with a fallback or strict TryFrom<i32> without one.
//
// The wire string/number lives exactly once per variant, in the #[wire = ...]
// attribute. Everything else is derived.
Expand Down Expand Up @@ -1158,15 +1159,6 @@ fn expand_wire_enum_int(
}
}

let Some(fb) = fallback else {
return syn::Error::new_spanned(
name,
"int-mode WireEnum requires a #[wire_fallback] variant like Unknown(i32)",
)
.to_compile_error();
};
let fb_ident = &fb.ident;

let code_arms: Vec<_> = infos
.iter()
.filter(|i| !i.is_fallback)
Expand All @@ -1193,25 +1185,78 @@ fn expand_wire_enum_int(
})
.collect();

let strict_from_arms: Vec<_> = infos
.iter()
.filter(|i| !i.is_fallback)
.map(|i| {
let id = &i.ident;
let VariantWire::Int(n) = i.wire.as_ref().unwrap() else {
unreachable!()
};
let lit = proc_macro2::Literal::i32_suffixed(*n);
quote! { #lit => ::core::result::Result::Ok(#name::#id) }
})
.collect();
Comment thread
coderabbitai[bot] marked this conversation as resolved.

let conversion = if let Some(fallback) = fallback {
let fallback_ident = &fallback.ident;
quote! {
impl ::core::convert::From<i32> for #name {
fn from(code: i32) -> Self {
match code {
#(#from_arms,)*
other => #name::#fallback_ident(other),
}
}
}
}
} else {
quote! {
impl ::core::convert::TryFrom<i32> for #name {
type Error = i32;

fn try_from(code: i32) -> ::core::result::Result<Self, Self::Error> {
match code {
#(#strict_from_arms,)*
other => ::core::result::Result::Err(other),
}
}
}
}
};

let fallback_code_arm = fallback.map(|fallback| {
let fallback_ident = &fallback.ident;
quote! { #name::#fallback_ident(n) => *n, }
});

let deserialize = if fallback.is_some() {
quote! {
::core::result::Result::Ok(<Self as ::core::convert::From<i32>>::from(n))
}
} else {
quote! {
<Self as ::core::convert::TryFrom<i32>>::try_from(n).map_err(|unknown| {
<D::Error as ::serde::de::Error>::custom(::core::format_args!(
"unknown numeric wire code {unknown} for {}",
::core::stringify!(#name),
))
})
}
};

quote! {
impl #name {
/// Numeric wire code for this variant (single source of truth).
pub fn code(&self) -> i32 {
match self {
#(#code_arms,)*
#name::#fb_ident(n) => *n,
#fallback_code_arm
}
}
}

impl ::core::convert::From<i32> for #name {
fn from(code: i32) -> Self {
match code {
#(#from_arms,)*
other => #name::#fb_ident(other),
}
}
}
#conversion

impl ::serde::Serialize for #name {
fn serialize<S: ::serde::Serializer>(
Expand All @@ -1227,7 +1272,7 @@ fn expand_wire_enum_int(
deserializer: D,
) -> ::core::result::Result<Self, D::Error> {
let n = <i32 as ::serde::Deserialize>::deserialize(deserializer)?;
::core::result::Result::Ok(<Self as ::core::convert::From<i32>>::from(n))
#deserialize
}
}
}
Expand Down
1 change: 1 addition & 0 deletions wacore/libsignal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ sha2 = { workspace = true }
subtle = { workspace = true }
thiserror = { workspace = true }
uuid = { workspace = true }
wacore-derive = { workspace = true }
waproto = { workspace = true }
x25519-dalek = { version = "3.0.0-rc.1", features = ["static_secrets"] }

Expand Down
Loading
Loading