diff --git a/Cargo.lock b/Cargo.lock index 95c6adb..155dbd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1083,20 +1083,6 @@ dependencies = [ "solana-sha256-hasher", ] -[[package]] -name = "solana-address" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c5d02824391b072dc5cd0aaa85fb0af9784a21d23286a767994d1e8a322131" -dependencies = [ - "borsh", - "bytemuck", - "bytemuck_derive", - "serde", - "serde_derive", - "wincode", -] - [[package]] name = "solana-atomic-u64" version = "3.0.0" @@ -1320,7 +1306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8909d399deb0851aa524420beeb5646b115fd253ef446e35fe4504c904da3941" dependencies = [ "rand 0.8.5", - "solana-address 1.0.0", + "solana-address", ] [[package]] @@ -1645,7 +1631,6 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "solana-address 2.2.0", "solana-program-error", "solana-program-option", "spl-pod 0.7.2", @@ -2169,7 +2154,6 @@ dependencies = [ "proc-macro2", "quote", "thiserror 2.0.18", - "wincode-derive", ] [[package]] diff --git a/pod/Cargo.toml b/pod/Cargo.toml index fdbdc5d..b4ddfed 100644 --- a/pod/Cargo.toml +++ b/pod/Cargo.toml @@ -8,9 +8,9 @@ license = "Apache-2.0" edition = "2021" [features] -bytemuck = ["dep:bytemuck", "dep:bytemuck_derive", "solana-address/bytemuck"] -serde = ["dep:serde", "dep:serde_derive", "solana-address/serde"] -borsh = ["dep:borsh", "solana-address/borsh"] +bytemuck = ["dep:bytemuck", "dep:bytemuck_derive"] +serde = ["dep:serde", "dep:serde_derive"] +borsh = ["dep:borsh"] wincode = ["dep:wincode", "dep:wincode-derive"] [dependencies] @@ -19,7 +19,6 @@ bytemuck = { version = "1.23.2", optional = true } bytemuck_derive = { version = "1.10.1", optional = true } serde = { version = "1.0.228", default-features = false, optional = true, features = ["alloc"] } serde_derive = { version = "1.0.228", optional = true } -solana-address = "2.2.0" solana-program-error = "3.0.0" solana-program-option = "3.0.0" wincode = { version = "0.4.4", default-features = false, optional = true } diff --git a/pod/src/lib.rs b/pod/src/lib.rs index 2509506..b31ae65 100644 --- a/pod/src/lib.rs +++ b/pod/src/lib.rs @@ -12,4 +12,4 @@ pub mod primitives; // Export current sdk types for downstream users building with a different sdk // version -pub use {solana_address, solana_program_error, solana_program_option}; +pub use {solana_program_error, solana_program_option}; diff --git a/pod/src/option.rs b/pod/src/option.rs index 0a080ec..25371ba 100644 --- a/pod/src/option.rs +++ b/pod/src/option.rs @@ -17,11 +17,7 @@ use { alloc::format, borsh::{BorshDeserialize, BorshSchema, BorshSerialize}, }; -use { - solana_address::{Address, ADDRESS_BYTES}, - solana_program_error::ProgramError, - solana_program_option::COption, -}; +use {solana_program_error::ProgramError, solana_program_option::COption}; /// Trait for types that can be `None`. /// @@ -172,11 +168,6 @@ impl TryFrom> for PodOption { } } -/// Implementation of `Nullable` for `Address`. -impl Nullable for Address { - const NONE: Self = Address::new_from_array([0u8; ADDRESS_BYTES]); -} - #[cfg(feature = "serde")] impl Serialize for PodOption where @@ -218,68 +209,96 @@ where mod tests { use super::*; - const ID: Address = Address::new_from_array([8; ADDRESS_BYTES]); + impl Nullable for u64 { + const NONE: Self = 0; + } #[test] fn test_try_from_option() { - let some_address = Some(ID); - assert_eq!(PodOption::try_from(some_address).unwrap(), PodOption(ID)); + let some = Some(8u64); + assert_eq!(PodOption::try_from(some).unwrap(), PodOption::from(8u64)); - let none_address = None; + let none = None; assert_eq!( - PodOption::try_from(none_address).unwrap(), - PodOption::from(Address::NONE) + PodOption::try_from(none).unwrap(), + PodOption::from(u64::NONE) ); - let invalid_option = Some(Address::NONE); + let invalid_option = Some(u64::NONE); let err = PodOption::try_from(invalid_option).unwrap_err(); assert_eq!(err, ProgramError::InvalidArgument); } #[test] - fn test_try_from_coption_reject_some_zero_address() { - let invalid_option = COption::Some(Address::NONE); + fn test_try_from_coption_accepts_some_and_none() { + assert_eq!( + PodOption::try_from(COption::Some(8u64)).unwrap(), + PodOption::from(8u64) + ); + assert_eq!( + PodOption::::try_from(COption::None).unwrap(), + PodOption::from(u64::NONE) + ); + } + + #[test] + fn test_try_from_coption_rejects_some_none_marker() { + let invalid_option = COption::Some(u64::NONE); let err = PodOption::try_from(invalid_option).unwrap_err(); assert_eq!(err, ProgramError::InvalidArgument); } #[test] fn test_from_pod_option() { - let some = PodOption::from(ID); - let none = PodOption::from(Address::NONE); + let some = PodOption::from(8u64); + let none = PodOption::from(u64::NONE); - assert_eq!(Option::
::from(some), Some(ID)); - assert_eq!(Option::
::from(none), None); - assert_eq!(COption::
::from(some), COption::Some(ID)); - assert_eq!(COption::
::from(none), COption::None); + assert_eq!(Option::::from(some), Some(8u64)); + assert_eq!(Option::::from(none), None); + assert_eq!(COption::::from(some), COption::Some(8u64)); + assert_eq!(COption::::from(none), COption::None); } #[test] fn test_default() { - let def = PodOption::
::default(); + let def = PodOption::::default(); assert_eq!(def, None.try_into().unwrap()); } #[test] fn test_copied() { - let some_address = PodOption::from(ID); - assert_eq!(some_address.copied(), Some(ID)); + let some = PodOption::from(8u64); + assert_eq!(some.copied(), Some(8u64)); - let none_address = PodOption::from(Address::NONE); - assert_eq!(none_address.copied(), None); + let none = PodOption::from(u64::NONE); + assert_eq!(none.copied(), None); + } + + #[test] + fn test_nullable_predicates() { + assert!(u64::NONE.is_none()); + assert!(!u64::NONE.is_some()); + assert!(8u64.is_some()); + assert!(!8u64.is_none()); + } + + #[test] + fn test_as_ref() { + let some = PodOption::from(8u64); + assert_eq!(some.as_ref(), Some(&8u64)); + + let none = PodOption::from(u64::NONE); + assert_eq!(none.as_ref(), None); } #[test] fn test_as_mut() { - let mut some = PodOption::from(Address::new_from_array([3; ADDRESS_BYTES])); + let mut some = PodOption::from(3u64); assert!(some.as_mut().is_some()); - *some.as_mut().unwrap() = Address::new_from_array([4; ADDRESS_BYTES]); - assert_eq!( - some.get(), - Some(Address::new_from_array([4; ADDRESS_BYTES])) - ); + *some.as_mut().unwrap() = 4u64; + assert_eq!(some.get(), Some(4u64)); - let mut none = PodOption::from(Address::NONE); + let mut none = PodOption::from(u64::NONE); assert!(none.as_mut().is_none()); } @@ -290,10 +309,6 @@ mod tests { const NONE: Self = Self([0u8; 4]); } - impl Nullable for u64 { - const NONE: Self = 0; - } - #[test] fn test_cloned_with_non_copy_nullable() { let some = PodOption::from(TestNonCopyNullable([1, 2, 3, 4])); @@ -305,27 +320,29 @@ mod tests { #[cfg(feature = "borsh")] mod borsh_tests { - use {super::*, alloc::vec}; + use super::*; #[test] fn test_borsh_roundtrip_and_encoding() { - let some = PodOption::from(Address::new_from_array([1; ADDRESS_BYTES])); - let none = PodOption::from(Address::NONE); + let some = PodOption::from(9u64); + let none = PodOption::from(0u64); let some_bytes = borsh::to_vec(&some).unwrap(); let none_bytes = borsh::to_vec(&none).unwrap(); - assert_eq!(some_bytes, vec![1; ADDRESS_BYTES]); - assert_eq!(none_bytes, vec![0; ADDRESS_BYTES]); + assert_eq!(some_bytes.len(), core::mem::size_of::()); + assert_eq!(none_bytes.len(), core::mem::size_of::()); + assert_eq!(some_bytes.as_slice(), &9u64.to_le_bytes()); + assert_eq!(none_bytes.as_slice(), &0u64.to_le_bytes()); assert_eq!( - borsh::from_slice::>(&some_bytes).unwrap(), + borsh::from_slice::>(&some_bytes).unwrap(), some ); assert_eq!( - borsh::from_slice::>(&none_bytes).unwrap(), + borsh::from_slice::>(&none_bytes).unwrap(), none ); - assert!(borsh::from_slice::>(&[]).is_err()); + assert!(borsh::from_slice::>(&[]).is_err()); } } @@ -363,38 +380,6 @@ mod tests { mod serde_tests { use {super::*, alloc::string::ToString}; - #[test] - fn test_serde_some() { - let some = PodOption::from(Address::new_from_array([1; ADDRESS_BYTES])); - let serialized = serde_json::to_string(&some).unwrap(); - assert_eq!( - &serialized, - "[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]" - ); - let deserialized = serde_json::from_str::>(&serialized).unwrap(); - assert_eq!(some, deserialized); - } - - #[test] - fn test_serde_none() { - let none = PodOption::from(Address::new_from_array([0; ADDRESS_BYTES])); - let serialized = serde_json::to_string(&none).unwrap(); - assert_eq!(&serialized, "null"); - let deserialized = serde_json::from_str::>(&serialized).unwrap(); - assert_eq!(none, deserialized); - } - - #[test] - fn test_serde_reject_zero_address_bytes() { - let zero_bytes = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]"; - assert!(serde_json::from_str::>(zero_bytes).is_err()); - } - - #[test] - fn test_serde_reject_invalid_address_string() { - assert!(serde_json::from_str::>("\"not_an_address\"").is_err()); - } - #[test] fn test_serde_u64_some() { let some = PodOption::from(7u64); @@ -429,51 +414,48 @@ mod tests { mod bytemuck_tests { use { super::*, - crate::bytemuck::{pod_from_bytes, pod_slice_from_bytes}, + crate::bytemuck::{pod_bytes_of, pod_from_bytes, pod_slice_from_bytes}, alloc::vec::Vec, }; #[test] - fn test_pod_option_address() { - let some_address = PodOption::from(ID); - assert_eq!(some_address.get(), Some(ID)); - - let none_address = PodOption::from(Address::default()); - assert_eq!(none_address.get(), None); - - let mut data = Vec::with_capacity(64); - data.extend_from_slice(ID.as_ref()); - data.extend_from_slice(&[0u8; 32]); - - let values = pod_slice_from_bytes::>(&data).unwrap(); - assert_eq!(values[0], PodOption::from(ID)); - assert_eq!(values[1], PodOption::from(Address::default())); + fn test_pod_option_u64() { + let mut data = Vec::with_capacity(2 * core::mem::size_of::()); + data.extend_from_slice(&8u64.to_le_bytes()); + data.extend_from_slice(&0u64.to_le_bytes()); + + let values = pod_slice_from_bytes::>(&data).unwrap(); + assert_eq!(values[0], PodOption::from(8u64)); + assert_eq!(values[1], PodOption::from(0u64)); } #[test] fn test_pod_from_bytes() { + let some = PodOption::from(1u64); assert_eq!( - Option::
::from( - *pod_from_bytes::>(&[1; ADDRESS_BYTES]).unwrap() + Option::::from( + *pod_from_bytes::>(pod_bytes_of(&some)).unwrap() ), - Some(Address::new_from_array([1; ADDRESS_BYTES])), + Some(1u64), ); + + let none = PodOption::from(0u64); assert_eq!( - Option::
::from( - *pod_from_bytes::>(&[0; ADDRESS_BYTES]).unwrap() + Option::::from( + *pod_from_bytes::>(pod_bytes_of(&none)).unwrap() ), None, ); assert_eq!( - pod_from_bytes::>(&[]).unwrap_err(), + pod_from_bytes::>(&[]).unwrap_err(), ProgramError::InvalidArgument ); assert_eq!( - pod_from_bytes::>(&[0; 1]).unwrap_err(), + pod_from_bytes::>(&[0; 7]).unwrap_err(), ProgramError::InvalidArgument ); assert_eq!( - pod_from_bytes::>(&[1; 1]).unwrap_err(), + pod_from_bytes::>(&[1; 7]).unwrap_err(), ProgramError::InvalidArgument ); }