Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing get_size for everything #197

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
70 changes: 66 additions & 4 deletions programs/mpl-core/src/plugins/external_plugin_adapters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError,
pubkey::Pubkey,
};
use strum::EnumCount;
use strum::{EnumCount, EnumIter};

use crate::{
error::MplCoreError,
plugins::{approve, reject},
state::{AssetV1, SolanaAccount},
state::{AssetV1, DataBlob, SolanaAccount},
};

use super::{
Expand All @@ -22,7 +22,17 @@ use super::{
/// List of third party plugin types.
#[repr(C)]
#[derive(
Clone, Copy, Debug, BorshSerialize, BorshDeserialize, Eq, PartialEq, EnumCount, PartialOrd, Ord,
Clone,
Copy,
Debug,
BorshSerialize,
BorshDeserialize,
Eq,
PartialEq,
EnumCount,
PartialOrd,
Ord,
EnumIter,
)]
pub enum ExternalPluginAdapterType {
/// Lifecycle Hook.
Expand All @@ -39,6 +49,14 @@ pub enum ExternalPluginAdapterType {
DataSection,
}

impl DataBlob for ExternalPluginAdapterType {
const BASE_LEN: usize = 1;

fn len(&self) -> usize {
Self::BASE_LEN
}
}

impl From<&ExternalPluginAdapterKey> for ExternalPluginAdapterType {
fn from(key: &ExternalPluginAdapterKey) -> Self {
match key {
Expand Down Expand Up @@ -383,7 +401,9 @@ impl From<&ExternalPluginAdapterInitInfo> for ExternalPluginAdapter {
}

#[repr(C)]
#[derive(Eq, PartialEq, Clone, BorshSerialize, BorshDeserialize, Debug, PartialOrd, Ord, Hash)]
#[derive(
Eq, PartialEq, Clone, BorshSerialize, BorshDeserialize, Debug, PartialOrd, Ord, Hash, EnumIter,
)]
/// An enum listing all the lifecyle events available for external plugin adapter hooks. Note that some
/// lifecycle events such as adding and removing plugins will be checked by default as they are
/// inherently part of the external plugin adapter system.
Expand All @@ -398,6 +418,14 @@ pub enum HookableLifecycleEvent {
Update,
}

impl DataBlob for HookableLifecycleEvent {
const BASE_LEN: usize = 1;

fn len(&self) -> usize {
Self::BASE_LEN
}
}

/// Prefix used with some of the `ExtraAccounts` that are PDAs.
pub const MPL_CORE_PREFIX: &str = "mpl-core";

Expand Down Expand Up @@ -747,3 +775,37 @@ impl From<&ExternalPluginAdapterInitInfo> for ExternalPluginAdapterKey {
}
}
}

