gmsol/utils/workarounds/
zero_copy.rs

1use std::sync::Arc;
2
3use anchor_client::{
4    anchor_lang::{AccountDeserialize, Discriminator},
5    solana_client::nonblocking::rpc_client::RpcClient,
6    solana_sdk::pubkey::Pubkey,
7};
8
9/// A workaround to deserialize "zero-copy" account data.
10///
11/// See [anchort#2689](https://github.com/coral-xyz/anchor/issues/2689) for more information.
12pub async fn try_deserailize_zero_copy_account<T>(
13    client: &RpcClient,
14    pubkey: &Pubkey,
15) -> crate::Result<T>
16where
17    T: anchor_client::anchor_lang::ZeroCopy,
18{
19    let data = client
20        .get_account_data(pubkey)
21        .await
22        .map_err(anchor_client::ClientError::from)?;
23
24    Ok(gmsol_store::utils::de::try_deserailize(&data)?)
25}
26
27/// Workaround for deserializing zero-copy accounts.
28#[derive(Debug, Clone, Copy)]
29pub struct ZeroCopy<T>(pub T);
30
31impl<T> ZeroCopy<T> {
32    /// Conver into inner value.
33    pub fn into_inner(self) -> T {
34        self.0
35    }
36}
37
38impl<T> AccountDeserialize for ZeroCopy<T>
39where
40    T: anchor_client::anchor_lang::ZeroCopy,
41{
42    fn try_deserialize(buf: &mut &[u8]) -> anchor_client::anchor_lang::Result<Self> {
43        let account = gmsol_store::utils::de::try_deserailize(buf)?;
44        Ok(Self(account))
45    }
46
47    fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_client::anchor_lang::Result<Self> {
48        let account = gmsol_store::utils::de::try_deserailize_unchecked(buf)?;
49        Ok(Self(account))
50    }
51}
52
53impl<T> Discriminator for ZeroCopy<T>
54where
55    T: Discriminator,
56{
57    const DISCRIMINATOR: [u8; 8] = T::DISCRIMINATOR;
58}
59
60impl<T> AsRef<T> for ZeroCopy<T> {
61    fn as_ref(&self) -> &T {
62        &self.0
63    }
64}
65
66/// Wrapper for deserializing account into arced type.
67pub struct Shared<T>(pub Arc<T>);
68
69impl<T> Clone for Shared<T> {
70    fn clone(&self) -> Self {
71        Self(self.0.clone())
72    }
73}
74
75impl<T> Shared<T> {
76    /// Conver into inner value.
77    pub fn into_inner(self) -> Arc<T> {
78        self.0
79    }
80}
81
82impl<T> AccountDeserialize for Shared<T>
83where
84    T: AccountDeserialize,
85{
86    fn try_deserialize(buf: &mut &[u8]) -> anchor_client::anchor_lang::Result<Self> {
87        let account = T::try_deserialize(buf)?;
88        Ok(Self(Arc::new(account)))
89    }
90
91    fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_client::anchor_lang::Result<Self> {
92        let account = T::try_deserialize_unchecked(buf)?;
93        Ok(Self(Arc::new(account)))
94    }
95}
96
97impl<T> Discriminator for Shared<T>
98where
99    T: Discriminator,
100{
101    const DISCRIMINATOR: [u8; 8] = T::DISCRIMINATOR;
102}
103
104impl<T> AsRef<T> for Shared<T> {
105    fn as_ref(&self) -> &T {
106        &self.0
107    }
108}
109
110/// Workaround for deserializing zero-copy accounts and wrapping the result into Arc.
111pub struct SharedZeroCopy<T>(pub Arc<T>);
112
113impl<T> Clone for SharedZeroCopy<T> {
114    fn clone(&self) -> Self {
115        Self(self.0.clone())
116    }
117}
118
119impl<T> SharedZeroCopy<T> {
120    /// Conver into inner value.
121    pub fn into_inner(self) -> Arc<T> {
122        self.0
123    }
124}
125
126impl<T> AccountDeserialize for SharedZeroCopy<T>
127where
128    T: anchor_client::anchor_lang::ZeroCopy,
129{
130    fn try_deserialize(buf: &mut &[u8]) -> anchor_client::anchor_lang::Result<Self> {
131        let account = gmsol_store::utils::de::try_deserailize(buf)?;
132        Ok(Self(Arc::new(account)))
133    }
134
135    fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_client::anchor_lang::Result<Self> {
136        let account = gmsol_store::utils::de::try_deserailize_unchecked(buf)?;
137        Ok(Self(Arc::new(account)))
138    }
139}
140
141impl<T> Discriminator for SharedZeroCopy<T>
142where
143    T: Discriminator,
144{
145    const DISCRIMINATOR: [u8; 8] = T::DISCRIMINATOR;
146}
147
148impl<T> AsRef<T> for SharedZeroCopy<T> {
149    fn as_ref(&self) -> &T {
150        &self.0
151    }
152}