use crate::error::RuleSetError;
use borsh::{BorshDeserialize, BorshSerialize};
use serde::{Deserialize, Serialize};
use safecoin_program::{entrypoint::ProgramResult, pubkey::Pubkey};
use std::collections::HashMap;
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub struct SeedsVec {
pub seeds: Vec<Vec<u8>>,
}
impl SeedsVec {
pub fn new(seeds: Vec<Vec<u8>>) -> Self {
Self { seeds }
}
}
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub struct ProofInfo {
pub proof: Vec<[u8; 32]>,
}
impl ProofInfo {
pub fn new(proof: Vec<[u8; 32]>) -> Self {
Self { proof }
}
}
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
pub enum PayloadType {
Pubkey(Pubkey),
Seeds(SeedsVec),
MerkleProof(ProofInfo),
Number(u64),
}
#[repr(C)]
#[derive(
BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Default,
)]
pub struct Payload {
map: HashMap<String, PayloadType>,
}
impl Payload {
pub fn new() -> Self {
Self {
map: HashMap::new(),
}
}
pub fn from<const N: usize>(arr: [(String, PayloadType); N]) -> Self {
Self {
map: HashMap::from(arr),
}
}
pub fn insert(&mut self, key: String, value: PayloadType) -> Option<PayloadType> {
self.map.insert(key, value)
}
pub fn try_insert(&mut self, key: String, value: PayloadType) -> ProgramResult {
if self.map.get(&key).is_none() {
self.map.insert(key, value);
Ok(())
} else {
Err(RuleSetError::ValueOccupied.into())
}
}
pub fn get(&self, key: &String) -> Option<&PayloadType> {
self.map.get(key)
}
pub fn get_pubkey(&self, key: &String) -> Option<&Pubkey> {
if let Some(val) = self.map.get(key) {
match val {
PayloadType::Pubkey(pubkey) => Some(pubkey),
_ => None,
}
} else {
None
}
}
pub fn get_seeds(&self, key: &String) -> Option<&SeedsVec> {
if let Some(val) = self.map.get(key) {
match val {
PayloadType::Seeds(seeds) => Some(seeds),
_ => None,
}
} else {
None
}
}
pub fn get_merkle_proof(&self, key: &String) -> Option<&ProofInfo> {
if let Some(val) = self.map.get(key) {
match val {
PayloadType::MerkleProof(proof_info) => Some(proof_info),
_ => None,
}
} else {
None
}
}
pub fn get_amount(&self, key: &String) -> Option<u64> {
if let Some(val) = self.map.get(key) {
match val {
PayloadType::Number(number) => Some(*number),
_ => None,
}
} else {
None
}
}
}