1use crate::address::{address_eq, Address};
9use crate::borrow::{Ref, RefMut};
10use crate::error::ProgramError;
11use crate::raw_account::RuntimeAccount;
12use crate::{ProgramResult, MAX_PERMITTED_DATA_INCREASE, NOT_BORROWED};
13
14#[repr(C)]
21#[cfg_attr(feature = "copy", derive(Copy))]
22#[derive(Clone, PartialEq, Eq)]
23pub struct AccountView {
24 raw: *mut RuntimeAccount,
25}
26
27unsafe impl Send for AccountView {}
30unsafe impl Sync for AccountView {}
31
32impl AccountView {
33 #[inline(always)]
41 pub const unsafe fn new_unchecked(raw: *mut RuntimeAccount) -> Self {
42 Self { raw }
43 }
44
45 #[inline(always)]
46 pub(crate) const fn raw_ptr(&self) -> *mut RuntimeAccount {
47 self.raw
48 }
49
50 #[inline(always)]
54 pub fn address(&self) -> &Address {
55 unsafe { &(*self.raw).address }
57 }
58
59 #[inline(always)]
67 pub unsafe fn owner(&self) -> &Address {
68 unsafe { &(*self.raw).owner }
70 }
71
72 #[inline(always)]
74 pub fn is_signer(&self) -> bool {
75 unsafe { (*self.raw).is_signer != 0 }
77 }
78
79 #[inline(always)]
81 pub fn is_writable(&self) -> bool {
82 unsafe { (*self.raw).is_writable != 0 }
83 }
84
85 #[inline(always)]
87 pub fn executable(&self) -> bool {
88 unsafe { (*self.raw).executable != 0 }
89 }
90
91 #[inline(always)]
93 pub fn data_len(&self) -> usize {
94 unsafe { (*self.raw).data_len as usize }
95 }
96
97 #[inline(always)]
99 pub fn resize_delta(&self) -> i32 {
100 unsafe { (*self.raw).resize_delta }
101 }
102
103 #[inline(always)]
105 pub fn lamports(&self) -> u64 {
106 unsafe { (*self.raw).lamports }
107 }
108
109 #[inline(always)]
111 pub fn is_data_empty(&self) -> bool {
112 self.data_len() == 0
113 }
114
115 #[inline(always)]
117 pub fn set_lamports(&self, lamports: u64) {
118 unsafe {
119 (*self.raw).lamports = lamports;
120 }
121 }
122
123 #[inline(always)]
127 pub fn owned_by(&self, program: &Address) -> bool {
128 unsafe { address_eq(&(*self.raw).owner, program) }
130 }
131
132 #[inline(always)]
139 pub unsafe fn assign(&self, new_owner: &Address) {
140 unsafe {
141 (*self.raw).owner = new_owner.clone();
142 }
143 }
144
145 #[inline(always)]
149 pub fn is_borrowed(&self) -> bool {
150 unsafe { (*self.raw).borrow_state != NOT_BORROWED }
151 }
152
153 #[inline(always)]
155 pub fn is_borrowed_mut(&self) -> bool {
156 unsafe { (*self.raw).borrow_state == 0 }
157 }
158
159 #[inline(always)]
161 pub fn check_borrow(&self) -> Result<(), ProgramError> {
162 let state = unsafe { (*self.raw).borrow_state };
163 if state == 0 {
164 Err(ProgramError::AccountBorrowFailed)
166 } else {
167 Ok(())
168 }
169 }
170
171 #[inline(always)]
173 pub fn check_borrow_mut(&self) -> Result<(), ProgramError> {
174 let state = unsafe { (*self.raw).borrow_state };
175 if state != NOT_BORROWED {
176 Err(ProgramError::AccountBorrowFailed)
178 } else {
179 Ok(())
180 }
181 }
182
183 #[inline(always)]
191 pub unsafe fn borrow_unchecked(&self) -> &[u8] {
192 let data_ptr = self.data_ptr_unchecked();
193 let len = self.data_len();
194 unsafe { core::slice::from_raw_parts(data_ptr, len) }
195 }
196
197 #[inline(always)]
203 pub unsafe fn borrow_unchecked_mut(&self) -> &mut [u8] {
204 let data_ptr = self.data_ptr_unchecked();
205 let len = self.data_len();
206 unsafe { core::slice::from_raw_parts_mut(data_ptr, len) }
207 }
208
209 #[inline(always)]
215 pub fn try_borrow(&self) -> Result<Ref<'_, [u8]>, ProgramError> {
216 self.check_borrow()?;
217 let state_ptr = unsafe { &mut (*self.raw).borrow_state as *mut u8 };
218 let state = unsafe { *state_ptr };
219 let new_state = if state == NOT_BORROWED { 1 } else { state + 1 };
220 if new_state == 0 {
221 return Err(ProgramError::AccountBorrowFailed);
223 }
224 unsafe {
225 *state_ptr = new_state;
226 }
227 let data = unsafe { self.borrow_unchecked() };
228 Ok(Ref::new(data, state_ptr))
229 }
230
231 #[inline(always)]
235 pub fn try_borrow_mut(&self) -> Result<RefMut<'_, [u8]>, ProgramError> {
236 self.check_borrow_mut()?;
237 let state_ptr = unsafe { &mut (*self.raw).borrow_state as *mut u8 };
238 unsafe {
239 *state_ptr = 0;
240 } let data = unsafe { self.borrow_unchecked_mut() };
242 Ok(RefMut::new(data, state_ptr))
243 }
244
245 #[inline(always)]
249 pub fn segment_ref<T: crate::pod::Pod>(
250 &self,
251 offset: u32,
252 size: u32,
253 ) -> Result<Ref<'_, T>, ProgramError> {
254 let expected_size = core::mem::size_of::<T>() as u32;
255 if size != expected_size {
256 return Err(ProgramError::InvalidArgument);
257 }
258
259 let end = offset
260 .checked_add(size)
261 .ok_or(ProgramError::ArithmeticOverflow)?;
262 if end as usize > self.data_len() {
263 return Err(ProgramError::AccountDataTooSmall);
264 }
265
266 self.check_borrow()?;
267 let state_ptr = unsafe { &mut (*self.raw).borrow_state as *mut u8 };
268 let state = unsafe { *state_ptr };
269 let new_state = if state == NOT_BORROWED { 1 } else { state + 1 };
270 if new_state == 0 {
271 return Err(ProgramError::AccountBorrowFailed);
272 }
273 unsafe {
274 *state_ptr = new_state;
275 }
276
277 let ptr = unsafe { self.data_ptr_unchecked().add(offset as usize) as *const T };
278 Ok(Ref::new(unsafe { &*ptr }, state_ptr))
279 }
280
281 #[inline(always)]
289 pub unsafe fn segment_ref_unchecked<T: crate::pod::Pod>(
290 &self,
291 offset: u32,
292 ) -> Result<Ref<'_, T>, ProgramError> {
293 self.check_borrow()?;
294 let state_ptr = unsafe { &mut (*self.raw).borrow_state as *mut u8 };
295 let state = unsafe { *state_ptr };
296 let new_state = if state == NOT_BORROWED { 1 } else { state + 1 };
297 if new_state == 0 {
298 return Err(ProgramError::AccountBorrowFailed);
299 }
300 unsafe {
301 *state_ptr = new_state;
302 }
303
304 let ptr = unsafe { self.data_ptr_unchecked().add(offset as usize) as *const T };
305 Ok(Ref::new(unsafe { &*ptr }, state_ptr))
306 }
307
308 #[inline(always)]
310 pub fn segment_mut<T: crate::pod::Pod>(
311 &self,
312 offset: u32,
313 size: u32,
314 ) -> Result<RefMut<'_, T>, ProgramError> {
315 self.require_writable()?;
316
317 let expected_size = core::mem::size_of::<T>() as u32;
318 if size != expected_size {
319 return Err(ProgramError::InvalidArgument);
320 }
321
322 let end = offset
323 .checked_add(size)
324 .ok_or(ProgramError::ArithmeticOverflow)?;
325 if end as usize > self.data_len() {
326 return Err(ProgramError::AccountDataTooSmall);
327 }
328
329 self.check_borrow_mut()?;
330 let state_ptr = unsafe { &mut (*self.raw).borrow_state as *mut u8 };
331 unsafe {
332 *state_ptr = 0;
333 }
334
335 let ptr = unsafe { self.data_ptr_unchecked().add(offset as usize) as *mut T };
336 Ok(RefMut::new(unsafe { &mut *ptr }, state_ptr))
337 }
338
339 #[inline(always)]
348 pub unsafe fn segment_mut_unchecked<T: crate::pod::Pod>(
349 &self,
350 offset: u32,
351 ) -> Result<RefMut<'_, T>, ProgramError> {
352 self.check_borrow_mut()?;
353 let state_ptr = unsafe { &mut (*self.raw).borrow_state as *mut u8 };
354 unsafe {
355 *state_ptr = 0;
356 }
357
358 let ptr = unsafe { self.data_ptr_unchecked().add(offset as usize) as *mut T };
359 Ok(RefMut::new(unsafe { &mut *ptr }, state_ptr))
360 }
361
362 #[inline(always)]
364 pub unsafe fn raw_ref<T: crate::pod::Pod>(&self) -> Result<Ref<'_, T>, ProgramError> {
365 self.segment_ref::<T>(0, core::mem::size_of::<T>() as u32)
366 }
367
368 #[inline(always)]
370 pub unsafe fn raw_mut<T: crate::pod::Pod>(&self) -> Result<RefMut<'_, T>, ProgramError> {
371 self.segment_mut::<T>(0, core::mem::size_of::<T>() as u32)
372 }
373
374 #[inline(always)]
381 pub fn resize(&self, new_len: usize) -> Result<(), ProgramError> {
382 let original_len = (self.data_len() as i64 - self.resize_delta() as i64) as usize;
383 if new_len > original_len + MAX_PERMITTED_DATA_INCREASE {
384 return Err(ProgramError::InvalidRealloc);
385 }
386 let delta = new_len as i64 - original_len as i64;
387 unsafe {
388 (*self.raw).data_len = new_len as u64;
389 (*self.raw).resize_delta = delta as i32;
390 }
391 Ok(())
392 }
393
394 #[inline(always)]
400 pub unsafe fn resize_unchecked(&self, new_len: usize) {
401 let original_len = (self.data_len() as i64 - self.resize_delta() as i64) as usize;
402 let delta = new_len as i64 - original_len as i64;
403 unsafe {
404 (*self.raw).data_len = new_len as u64;
405 (*self.raw).resize_delta = delta as i32;
406 }
407 }
408
409 pub const SYSTEM_PROGRAM_ID: Address = Address::new_from_array([0u8; 32]);
420
421 #[inline(always)]
433 pub fn close(&self) -> ProgramResult {
434 self.set_lamports(0);
435 unsafe {
436 let len = self.data_len();
437 if len > 0 {
438 crate::mem::memset(self.data_ptr_unchecked(), 0, len);
440 }
441 (*self.raw).data_len = 0;
442 (*self.raw).owner = Self::SYSTEM_PROGRAM_ID;
443 }
444 Ok(())
445 }
446
447 #[inline(always)]
453 pub unsafe fn close_unchecked(&self) {
454 unsafe {
455 (*self.raw).lamports = 0;
456 (*self.raw).data_len = 0;
457 (*self.raw).owner = Self::SYSTEM_PROGRAM_ID;
458 }
459 }
460
461 #[inline(always)]
465 pub const fn account_ptr(&self) -> *const RuntimeAccount {
466 self.raw as *const RuntimeAccount
467 }
468
469 #[doc(hidden)]
480 #[inline(always)]
481 pub fn data_ptr_unchecked(&self) -> *mut u8 {
482 unsafe { (self.raw as *mut u8).add(core::mem::size_of::<RuntimeAccount>()) }
485 }
486
487 #[inline(always)]
491 pub fn require_signer(&self) -> ProgramResult {
492 if self.is_signer() {
493 Ok(())
494 } else {
495 Err(ProgramError::MissingRequiredSignature)
496 }
497 }
498
499 #[inline(always)]
501 pub fn require_writable(&self) -> ProgramResult {
502 if self.is_writable() {
503 Ok(())
504 } else {
505 Err(ProgramError::Immutable)
506 }
507 }
508
509 #[inline(always)]
511 pub fn require_owned_by(&self, program: &Address) -> ProgramResult {
512 if self.owned_by(program) {
513 Ok(())
514 } else {
515 Err(ProgramError::IncorrectProgramId)
516 }
517 }
518
519 #[inline(always)]
521 pub fn require_payer(&self) -> ProgramResult {
522 self.require_signer()?;
523 self.require_writable()
524 }
525
526 #[inline(always)]
530 pub fn disc(&self) -> u8 {
531 if self.data_len() == 0 {
532 return 0;
533 }
534 unsafe { *self.data_ptr_unchecked() }
535 }
536
537 #[inline(always)]
541 pub fn version(&self) -> u8 {
542 if self.data_len() < 2 {
543 return 0;
544 }
545 unsafe { *self.data_ptr_unchecked().add(1) }
546 }
547
548 #[inline(always)]
553 pub fn layout_id(&self) -> Option<&[u8; 8]> {
554 if self.data_len() < 12 {
555 return None;
556 }
557 unsafe { Some(&*(self.data_ptr_unchecked().add(4) as *const [u8; 8])) }
558 }
559
560 #[inline(always)]
562 pub fn require_disc(&self, expected: u8) -> ProgramResult {
563 if self.disc() == expected {
564 Ok(())
565 } else {
566 Err(ProgramError::InvalidAccountData)
567 }
568 }
569
570 #[inline(always)]
584 pub fn check_signer(&self) -> Result<&Self, ProgramError> {
585 if self.is_signer() {
586 Ok(self)
587 } else {
588 Err(ProgramError::MissingRequiredSignature)
589 }
590 }
591
592 #[inline(always)]
594 pub fn check_writable(&self) -> Result<&Self, ProgramError> {
595 if self.is_writable() {
596 Ok(self)
597 } else {
598 Err(ProgramError::Immutable)
599 }
600 }
601
602 #[inline(always)]
604 pub fn check_owned_by(&self, program: &Address) -> Result<&Self, ProgramError> {
605 if self.owned_by(program) {
606 Ok(self)
607 } else {
608 Err(ProgramError::IncorrectProgramId)
609 }
610 }
611
612 #[inline(always)]
614 pub fn check_disc(&self, expected: u8) -> Result<&Self, ProgramError> {
615 if self.disc() == expected {
616 Ok(self)
617 } else {
618 Err(ProgramError::InvalidAccountData)
619 }
620 }
621
622 #[inline(always)]
624 pub fn check_has_data(&self) -> Result<&Self, ProgramError> {
625 if !self.is_data_empty() {
626 Ok(self)
627 } else {
628 Err(ProgramError::AccountDataTooSmall)
629 }
630 }
631
632 #[inline(always)]
634 pub fn check_executable(&self) -> Result<&Self, ProgramError> {
635 if self.executable() {
636 Ok(self)
637 } else {
638 Err(ProgramError::InvalidArgument)
639 }
640 }
641
642 #[inline(always)]
644 pub fn check_address(&self, expected: &Address) -> Result<&Self, ProgramError> {
645 if address_eq(self.address(), expected) {
646 Ok(self)
647 } else {
648 Err(ProgramError::InvalidArgument)
649 }
650 }
651
652 #[inline(always)]
654 pub fn check_data_len(&self, min_len: usize) -> Result<&Self, ProgramError> {
655 if self.data_len() >= min_len {
656 Ok(self)
657 } else {
658 Err(ProgramError::AccountDataTooSmall)
659 }
660 }
661
662 #[inline(always)]
670 pub fn read_owner(&self) -> Address {
671 unsafe { (*self.raw).owner.clone() }
672 }
673
674 #[inline(always)]
683 fn header_u32(&self) -> u32 {
684 unsafe { *(self.raw as *const u32) }
689 }
690
691 #[inline(always)]
707 pub fn flags(&self) -> u8 {
708 let h = self.header_u32();
711 let mut f: u8 = 0;
712 if h & 0x0000_FF00 != 0 {
713 f |= 0b0001;
714 } if h & 0x00FF_0000 != 0 {
716 f |= 0b0010;
717 } if h & 0xFF00_0000 != 0 {
719 f |= 0b0100;
720 } if !self.is_data_empty() {
722 f |= 0b1000;
723 }
724 f
725 }
726
727 #[inline(always)]
731 pub fn expect_flags(&self, required: u8) -> ProgramResult {
732 if self.flags() & required == required {
733 Ok(())
734 } else {
735 Err(ProgramError::InvalidArgument)
736 }
737 }
738}
739
740impl core::fmt::Debug for AccountView {
741 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
742 f.debug_struct("AccountView")
743 .field("address", self.address())
744 .field("lamports", &self.lamports())
745 .field("data_len", &self.data_len())
746 .field("is_signer", &self.is_signer())
747 .field("is_writable", &self.is_writable())
748 .finish()
749 }
750}
751
752pub struct RemainingAccounts<'a> {
756 accounts: &'a [AccountView],
757 cursor: usize,
758}
759
760impl<'a> RemainingAccounts<'a> {
761 #[inline(always)]
763 pub fn new(accounts: &'a [AccountView]) -> Self {
764 Self {
765 accounts,
766 cursor: 0,
767 }
768 }
769
770 #[inline(always)]
772 pub fn remaining(&self) -> usize {
773 self.accounts.len() - self.cursor
774 }
775
776 #[inline(always)]
778 pub fn next(&mut self) -> Result<&'a AccountView, ProgramError> {
779 if self.cursor >= self.accounts.len() {
780 return Err(ProgramError::NotEnoughAccountKeys);
781 }
782 let account = &self.accounts[self.cursor];
783 self.cursor += 1;
784 Ok(account)
785 }
786
787 #[inline(always)]
789 pub fn next_signer(&mut self) -> Result<&'a AccountView, ProgramError> {
790 let account = self.next()?;
791 account.require_signer()?;
792 Ok(account)
793 }
794
795 #[inline(always)]
797 pub fn next_writable(&mut self) -> Result<&'a AccountView, ProgramError> {
798 let account = self.next()?;
799 account.require_writable()?;
800 Ok(account)
801 }
802
803 #[inline(always)]
805 pub fn next_owned_by(&mut self, program: &Address) -> Result<&'a AccountView, ProgramError> {
806 let account = self.next()?;
807 account.require_owned_by(program)?;
808 Ok(account)
809 }
810}