gmsol_store/utils/
de.rs

1use std::borrow::Cow;
2
3use anchor_lang::{err, Discriminator};
4
5/// Check discriminator.
6pub fn check_discriminator<T: Discriminator>(data: &[u8]) -> anchor_lang::prelude::Result<()> {
7    use anchor_lang::error::ErrorCode;
8
9    let disc = T::discriminator();
10    if data.len() < disc.len() {
11        return err!(ErrorCode::AccountDiscriminatorNotFound);
12    }
13    let given_disc = &data[..8];
14    if disc != given_disc {
15        return err!(ErrorCode::AccountDiscriminatorMismatch);
16    }
17    Ok(())
18}
19
20/// A workaround to deserialize "zero-copy" account data.
21///
22/// See [anchort#2689](https://github.com/coral-xyz/anchor/issues/2689) for more information.
23pub fn try_deserailize<T>(data: &[u8]) -> anchor_lang::prelude::Result<T>
24where
25    T: anchor_lang::ZeroCopy,
26{
27    check_discriminator::<T>(data)?;
28    try_deserailize_unchecked(data)
29}
30
31/// A workaround to deserialize "zero-copy" account data.
32///
33/// See [anchort#2689](https://github.com/coral-xyz/anchor/issues/2689) for more information.
34pub fn try_deserailize_unchecked<T>(data: &[u8]) -> anchor_lang::prelude::Result<T>
35where
36    T: anchor_lang::ZeroCopy,
37{
38    use anchor_lang::{error, error::ErrorCode};
39    let end = std::mem::size_of::<T>() + 8;
40    if data.len() < end {
41        return err!(ErrorCode::AccountDidNotDeserialize);
42    }
43    // Note: We use vec to fix the alignment issue, maybe there is a better way.
44    let mut data_without_discriminator = Cow::Borrowed(&data[8..end]);
45    Ok(
46        *bytemuck::try_from_bytes(data_without_discriminator.to_mut())
47            .map_err(|_| error!(ErrorCode::AccountDidNotDeserialize))?,
48    )
49}