Skip to content

Commit 022b275

Browse files
authored
client-rust: use a normal vector for ConfigKeys (#46)
* client-rust: use a normal vector for `ConfigKeys` * borsh short vec serialize
1 parent f7f19f6 commit 022b275

File tree

2 files changed

+77
-33
lines changed

2 files changed

+77
-33
lines changed

clients/rust/src/hooked/short_vec.rs

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
#[cfg(feature = "serde")]
2-
use serde::{Deserialize, Deserializer, Serialize, Serializer};
31
use {
42
borsh::{BorshDeserialize, BorshSerialize},
53
solana_program::pubkey::Pubkey,
64
};
5+
#[cfg(feature = "serde")]
6+
use {
7+
serde::{Deserialize, Deserializer, Serialize, Serializer},
8+
solana_program::short_vec,
9+
};
710

811
struct ShortU16(u16);
912

@@ -52,13 +55,20 @@ impl BorshDeserialize for ShortU16 {
5255
#[derive(Clone, Debug, Eq, PartialEq)]
5356
pub struct ShortVec<T>(pub Vec<T>);
5457

58+
fn borsh_serialize_as_short_vec<T: BorshSerialize, W: std::io::Write>(
59+
vec: &Vec<T>,
60+
writer: &mut W,
61+
) -> std::io::Result<()> {
62+
ShortU16(vec.len() as u16).serialize(writer)?;
63+
for item in vec {
64+
item.serialize(writer)?;
65+
}
66+
Ok(())
67+
}
68+
5569
impl<T: BorshSerialize> BorshSerialize for ShortVec<T> {
5670
fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
57-
ShortU16(self.0.len() as u16).serialize(writer)?;
58-
for item in &self.0 {
59-
item.serialize(writer)?;
60-
}
61-
Ok(())
71+
borsh_serialize_as_short_vec(&self.0, writer)
6272
}
6373
}
6474

@@ -79,7 +89,7 @@ impl<T: Serialize> Serialize for ShortVec<T> {
7989
where
8090
S: Serializer,
8191
{
82-
solana_program::short_vec::serialize(&self.0, serializer)
92+
short_vec::serialize(&self.0, serializer)
8393
}
8494
}
8595

@@ -89,16 +99,31 @@ impl<'de, T: Deserialize<'de>> Deserialize<'de> for ShortVec<T> {
8999
where
90100
D: Deserializer<'de>,
91101
{
92-
solana_program::short_vec::deserialize(deserializer).map(ShortVec)
102+
short_vec::deserialize(deserializer).map(ShortVec)
93103
}
94104
}
95105

96106
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
97-
#[derive(BorshDeserialize, BorshSerialize, Clone, Debug, Eq, PartialEq)]
107+
#[derive(Clone, Debug, Eq, PartialEq)]
98108
pub struct ConfigKeys {
99109
/// Each key tuple comprises a unique `Pubkey` identifier,
100110
/// and `bool` whether that key is a signer of the data.
101-
pub keys: ShortVec<(Pubkey, bool)>,
111+
#[cfg_attr(feature = "serde", serde(with = "short_vec"))]
112+
pub keys: Vec<(Pubkey, bool)>,
113+
}
114+
115+
impl BorshSerialize for ConfigKeys {
116+
fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
117+
borsh_serialize_as_short_vec(&self.keys, writer)
118+
}
119+
}
120+
121+
impl BorshDeserialize for ConfigKeys {
122+
fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
123+
Ok(ConfigKeys {
124+
keys: ShortVec::deserialize_reader(reader)?.0,
125+
})
126+
}
102127
}
103128

