diff --git a/Cargo.lock b/Cargo.lock index 82cae536..b4f19d49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -263,6 +263,41 @@ dependencies = [ "syn", ] +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "derivation-path" version = "0.2.0" @@ -479,6 +514,12 @@ dependencies = [ "digest", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "indexmap" version = "2.7.1" @@ -695,6 +736,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "pastey" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" + [[package]] name = "pbkdf2" version = "0.11.0" @@ -754,9 +801,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -772,9 +819,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.41" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -1076,7 +1123,7 @@ dependencies = [ "curve25519-dalek", "solana-define-syscall 2.3.0", "subtle", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1466,7 +1513,7 @@ dependencies = [ "solana-signature", "solana-signer", "subtle", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasm-bindgen", "zeroize", ] @@ -1536,7 +1583,7 @@ dependencies = [ "quote", "sha2", "syn", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1577,7 +1624,10 @@ dependencies = [ "solana-program-option", "solana-pubkey", "solana-zk-sdk", - "thiserror 2.0.17", + "spl-pod 0.7.1", + "test-case", + "thiserror 2.0.18", + "wincode", ] [[package]] @@ -1596,7 +1646,7 @@ dependencies = [ "solana-program-option", "solana-pubkey", "solana-zk-sdk", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1613,7 +1663,7 @@ dependencies = [ "solana-sha256-hasher", "solana-sysvar", "spl-program-error-derive", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1645,7 +1695,7 @@ dependencies = [ "spl-pod 0.7.1", "spl-program-error", "spl-type-length-value 0.9.0", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", ] @@ -1674,7 +1724,7 @@ dependencies = [ "spl-token-group-interface", "spl-token-metadata-interface", "spl-type-length-value 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1694,7 +1744,7 @@ dependencies = [ "solana-sdk-ids", "solana-zk-sdk", "spl-pod 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1705,7 +1755,7 @@ checksum = "f63a2b41095945dc15274b924b21ccae9b3ec9dc2fdd43dbc08de8c33bbcd915" dependencies = [ "curve25519-dalek", "solana-zk-sdk", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1723,7 +1773,7 @@ dependencies = [ "solana-pubkey", "spl-discriminator 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "spl-pod 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1743,7 +1793,7 @@ dependencies = [ "solana-program-pack", "solana-pubkey", "solana-sdk-ids", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1762,7 +1812,7 @@ dependencies = [ "spl-discriminator 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "spl-pod 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "spl-type-length-value 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1779,7 +1829,7 @@ dependencies = [ "spl-discriminator 0.5.1", "spl-pod 0.7.1", "spl-type-length-value-derive", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1797,7 +1847,7 @@ dependencies = [ "solana-program-error", "spl-discriminator 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "spl-pod 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -1819,6 +1869,12 @@ dependencies = [ "spl-type-length-value 0.9.0", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.6.1" @@ -1827,9 +1883,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.106" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -1880,11 +1936,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -1900,9 +1956,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -2078,6 +2134,31 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wincode" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "466e67917609b2d40a838a5b972d1a6237c9749600cb8de8f65559b90d48485b" +dependencies = [ + "pastey", + "proc-macro2", + "quote", + "thiserror 2.0.18", + "wincode-derive", +] + +[[package]] +name = "wincode-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26a7a568eda854acc9945ed136a9d50b8c6d31911584624958808ae96eee3912" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/pod/Cargo.toml b/pod/Cargo.toml index 543c622f..312164ae 100644 --- a/pod/Cargo.toml +++ b/pod/Cargo.toml @@ -10,6 +10,7 @@ edition = "2021" [features] serde-traits = ["dep:serde"] borsh = ["dep:borsh", "solana-pubkey/borsh"] +wincode = ["dep:wincode"] [dependencies] borsh = { version = "1.5.7", features = ["derive", "unstable__schema"], optional = true } @@ -19,6 +20,7 @@ num-derive = "0.4" num_enum = "0.7" num-traits = "0.2" serde = { version = "1.0.228", optional = true } +wincode = { version = "0.4.4", features = ["derive"], optional = true } solana-program-error = "3.0.0" solana-program-option = "3.0.0" solana-pubkey = "3.0.0" @@ -26,8 +28,10 @@ solana-zk-sdk = "4.0.0" thiserror = "2.0" [dev-dependencies] -serde_json = "1.0.145" base64 = { version = "0.22.1" } +serde_json = "1.0.145" +spl-pod = { path = ".", features = ["wincode"] } +test-case = "3.3.1" [lib] crate-type = ["lib"] diff --git a/pod/src/primitives.rs b/pod/src/primitives.rs index 5eb694ed..23953b2f 100644 --- a/pod/src/primitives.rs +++ b/pod/src/primitives.rs @@ -4,8 +4,12 @@ use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use bytemuck_derive::{Pod, Zeroable}; #[cfg(feature = "serde-traits")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "wincode")] +use wincode::{SchemaRead, SchemaWrite}; /// The standard `bool` is not a `Pod`, define a replacement that is +#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))] +#[cfg_attr(feature = "wincode", wincode(assert_zero_copy))] #[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-traits", serde(from = "bool", into = "bool"))] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] @@ -68,6 +72,8 @@ macro_rules! impl_int_conversion { } /// `u16` type that can be used in `Pod`s +#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))] +#[cfg_attr(feature = "wincode", wincode(assert_zero_copy))] #[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-traits", serde(from = "u16", into = "u16"))] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] @@ -76,6 +82,8 @@ pub struct PodU16(pub [u8; 2]); impl_int_conversion!(PodU16, u16); /// `i16` type that can be used in Pods +#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))] +#[cfg_attr(feature = "wincode", wincode(assert_zero_copy))] #[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-traits", serde(from = "i16", into = "i16"))] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] @@ -84,6 +92,8 @@ pub struct PodI16(pub [u8; 2]); impl_int_conversion!(PodI16, i16); /// `u32` type that can be used in `Pod`s +#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))] +#[cfg_attr(feature = "wincode", wincode(assert_zero_copy))] #[cfg_attr( feature = "borsh", derive(BorshDeserialize, BorshSerialize, BorshSchema) @@ -96,6 +106,8 @@ pub struct PodU32(pub [u8; 4]); impl_int_conversion!(PodU32, u32); /// `u64` type that can be used in Pods +#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))] +#[cfg_attr(feature = "wincode", wincode(assert_zero_copy))] #[cfg_attr( feature = "borsh", derive(BorshDeserialize, BorshSerialize, BorshSchema) @@ -108,6 +120,8 @@ pub struct PodU64(pub [u8; 8]); impl_int_conversion!(PodU64, u64); /// `i64` type that can be used in Pods +#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))] +#[cfg_attr(feature = "wincode", wincode(assert_zero_copy))] #[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-traits", serde(from = "i64", into = "i64"))] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] @@ -116,6 +130,8 @@ pub struct PodI64([u8; 8]); impl_int_conversion!(PodI64, i64); /// `u128` type that can be used in Pods +#[cfg_attr(feature = "wincode", derive(SchemaRead, SchemaWrite))] +#[cfg_attr(feature = "wincode", wincode(assert_zero_copy))] #[cfg_attr( feature = "borsh", derive(BorshDeserialize, BorshSerialize, BorshSchema) @@ -266,4 +282,30 @@ mod tests { let deserialized = serde_json::from_str::(&serialized).unwrap(); assert_eq!(pod_u128, deserialized); } + + #[cfg(feature = "wincode")] + mod wincode_tests { + use {super::*, test_case::test_case}; + + #[test_case(PodBool::from_bool(true))] + #[test_case(PodBool::from_bool(false))] + #[test_case(PodU16::from_primitive(u16::MAX))] + #[test_case(PodI16::from_primitive(i16::MIN))] + #[test_case(PodU32::from_primitive(u32::MAX))] + #[test_case(PodU64::from_primitive(u64::MAX))] + #[test_case(PodI64::from_primitive(i64::MIN))] + #[test_case(PodU128::from_primitive(u128::MAX))] + fn wincode_roundtrip< + T: PartialEq + + std::fmt::Debug + + for<'de> wincode::SchemaRead<'de, wincode::config::DefaultConfig, Dst = T> + + wincode::SchemaWrite, + >( + pod: T, + ) { + let bytes = wincode::serialize(&pod).unwrap(); + let deserialized: T = wincode::deserialize(&bytes).unwrap(); + assert_eq!(pod, deserialized); + } + } }