Skip to main content

anchor_lang/accounts/
boxed.rs

1extern crate alloc;
2
3use {
4    crate::{AccountConstraint, AccountInitialize, AnchorAccount, Discriminator, Space},
5    alloc::boxed::Box,
6    pinocchio::{account::AccountView, address::Address},
7    solana_program_error::ProgramError,
8};
9
10impl<T: AnchorAccount> AnchorAccount for Box<T> {
11    type Data = T;
12    const IS_SIGNER: bool = T::IS_SIGNER;
13    const MIN_DATA_LEN: usize = T::MIN_DATA_LEN;
14
15    fn load(view: AccountView) -> Result<Self, ProgramError> {
16        T::load(view).map(Box::new)
17    }
18
19    /// # Safety
20    ///
21    /// See [`AnchorAccount::load_mut`] — caller must ensure no other live
22    /// `&mut` to the same account data exists.
23    unsafe fn load_mut(view: AccountView) -> Result<Self, ProgramError> {
24        T::load_mut(view).map(Box::new)
25    }
26
27    /// # Safety
28    ///
29    /// See [`AnchorAccount::load_mut_after_init`] — caller must ensure no
30    /// other live `&mut` to the same account data exists.
31    unsafe fn load_mut_after_init(view: AccountView) -> Result<Self, ProgramError> {
32        T::load_mut_after_init(view).map(Box::new)
33    }
34
35    fn account(&self) -> &AccountView {
36        (**self).account()
37    }
38
39    fn exit(&mut self) -> pinocchio::ProgramResult {
40        (**self).exit()
41    }
42}
43
44impl<T: crate::ToCpiHandle + ?Sized> crate::ToCpiHandle for Box<T> {
45    #[inline(always)]
46    fn to_cpi_handle(&self) -> crate::CpiHandle<'_> {
47        self.as_ref().to_cpi_handle()
48    }
49}
50
51impl<T: crate::ToCpiHandleMut + ?Sized> crate::ToCpiHandleMut for Box<T> {
52    #[inline(always)]
53    fn try_to_cpi_handle_mut(
54        &mut self,
55    ) -> Result<crate::CpiHandleMut<'_>, solana_program_error::ProgramError> {
56        self.as_mut().try_to_cpi_handle_mut()
57    }
58}
59
60impl<T: crate::AccountRealloc> crate::AccountRealloc for Box<T> {
61    #[inline(always)]
62    fn realloc_account(
63        &mut self,
64        new_space: usize,
65        payer: AccountView,
66        zero: bool,
67    ) -> pinocchio::ProgramResult {
68        self.as_mut().realloc_account(new_space, payer, zero)
69    }
70}
71
72impl<T: crate::AccountClose> crate::AccountClose for Box<T> {
73    #[inline(always)]
74    fn close(&mut self, destination: AccountView) -> pinocchio::ProgramResult {
75        self.as_mut().close(destination)
76    }
77}
78
79#[doc(hidden)]
80impl<T: crate::IdlAccountType> crate::IdlAccountType for Box<T> {
81    const __IDL_ACCOUNT_ENTRY: Option<&'static str> = T::__IDL_ACCOUNT_ENTRY;
82    const __IDL_TYPE_DEF: Option<&'static str> = T::__IDL_TYPE_DEF;
83    fn __idl_account_entry() -> Option<&'static str> {
84        T::__idl_account_entry()
85    }
86    fn __idl_type_def() -> Option<&'static str> {
87        T::__idl_type_def()
88    }
89    fn __register_idl_deps(
90        accounts: &mut ::alloc::vec::Vec<&'static str>,
91        types: &mut ::alloc::vec::Vec<&'static str>,
92    ) {
93        T::__register_idl_deps(accounts, types);
94    }
95}
96
97// ---------------------------------------------------------------------------
98// Forward the init-time trait surface so `Box<Account<T>>` and
99// `Box<BorshAccount<T>>` work with `#[account(init, …)]`, `#[account(zeroed)]`,
100// `space = …` omitted, and namespaced constraints (`token::mint = …`, etc.).
101//
102// The derive reaches for these traits via UFCS on the field type — e.g.
103// `<Box<Account<T>> as AccountInitialize>::create_and_initialize(…)` — so
104// auto-deref on the receiver isn't sufficient; explicit forwards are required.
105// ---------------------------------------------------------------------------
106
107impl<T: AccountInitialize> AccountInitialize for Box<T> {
108    type Params<'a> = T::Params<'a>;
109
110    fn create_and_initialize<'a>(
111        payer: &AccountView,
112        account: &AccountView,
113        space: usize,
114        owner: &Address,
115        params: &Self::Params<'a>,
116        signer_seeds: Option<&[&[u8]]>,
117        payer_signer_seeds: Option<&[&[u8]]>,
118    ) -> Result<Self, ProgramError> {
119        T::create_and_initialize(
120            payer,
121            account,
122            space,
123            owner,
124            params,
125            signer_seeds,
126            payer_signer_seeds,
127        )
128        .map(Box::new)
129    }
130}
131
132impl<T: Space> Space for Box<T> {
133    const INIT_SPACE: usize = T::INIT_SPACE;
134}
135
136impl<T: Discriminator> Discriminator for Box<T> {
137    const DISCRIMINATOR: &'static [u8] = T::DISCRIMINATOR;
138}
139
140impl<C, T> AccountConstraint<Box<T>> for C
141where
142    C: AccountConstraint<T>,
143{
144    type Value = <C as AccountConstraint<T>>::Value;
145
146    #[inline(always)]
147    fn init(account: &mut Box<T>, value: &Self::Value) -> Result<(), ProgramError> {
148        C::init(account.as_mut(), value)
149    }
150
151    #[inline(always)]
152    fn check(account: &Box<T>, value: &Self::Value) -> Result<(), ProgramError> {
153        C::check(account.as_ref(), value)
154    }
155
156    #[inline(always)]
157    fn update(account: &mut Box<T>, value: &Self::Value) -> Result<(), ProgramError> {
158        C::update(account.as_mut(), value)
159    }
160
161    #[inline(always)]
162    fn exit(account: &mut Box<T>, value: &Self::Value) -> Result<(), ProgramError> {
163        C::exit(account.as_mut(), value)
164    }
165}