/// Test DataBlob sizing
#[cfg(test)]
mod test {
use strum::IntoEnumIterator;

use super::*;

#[test]
fn test_external_plugin_adapter_type_size() {
for fixture in ExternalPluginAdapterType::iter() {
let serialized = fixture.try_to_vec().unwrap();
assert_eq!(
serialized.len(),
fixture.len(),
"Serialized {:?} should match size returned by len()",
fixture
);
}
}

#[test]
fn test_hookable_lifecycle_event_size() {
for fixture in HookableLifecycleEvent::iter() {
let serialized = fixture.try_to_vec().unwrap();
assert_eq!(
serialized.len(),
fixture.len(),
"Serialized {:?} should match size returned by len()",
fixture
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ use crate::{
pub struct AddBlocker {}

impl DataBlob for AddBlocker {
fn get_initial_size() -> usize {
0
}
const BASE_LEN: usize = 0;

fn get_size(&self) -> usize {
0
fn len(&self) -> usize {
Self::BASE_LEN
}
}

Expand All @@ -41,3 +39,15 @@ impl PluginValidation for AddBlocker {
reject!()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_add_blocker_len() {
let add_blocker = AddBlocker {};
let serialized = add_blocker.try_to_vec().unwrap();
assert_eq!(serialized.len(), add_blocker.len());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,26 @@ use borsh::{BorshDeserialize, BorshSerialize};
#[derive(Clone, BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, Default)]
pub struct Attribute {
/// The Key of the attribute.
pub key: String, // 4
pub key: String, // 4 + len
/// The Value of the attribute.
pub value: String, // 4
pub value: String, // 4 + len
}

impl DataBlob for Attribute {
const BASE_LEN: usize = 4 // The length of the Key string
+ 4; // The length of the Value string

fn len(&self) -> usize {
Self::BASE_LEN + self.key.len() + self.value.len()
}
}

/// The Attributes plugin allows the authority to add arbitrary Key-Value pairs to the asset.
#[repr(C)]
#[derive(Clone, BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, Default)]
pub struct Attributes {
/// A vector of Key-Value pairs.
pub attribute_list: Vec<Attribute>, // 4
pub attribute_list: Vec<Attribute>, // 4 + len * Attribute
}

impl Attributes {
Expand All @@ -27,13 +36,56 @@ impl Attributes {
}

impl DataBlob for Attributes {
fn get_initial_size() -> usize {
4
}
const BASE_LEN: usize = 4; // The length of the attribute list

fn get_size(&self) -> usize {
4 // TODO: Implement this.
fn len(&self) -> usize {
Self::BASE_LEN
+ self
.attribute_list
.iter()
.map(|attr| attr.len())
.sum::<usize>()
}
}

impl PluginValidation for Attributes {}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_attribute_len() {
let attribute = Attribute {
key: "test".to_string(),
value: "test".to_string(),
};
let serialized = attribute.try_to_vec().unwrap();
assert_eq!(serialized.len(), attribute.len());
}

#[test]
fn test_attributes_default_len() {
let attributes = Attributes::new();
let serialized = attributes.try_to_vec().unwrap();
assert_eq!(serialized.len(), attributes.len());
}

#[test]
fn test_attributes_len() {
let attributes = Attributes {
attribute_list: vec![
Attribute {
key: "test".to_string(),
value: "test".to_string(),
},
Attribute {
key: "test2".to_string(),
value: "test2".to_string(),
},
],
};
let serialized = attributes.try_to_vec().unwrap();
assert_eq!(serialized.len(), attributes.len());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ use crate::{
pub struct ImmutableMetadata {}

impl DataBlob for ImmutableMetadata {
fn get_initial_size() -> usize {
0
}
const BASE_LEN: usize = 0;

fn get_size(&self) -> usize {
fn len(&self) -> usize {
0
}
}
Expand All @@ -32,3 +30,15 @@ impl PluginValidation for ImmutableMetadata {
reject!()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_immutable_metadata_len() {
let immutable_metadata = ImmutableMetadata {};
let serialized = immutable_metadata.try_to_vec().unwrap();
assert_eq!(serialized.len(), immutable_metadata.len());
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,54 @@
use borsh::{BorshDeserialize, BorshSerialize};

use crate::plugins::PluginValidation;
use crate::{plugins::PluginValidation, state::DataBlob};

/// The master edition plugin allows the creator to specify details on the master edition including max supply, name, and uri.
/// The default authority for this plugin is the creator.
#[repr(C)]
#[derive(Clone, BorshSerialize, BorshDeserialize, Default, Debug, PartialEq, Eq)]
pub struct MasterEdition {
/// The max supply of editions
pub max_supply: Option<u32>,
pub max_supply: Option<u32>, // 1 + optional 4
/// optional master edition name
pub name: Option<String>,
pub name: Option<String>, // 1 + optional 4
/// optional master edition uri
pub uri: Option<String>,
pub uri: Option<String>, // 1 + optional 4
}

impl PluginValidation for MasterEdition {}

impl DataBlob for MasterEdition {
const BASE_LEN: usize = 1 // The max_supply option
+ 1 // The name option
+ 1; // The uri option

fn len(&self) -> usize {
Self::BASE_LEN
+ self.max_supply.map_or(0, |_| 4)
+ self.name.as_ref().map_or(0, |name| 4 + name.len())
+ self.uri.as_ref().map_or(0, |uri| 4 + uri.len())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_master_edition_default_len() {
let master_edition = MasterEdition::default();
let serialized = master_edition.try_to_vec().unwrap();
assert_eq!(serialized.len(), master_edition.len());
}

#[test]
fn test_master_edition_len() {
let master_edition = MasterEdition {
max_supply: Some(100),
name: Some("test".to_string()),
uri: Some("test".to_string()),
};
let serialized = master_edition.try_to_vec().unwrap();
assert_eq!(serialized.len(), master_edition.len());
}
}
Loading
Loading