Skip to content

Commit

Permalink
VoteState: make deserialize_into take &mut VoteState again
Browse files Browse the repository at this point in the history
Introduce new ::deserialize_into_uninit that takes
MaybeUninit<VoteState>. This way we don't break API, and we can less
abruptly deprecate ::deserialize_into and later on rename
::deserialize_into_uninit to ::deserialize_into.
  • Loading branch information
alessandrod committed Jul 28, 2024
1 parent 176c400 commit 3d74cde
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 15 deletions.
39 changes: 28 additions & 11 deletions sdk/program/src/vote/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,17 @@ impl VoteState {
}
}

/// Deserializes the input `VoteStateVersions` buffer directly into the provided `VoteState`.
///
/// In a SBPF context, V0_23_5 is not supported, but in non-SBPF, all versions are supported for
/// compatibility with `bincode::deserialize`.
pub fn deserialize_into(
input: &[u8],
vote_state: &mut VoteState,
) -> Result<(), InstructionError> {
VoteState::deserialize_into_ptr(input, vote_state as *mut VoteState)
}

/// Deserializes the input `VoteStateVersions` buffer directly into the provided
/// `MaybeUninit<VoteState>`.
///
Expand All @@ -488,11 +499,17 @@ impl VoteState {
/// On success, `vote_state` is fully initialized and can be converted to `VoteState` using
/// [MaybeUninit::assume_init]. On failure, `vote_state` may still be uninitialized and must not
/// be converted to `VoteState`.
pub fn deserialize_into(
pub fn deserialize_into_uninit(
input: &[u8],
vote_state: &mut MaybeUninit<VoteState>,
) -> Result<(), InstructionError> {
let vote_state = vote_state.as_mut_ptr();
VoteState::deserialize_into_ptr(input, vote_state.as_mut_ptr())
}

fn deserialize_into_ptr(
input: &[u8],
vote_state: *mut VoteState,
) -> Result<(), InstructionError> {
let mut cursor = Cursor::new(input);

let variant = read_u32(&mut cursor)?;
Expand Down Expand Up @@ -1107,14 +1124,14 @@ mod tests {
}

#[test]
fn test_vote_deserialize_into() {
fn test_vote_deserialize_into_uninit() {
// base case
let target_vote_state = VoteState::default();
let vote_state_buf =
bincode::serialize(&VoteStateVersions::new_current(target_vote_state.clone())).unwrap();

let mut test_vote_state = MaybeUninit::uninit();
VoteState::deserialize_into(&vote_state_buf, &mut test_vote_state).unwrap();
VoteState::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state).unwrap();
let test_vote_state = unsafe { test_vote_state.assume_init() };

assert_eq!(target_vote_state, test_vote_state);
Expand All @@ -1132,18 +1149,18 @@ mod tests {
let target_vote_state = target_vote_state_versions.convert_to_current();

let mut test_vote_state = MaybeUninit::uninit();
VoteState::deserialize_into(&vote_state_buf, &mut test_vote_state).unwrap();
VoteState::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state).unwrap();
let test_vote_state = unsafe { test_vote_state.assume_init() };

assert_eq!(target_vote_state, test_vote_state);
}
}

#[test]
fn test_vote_deserialize_into_nopanic() {
fn test_vote_deserialize_into_uninit_nopanic() {
// base case
let mut test_vote_state = MaybeUninit::uninit();
let e = VoteState::deserialize_into(&[], &mut test_vote_state).unwrap_err();
let e = VoteState::deserialize_into_uninit(&[], &mut test_vote_state).unwrap_err();
assert_eq!(e, InstructionError::InvalidAccountData);

// variant
Expand All @@ -1165,7 +1182,7 @@ mod tests {
// it is extremely improbable, though theoretically possible, for random bytes to be syntactically valid
// so we only check that the parser does not panic and that it succeeds or fails exactly in line with bincode
let mut test_vote_state = MaybeUninit::uninit();
let test_res = VoteState::deserialize_into(&raw_data, &mut test_vote_state);
let test_res = VoteState::deserialize_into_uninit(&raw_data, &mut test_vote_state);
let bincode_res = bincode::deserialize::<VoteStateVersions>(&raw_data)
.map(|versioned| versioned.convert_to_current());

Expand All @@ -1179,7 +1196,7 @@ mod tests {
}

#[test]
fn test_vote_deserialize_into_ill_sized() {
fn test_vote_deserialize_into_uninit_ill_sized() {
// provide 4x the minimum struct size in bytes to ensure we typically touch every field
let struct_bytes_x4 = std::mem::size_of::<VoteState>() * 4;
for _ in 0..1000 {
Expand All @@ -1198,7 +1215,7 @@ mod tests {

// truncated fails
let mut test_vote_state = MaybeUninit::uninit();
let test_res = VoteState::deserialize_into(&truncated_buf, &mut test_vote_state);
let test_res = VoteState::deserialize_into_uninit(&truncated_buf, &mut test_vote_state);
let bincode_res = bincode::deserialize::<VoteStateVersions>(&truncated_buf)
.map(|versioned| versioned.convert_to_current());

Expand All @@ -1207,7 +1224,7 @@ mod tests {

// expanded succeeds
let mut test_vote_state = MaybeUninit::uninit();
VoteState::deserialize_into(&expanded_buf, &mut test_vote_state).unwrap();
VoteState::deserialize_into_uninit(&expanded_buf, &mut test_vote_state).unwrap();
let bincode_res = bincode::deserialize::<VoteStateVersions>(&expanded_buf)
.map(|versioned| versioned.convert_to_current());

Expand Down
4 changes: 2 additions & 2 deletions sdk/program/src/vote/state/vote_state_0_23_5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ mod tests {
let vote_state_buf = bincode::serialize(&target_vote_state_versions).unwrap();

let mut test_vote_state = MaybeUninit::uninit();
VoteState::deserialize_into(&vote_state_buf, &mut test_vote_state).unwrap();
VoteState::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state).unwrap();
let test_vote_state = unsafe { test_vote_state.assume_init() };

assert_eq!(
Expand All @@ -99,7 +99,7 @@ mod tests {
let target_vote_state = target_vote_state_versions.convert_to_current();

let mut test_vote_state = MaybeUninit::uninit();
VoteState::deserialize_into(&vote_state_buf, &mut test_vote_state).unwrap();
VoteState::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state).unwrap();
let test_vote_state = unsafe { test_vote_state.assume_init() };

assert_eq!(target_vote_state, test_vote_state);
Expand Down
4 changes: 2 additions & 2 deletions sdk/program/src/vote/state/vote_state_1_14_11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ mod tests {
let vote_state_buf = bincode::serialize(&target_vote_state_versions).unwrap();

let mut test_vote_state = MaybeUninit::uninit();
VoteState::deserialize_into(&vote_state_buf, &mut test_vote_state).unwrap();
VoteState::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state).unwrap();
let test_vote_state = unsafe { test_vote_state.assume_init() };

assert_eq!(
Expand All @@ -118,7 +118,7 @@ mod tests {
let target_vote_state = target_vote_state_versions.convert_to_current();

let mut test_vote_state = MaybeUninit::uninit();
VoteState::deserialize_into(&vote_state_buf, &mut test_vote_state).unwrap();
VoteState::deserialize_into_uninit(&vote_state_buf, &mut test_vote_state).unwrap();
let test_vote_state = unsafe { test_vote_state.assume_init() };

assert_eq!(target_vote_state, test_vote_state);
Expand Down

0 comments on commit 3d74cde

Please sign in to comment.