magicblock_account/cow/
owned.rs1use super::borrowed::{AccountHeader, DataHeader, STATIC_SIZE};
2use super::{ALIGNMENT, StateFlags};
3use crate::cow::AccountCore;
4use crate::cow::borrowed::IMAGE_OFFSET;
5use crate::{Account, AccountMode, AccountSharedData, StorageUnit};
6use solana_clock::Slot;
7use solana_pubkey::Pubkey;
8use std::{ptr::NonNull, sync::Arc};
9
10#[derive(Clone, Default, Eq, PartialEq)]
12#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
13pub struct OwnedAccount {
14 pub(crate) core: AccountCore,
16 pub(crate) data: Arc<Vec<u8>>,
18}
19
20impl OwnedAccount {
21 pub fn units(&self) -> u32 {
23 self.allocation() * 2 + IMAGE_OFFSET as u32
24 }
25
26 fn allocation(&self) -> u32 {
28 (STATIC_SIZE + self.data.len()).div_ceil(ALIGNMENT) as u32
29 }
30
31 pub unsafe fn serialize(&self, buf: &mut [StorageUnit], pubkey: &Pubkey) {
39 let ptr = NonNull::new_unchecked(buf.as_mut_ptr());
40 debug_assert_eq!(self.units() as usize, buf.len());
41
42 fn write<U, T: Sized>(ptr: NonNull<U>, v: T) -> NonNull<T> {
43 unsafe {
45 ptr.cast().write(v);
46 ptr.cast().add(1)
47 }
48 }
49
50 let allocation = self.allocation();
51 let ptr = write(ptr, AccountHeader::new(allocation));
52 let ptr = write(ptr, *pubkey);
54 let ptr = write(ptr, self.core);
55 let len = self.data.len();
56 let ptr = write(ptr, DataHeader::new(len as u32, allocation)).cast();
57 self.data.as_ptr().copy_to_nonoverlapping(ptr.as_ptr(), len);
58 }
59
60 pub fn is(&self, mode: AccountMode) -> bool {
62 self.core.mode == mode
63 }
64
65 pub fn owner(&self) -> Pubkey {
67 self.core.owner
68 }
69
70 pub fn lamports(&self) -> u64 {
72 self.core.lamports
73 }
74
75 pub fn mode(&self) -> AccountMode {
77 self.core.mode
78 }
79
80 pub fn slot(&self) -> u64 {
82 self.core.slot
83 }
84
85 pub fn flags(&self) -> StateFlags {
87 self.core.flags
88 }
89
90 pub fn data(&self) -> &[u8] {
92 &self.data
93 }
94}
95
96#[derive(Default, Clone)]
100pub struct AccountBuilder(OwnedAccount);
101
102impl AccountBuilder {
103 pub fn lamports(mut self, lamports: u64) -> Self {
105 self.0.core.lamports = lamports;
106 self
107 }
108
109 pub fn data(mut self, data: impl Into<Arc<Vec<u8>>>) -> Self {
111 self.0.data = data.into();
112 self
113 }
114
115 pub fn owner(mut self, owner: Pubkey) -> Self {
117 self.0.core.owner = owner;
118 self
119 }
120
121 pub fn mode(mut self, mode: AccountMode) -> Self {
123 self.0.core.mode = mode;
124 self
125 }
126
127 pub fn executable(mut self, executable: bool) -> Self {
129 self.0.core.flags.set(StateFlags::EXECUTABLE, executable);
130 self
131 }
132
133 pub fn slot(mut self, slot: Slot) -> Self {
135 self.0.core.slot = slot;
136 self
137 }
138
139 pub fn read(&self) -> &OwnedAccount {
141 &self.0
142 }
143
144 pub fn build<A: From<OwnedAccount>>(self) -> A {
146 self.0.into()
147 }
148}
149
150impl From<Account> for OwnedAccount {
151 fn from(value: Account) -> Self {
152 AccountBuilder::default()
153 .lamports(value.lamports)
154 .data(value.data)
155 .owner(value.owner)
156 .executable(value.executable)
157 .build()
158 }
159}
160
161impl From<AccountBuilder> for OwnedAccount {
162 fn from(value: AccountBuilder) -> Self {
163 value.0
164 }
165}
166
167impl From<Account> for AccountBuilder {
168 fn from(value: Account) -> Self {
169 Self(value.into())
170 }
171}
172
173impl From<AccountSharedData> for AccountBuilder {
174 fn from(value: AccountSharedData) -> Self {
175 Self(value.owned())
176 }
177}