core_preview/hooked/
mod.rs1pub mod plugin;
2pub use plugin::*;
3
4pub mod advanced_types;
5pub use advanced_types::*;
6
7pub mod asset;
8pub use asset::*;
9
10use borsh::{BorshDeserialize, BorshSerialize};
11
12use std::{cmp::Ordering, mem::size_of};
13
14use crate::{
15 accounts::{BaseAssetV1, BaseCollectionV1, PluginHeaderV1, PluginRegistryV1},
16 errors::MplCoreError,
17 types::{Key, Plugin, PluginType, RegistryRecord},
18};
19use solana_program::account_info::AccountInfo;
20
21impl From<&Plugin> for PluginType {
22 fn from(plugin: &Plugin) -> Self {
23 match plugin {
24 Plugin::Royalties(_) => PluginType::Royalties,
25 Plugin::FreezeDelegate(_) => PluginType::FreezeDelegate,
26 Plugin::BurnDelegate(_) => PluginType::BurnDelegate,
27 Plugin::TransferDelegate(_) => PluginType::TransferDelegate,
28 Plugin::UpdateDelegate(_) => PluginType::UpdateDelegate,
29 Plugin::PermanentFreezeDelegate(_) => PluginType::PermanentFreezeDelegate,
30 Plugin::Attributes(_) => PluginType::Attributes,
31 Plugin::PermanentTransferDelegate(_) => PluginType::PermanentTransferDelegate,
32 Plugin::PermanentBurnDelegate(_) => PluginType::PermanentBurnDelegate,
33 }
34 }
35}
36
37impl BaseAssetV1 {
38 pub const BASE_LENGTH: usize = 1 + 32 + 33 + 4 + 4 + 1;
40}
41
42impl BaseCollectionV1 {
43 pub const BASE_LENGTH: usize = 1 + 32 + 4 + 4 + 4 + 4;
45}
46
47impl DataBlob for BaseAssetV1 {
48 fn get_initial_size() -> usize {
49 BaseAssetV1::BASE_LENGTH
50 }
51
52 fn get_size(&self) -> usize {
53 let mut size = BaseAssetV1::BASE_LENGTH + self.name.len() + self.uri.len();
54 if self.seq.is_some() {
55 size += size_of::<u64>();
56 }
57 size
58 }
59}
60
61impl SolanaAccount for BaseAssetV1 {
62 fn key() -> Key {
63 Key::AssetV1
64 }
65}
66
67impl DataBlob for BaseCollectionV1 {
68 fn get_initial_size() -> usize {
69 Self::BASE_LENGTH
70 }
71
72 fn get_size(&self) -> usize {
73 Self::BASE_LENGTH + self.name.len() + self.uri.len()
74 }
75}
76
77impl SolanaAccount for BaseCollectionV1 {
78 fn key() -> Key {
79 Key::CollectionV1
80 }
81}
82
83impl SolanaAccount for PluginRegistryV1 {
84 fn key() -> Key {
85 Key::PluginRegistryV1
86 }
87}
88
89impl SolanaAccount for PluginHeaderV1 {
90 fn key() -> Key {
91 Key::PluginHeaderV1
92 }
93}
94
95impl Key {
96 pub fn from_u8(value: u8) -> Option<Self> {
97 match value {
98 0 => Some(Key::Uninitialized),
99 1 => Some(Key::AssetV1),
100 2 => Some(Key::HashedAssetV1),
101 3 => Some(Key::PluginHeaderV1),
102 4 => Some(Key::PluginRegistryV1),
103 5 => Some(Key::CollectionV1),
104 _ => None,
105 }
106 }
107}
108
109pub fn load_key(account: &AccountInfo, offset: usize) -> Result<Key, std::io::Error> {
111 let key = Key::from_u8((*account.data).borrow()[offset]).ok_or(std::io::Error::new(
112 std::io::ErrorKind::Other,
113 MplCoreError::DeserializationError.to_string(),
114 ))?;
115
116 Ok(key)
117}
118
119pub trait DataBlob: BorshSerialize + BorshDeserialize {
121 fn get_initial_size() -> usize;
123 fn get_size(&self) -> usize;
125}
126
127pub trait SolanaAccount: BorshSerialize + BorshDeserialize {
129 fn key() -> Key;
131
132 fn load(account: &AccountInfo, offset: usize) -> Result<Self, std::io::Error> {
134 let key = load_key(account, offset)?;
135
136 if key != Self::key() {
137 return Err(std::io::Error::new(
138 std::io::ErrorKind::Other,
139 MplCoreError::DeserializationError.to_string(),
140 ));
141 }
142
143 let mut bytes: &[u8] = &(*account.data).borrow()[offset..];
144 Self::deserialize(&mut bytes)
145 }
146
147 fn save(&self, account: &AccountInfo, offset: usize) -> Result<(), std::io::Error> {
149 borsh::to_writer(&mut account.data.borrow_mut()[offset..], self)
150 }
151}
152
153impl RegistryRecord {
154 pub fn compare_offsets(a: &RegistryRecord, b: &RegistryRecord) -> Ordering {
156 a.offset.cmp(&b.offset)
157 }
158}