104129
/// Utility for extracting the `ConfigKeys` data from the account data.
@@ -111,12 +136,16 @@ pub fn get_config_data(bytes: &[u8]) -> Result<&[u8], bincode::Error> {
111136

112137
#[cfg(test)]
113138
mod tests {
114-
#[cfg(feature = "serde")]
115-
use {super::*, assert_matches::assert_matches, bincode::serialize};
116139
use {
140+
super::*,
117141
bincode::deserialize,
118-
solana_program::short_vec::{decode_shortu16_len, ShortU16},
142+
solana_program::{
143+
pubkey::Pubkey,
144+
short_vec::{decode_shortu16_len, ShortU16},
145+
},
119146
};
147+
#[cfg(feature = "serde")]
148+
use {assert_matches::assert_matches, bincode::serialize};
120149

121150
/// Return the serialized length.
122151
fn encode_len(len: u16) -> Vec<u8> {
@@ -225,4 +254,34 @@ mod tests {
225254
];
226255
assert!(deserialize::<ShortVec<u8>>(&bytes).is_err());
227256
}
257+
258+
#[test]
259+
fn test_serialization_borsh() {
260+
fn test_serialization(data: ConfigKeys) {
261+
let bytes = data.try_to_vec().unwrap();
262+
let data1 = ConfigKeys::try_from_slice(&bytes).unwrap();
263+
assert_eq!(data, data1);
264+
}
265+
266+
test_serialization(ConfigKeys { keys: vec![] });
267+
268+
test_serialization(ConfigKeys {
269+
keys: vec![(Pubkey::new_unique(), false)],
270+
});
271+
272+
test_serialization(ConfigKeys {
273+
keys: vec![(Pubkey::new_unique(), true), (Pubkey::new_unique(), false)],
274+
});
275+
276+
test_serialization(ConfigKeys {
277+
keys: vec![
278+
(Pubkey::new_unique(), true),
279+
(Pubkey::new_unique(), false),
280+
(Pubkey::new_unique(), true),
281+
(Pubkey::new_unique(), true),
282+
(Pubkey::new_unique(), false),
283+
(Pubkey::new_unique(), true),
284+
],
285+
});
286+
}
228287
}

clients/rust/src/instructions_bincode.rs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Program instruction helpers.
22
33
use {
4-
crate::{ConfigKeys, ShortVec, ID},
4+
crate::{ConfigKeys, ID},
55
bincode::serialized_size,
66
solana_program::{
77
instruction::{AccountMeta, Instruction},
@@ -18,12 +18,7 @@ pub trait ConfigState: serde::Serialize + Default {
1818

1919
fn initialize_account<T: ConfigState>(config_pubkey: &Pubkey) -> Instruction {
2020
let account_metas = vec![AccountMeta::new(*config_pubkey, true)];
21-
let account_data = (
22-
ConfigKeys {
23-
keys: ShortVec(vec![]),
24-
},
25-
T::default(),
26-
);
21+
let account_data = (ConfigKeys { keys: vec![] }, T::default());
2722
Instruction::new_with_bincode(ID, &account_data, account_metas)
2823
}
2924

@@ -34,12 +29,7 @@ pub fn create_account<T: ConfigState>(
3429
lamports: u64,
3530
keys: Vec<(Pubkey, bool)>,
3631
) -> Vec<Instruction> {
37-
let space = T::max_space().saturating_add(
38-
serialized_size(&ConfigKeys {
39-
keys: ShortVec(keys),
40-
})
41-
.unwrap(),
42-
);
32+
let space = T::max_space().saturating_add(serialized_size(&ConfigKeys { keys }).unwrap());
4333
vec![
4434
system_instruction::create_account(
4535
from_account_pubkey,
@@ -65,11 +55,6 @@ pub fn store<T: ConfigState>(
6555
account_metas.push(AccountMeta::new(*signer_pubkey, true));
6656
}
6757
}
68-
let account_data = (
69-
ConfigKeys {
70-
keys: ShortVec(keys),
71-
},
72-
data,
73-
);
58+
let account_data = (ConfigKeys { keys }, data);
7459
Instruction::new_with_bincode(ID, &account_data, account_metas)
7560
}

0 commit comments

Comments
 (0)