Skip to content

Commit

Permalink
refactor: which to try from trait for doing struct conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
kespinola committed Mar 4, 2024
1 parent 53bce90 commit 99b2ef7
Showing 1 changed file with 152 additions and 102 deletions.
254 changes: 152 additions & 102 deletions plerkle_serialization/src/deserializer/solana.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::convert::TryFrom;

use crate::{
CompiledInnerInstructions as FBCompiledInnerInstructions,
CompiledInstruction as FBCompiledInstruction, InnerInstructions as FBInnerInstructions,
Expand All @@ -19,81 +21,81 @@ pub enum SolanaDeserializerError {

pub type SolanaDeserializeResult<T> = Result<T, SolanaDeserializerError>;

pub fn parse_pubkey(pubkey: Option<&FBPubkey>) -> SolanaDeserializeResult<Pubkey> {
Pubkey::try_from(
pubkey
.ok_or(SolanaDeserializerError::NotFound)?
.0
.as_slice(),
)
.map_err(|_error| SolanaDeserializerError::InvalidFlatBufferKey)
}
pub struct SolanaPubkey(pub Pubkey);

pub fn parse_slice(data: Option<Vector<'_, u8>>) -> SolanaDeserializeResult<&[u8]> {
Ok(data.ok_or(SolanaDeserializerError::NotFound)?.bytes())
impl TryFrom<Option<&FBPubkey>> for SolanaPubkey {
type Error = SolanaDeserializerError;

fn try_from(pubkey: Option<&FBPubkey>) -> SolanaDeserializeResult<Self> {
Ok(Self(
Pubkey::try_from(
pubkey
.ok_or(SolanaDeserializerError::NotFound)?
.0
.as_slice(),
)
.map_err(|_error| SolanaDeserializerError::InvalidFlatBufferKey)?,
))
}
}

pub fn parse_signature(data: Option<&str>) -> SolanaDeserializeResult<Signature> {
data.ok_or(SolanaDeserializerError::NotFound)?
.parse()
.map_err(|_error| SolanaDeserializerError::DeserializationError)
pub struct SolanaDataSlice<'a>(pub &'a [u8]);

impl<'a> TryFrom<Option<Vector<'a, u8>>> for SolanaDataSlice<'a> {
type Error = SolanaDeserializerError;

fn try_from(data: Option<Vector<'a, u8>>) -> SolanaDeserializeResult<Self> {
Ok(Self(data.ok_or(SolanaDeserializerError::NotFound)?.bytes()))
}
}

pub fn parse_account_keys(
public_keys: Option<Vector<'_, FBPubkey>>,
) -> SolanaDeserializeResult<Vec<Pubkey>> {
public_keys
.ok_or(SolanaDeserializerError::NotFound)?
.iter()
.map(|key| {
Pubkey::try_from(key.0.as_slice())
.map_err(|_error| SolanaDeserializerError::InvalidFlatBufferKey)
})
.collect::<SolanaDeserializeResult<Vec<Pubkey>>>()
pub struct SolanaSignature(pub Signature);

impl TryFrom<Option<&str>> for SolanaSignature {
type Error = SolanaDeserializerError;

fn try_from(data: Option<&str>) -> SolanaDeserializeResult<Self> {
Ok(Self(
data.ok_or(SolanaDeserializerError::NotFound)?
.parse::<Signature>()
.map_err(|_error| SolanaDeserializerError::DeserializationError)?,
))
}
}

pub fn parse_compiled_instructions(
vec_cix: Option<Vector<'_, ForwardsUOffset<FBCompiledInstruction>>>,
) -> SolanaDeserializeResult<Vec<CompiledInstruction>> {
let mut message_instructions = vec![];

if let Some(vec_cix) = vec_cix {
for cix in vec_cix {
message_instructions.push(CompiledInstruction {
program_id_index: cix.program_id_index(),
accounts: cix
.accounts()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
data: cix
.data()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
pub struct SolanaPubkeys(pub Vec<Pubkey>);

impl TryFrom<Option<Vector<'_, FBPubkey>>> for SolanaPubkeys {
type Error = SolanaDeserializerError;

fn try_from(public_keys: Option<Vector<'_, FBPubkey>>) -> SolanaDeserializeResult<Self> {
public_keys
.ok_or(SolanaDeserializerError::NotFound)?
.iter()
.map(|key| {
Pubkey::try_from(key.0.as_slice())
.map_err(|_error| SolanaDeserializerError::InvalidFlatBufferKey)
})
}
.collect::<SolanaDeserializeResult<Vec<Pubkey>>>()
.map(SolanaPubkeys)
}

Ok(message_instructions)
}

pub fn parse_compiled_inner_instructions(
vec_ixs: Vector<'_, ForwardsUOffset<FBCompiledInnerInstructions>>,
) -> SolanaDeserializeResult<Vec<InnerInstructions>> {
let mut meta_inner_instructions = vec![];
pub struct SolanaCompiledInstructions(pub Vec<CompiledInstruction>);

for ixs in vec_ixs {
let mut instructions = vec![];
for ix in ixs
.instructions()
.ok_or(SolanaDeserializerError::NotFound)?
{
let cix = ix
.compiled_instruction()
.ok_or(SolanaDeserializerError::NotFound)?;
instructions.push(InnerInstruction {
instruction: CompiledInstruction {
impl<'a> TryFrom<Option<Vector<'a, ForwardsUOffset<FBCompiledInstruction<'a>>>>>
for SolanaCompiledInstructions
{
type Error = SolanaDeserializerError;

fn try_from(
vec_cix: Option<Vector<'a, ForwardsUOffset<FBCompiledInstruction<'a>>>>,
) -> SolanaDeserializeResult<Self> {
let mut message_instructions = vec![];

if let Some(vec_cix) = vec_cix {
for cix in vec_cix {
message_instructions.push(CompiledInstruction {
program_id_index: cix.program_id_index(),
accounts: cix
.accounts()
Expand All @@ -105,52 +107,100 @@ pub fn parse_compiled_inner_instructions(
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
},
stack_height: Some(ix.stack_height() as u32),
});
})
}
}
meta_inner_instructions.push(InnerInstructions {
index: ixs.index(),
instructions,
})
}

Ok(meta_inner_instructions)
Ok(Self(message_instructions))
}
}

pub fn parse_inner_instructions(
vec_ixs: Vector<'_, ForwardsUOffset<FBInnerInstructions>>,
) -> SolanaDeserializeResult<Vec<InnerInstructions>> {
vec_ixs
.iter()
.map(|iixs| {
let instructions = iixs
pub struct SolanaInnerInstructions(pub Vec<InnerInstructions>);

impl<'a> TryFrom<Vector<'_, ForwardsUOffset<FBCompiledInnerInstructions<'a>>>>
for SolanaInnerInstructions
{
type Error = SolanaDeserializerError;

fn try_from(
vec_ixs: Vector<'_, ForwardsUOffset<FBCompiledInnerInstructions<'a>>>,
) -> SolanaDeserializeResult<Self> {
let mut meta_inner_instructions = vec![];

for ixs in vec_ixs {
let mut instructions = vec![];
for ix in ixs
.instructions()
.ok_or(SolanaDeserializerError::NotFound)?
.iter()
.map(|cix| {
Ok(InnerInstruction {
instruction: CompiledInstruction {
program_id_index: cix.program_id_index(),
accounts: cix
.accounts()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
data: cix
.data()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
},
stack_height: Some(0),
{
let cix = ix
.compiled_instruction()
.ok_or(SolanaDeserializerError::NotFound)?;
instructions.push(InnerInstruction {
instruction: CompiledInstruction {
program_id_index: cix.program_id_index(),
accounts: cix
.accounts()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
data: cix
.data()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
},
stack_height: Some(ix.stack_height() as u32),
});
}
meta_inner_instructions.push(InnerInstructions {
index: ixs.index(),
instructions,
})
}

Ok(Self(meta_inner_instructions))
}
}

impl<'a> TryFrom<Vector<'_, ForwardsUOffset<FBInnerInstructions<'a>>>> for SolanaInnerInstructions {
type Error = SolanaDeserializerError;

fn try_from(
vec_ixs: Vector<'_, ForwardsUOffset<FBInnerInstructions>>,
) -> SolanaDeserializeResult<Self> {
vec_ixs
.iter()
.map(|iixs| {
let instructions = iixs
.instructions()
.ok_or(SolanaDeserializerError::NotFound)?
.iter()
.map(|cix| {
Ok(InnerInstruction {
instruction: CompiledInstruction {
program_id_index: cix.program_id_index(),
accounts: cix
.accounts()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
data: cix
.data()
.ok_or(SolanaDeserializerError::NotFound)?
.bytes()
.to_vec(),
},
stack_height: Some(0),
})
})
.collect::<SolanaDeserializeResult<Vec<InnerInstruction>>>()?;
Ok(InnerInstructions {
index: iixs.index(),
instructions,
})
.collect::<SolanaDeserializeResult<Vec<InnerInstruction>>>()?;
Ok(InnerInstructions {
index: iixs.index(),
instructions,
})
})
.collect::<SolanaDeserializeResult<Vec<InnerInstructions>>>()
.collect::<SolanaDeserializeResult<Vec<InnerInstructions>>>()
.map(SolanaInnerInstructions)
}
}

0 comments on commit 99b2ef7

Please sign in to comment.