hopper_core/check/
modifier.rs1use crate::account::{FixedLayout, Pod, VerifiedAccount, VerifiedAccountMut};
21use crate::check;
22use hopper_runtime::error::ProgramError;
23use hopper_runtime::{AccountView, Address};
24
25pub struct Account<'a, T: Pod + FixedLayout> {
29 view: &'a AccountView,
30 verified: VerifiedAccount<'a, T>,
31}
32
33impl<'a, T: Pod + FixedLayout> Account<'a, T> {
34 #[inline(always)]
36 pub fn view(&self) -> &'a AccountView {
37 self.view
38 }
39
40 #[inline(always)]
42 pub fn get(&self) -> &T {
43 self.verified.get()
44 }
45
46 #[inline(always)]
48 pub fn data(&self) -> &[u8] {
49 self.verified.data()
50 }
51
52 #[inline(always)]
54 pub fn map<U, F>(&self, f: F) -> U
55 where
56 F: FnOnce(&T) -> U,
57 {
58 self.verified.map(f)
59 }
60}
61
62pub struct AccountMut<'a, T: Pod + FixedLayout> {
66 view: &'a AccountView,
67 verified: VerifiedAccountMut<'a, T>,
68}
69
70impl<'a, T: Pod + FixedLayout> AccountMut<'a, T> {
71 #[inline(always)]
73 pub fn view(&self) -> &'a AccountView {
74 self.view
75 }
76
77 #[inline(always)]
79 pub fn get(&self) -> &T {
80 self.verified.get()
81 }
82
83 #[inline(always)]
85 pub fn get_mut(&mut self) -> &mut T {
86 self.verified.get_mut()
87 }
88
89 #[inline(always)]
91 pub fn map_mut<U, F>(&mut self, f: F) -> U
92 where
93 F: FnOnce(&mut T) -> U,
94 {
95 self.verified.map_mut(f)
96 }
97}
98
99pub struct Signer<I> {
103 inner: I,
104}
105
106impl<I> Signer<I> {
107 #[inline(always)]
109 pub fn inner(&self) -> &I {
110 &self.inner
111 }
112
113 #[inline(always)]
115 pub fn into_inner(self) -> I {
116 self.inner
117 }
118}
119
120pub struct Mut<I> {
122 inner: I,
123}
124
125impl<I> Mut<I> {
126 #[inline(always)]
128 pub fn inner(&self) -> &I {
129 &self.inner
130 }
131
132 #[inline(always)]
134 pub fn into_inner(self) -> I {
135 self.inner
136 }
137}
138
139pub trait FromAccount<'a>: Sized {
143 fn from_account(account: &'a AccountView, program_id: &Address) -> Result<Self, ProgramError>;
145}
146
147impl<'a, T: Pod + FixedLayout + HopperLayout> FromAccount<'a> for Account<'a, T> {
149 #[inline]
150 fn from_account(account: &'a AccountView, program_id: &Address) -> Result<Self, ProgramError> {
151 check::check_owner(account, program_id)?;
152 let data = account.try_borrow()?;
153 crate::account::check_header(&data, T::DISC, T::VERSION, &T::LAYOUT_ID)?;
154 check::check_size(&data, T::LEN_WITH_HEADER)?;
155 let verified = VerifiedAccount::from_ref(data)?;
156 Ok(Self {
157 view: account,
158 verified,
159 })
160 }
161}
162
163impl<'a, T: Pod + FixedLayout + HopperLayout> FromAccount<'a> for AccountMut<'a, T> {
165 #[inline]
166 fn from_account(account: &'a AccountView, program_id: &Address) -> Result<Self, ProgramError> {
167 check::check_owner(account, program_id)?;
168 check::check_writable(account)?;
169 let data = account.try_borrow_mut()?;
170 crate::account::check_header(&data, T::DISC, T::VERSION, &T::LAYOUT_ID)?;
171 check::check_size(&data, T::LEN_WITH_HEADER)?;
172 let verified = VerifiedAccountMut::from_ref_mut(data)?;
173 Ok(Self {
174 view: account,
175 verified,
176 })
177 }
178}
179
180impl<'a, I: FromAccount<'a> + HasView<'a>> FromAccount<'a> for Signer<I> {
182 #[inline]
183 fn from_account(account: &'a AccountView, program_id: &Address) -> Result<Self, ProgramError> {
184 check::check_signer(account)?;
185 let inner = I::from_account(account, program_id)?;
186 Ok(Self { inner })
187 }
188}
189
190impl<'a, I: FromAccount<'a> + HasView<'a>> FromAccount<'a> for Mut<I> {
192 #[inline]
193 fn from_account(account: &'a AccountView, program_id: &Address) -> Result<Self, ProgramError> {
194 check::check_writable(account)?;
195 let inner = I::from_account(account, program_id)?;
196 Ok(Self { inner })
197 }
198}
199
200pub trait HasView<'a> {
202 fn view(&self) -> &'a AccountView;
203}
204
205impl<'a, T: Pod + FixedLayout> HasView<'a> for Account<'a, T> {
206 #[inline(always)]
207 fn view(&self) -> &'a AccountView {
208 self.view
209 }
210}
211
212impl<'a, T: Pod + FixedLayout> HasView<'a> for AccountMut<'a, T> {
213 #[inline(always)]
214 fn view(&self) -> &'a AccountView {
215 self.view
216 }
217}
218
219impl<'a, I: HasView<'a>> HasView<'a> for Signer<I> {
220 #[inline(always)]
221 fn view(&self) -> &'a AccountView {
222 self.inner.view()
223 }
224}
225
226impl<'a, I: HasView<'a>> HasView<'a> for Mut<I> {
227 #[inline(always)]
228 fn view(&self) -> &'a AccountView {
229 self.inner.view()
230 }
231}
232
233pub trait HopperLayout: Pod + FixedLayout {
238 const DISC: u8;
239 const VERSION: u8;
240 const LAYOUT_ID: [u8; 8];
241 const LEN_WITH_HEADER: usize;
242}